Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 16928bfe authored by Romain Guy's avatar Romain Guy
Browse files

Add runtime debugging capabilities to OpenGL

The shell property debug.egl.trace can now be set to:

0
  disables tracing
1
  logs all GL calls
error
  checks glGetError after every GL call, logs a stack trace on error
systrace
  logs each GL call to systrace

Change-Id: I34a2a2d4e19c373fd9eaa1b0cd93e67c87378996
parent 7f79a2bd
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -67,6 +67,11 @@
// function body.
#define ATRACE_CALL() android::ScopedTrace ___tracer(ATRACE_TAG, __FUNCTION__)

// ATRACE_NAME traces the beginning and end of the current function.  To trace
// the correct start and end times this macro should be the first line of the
// function body.
#define ATRACE_NAME(name) android::ScopedTrace ___tracer(ATRACE_TAG, name)

// ATRACE_INT traces a named integer value.  This can be used to track how the
// value changes over time in a trace.
#define ATRACE_INT(name, value) android::Tracer::traceCounter(ATRACE_TAG, name, value)
+35 −4
Original line number Diff line number Diff line
@@ -62,12 +62,18 @@ EGLAPI pthread_key_t gGLTraceKey = -1;
// ----------------------------------------------------------------------------

/**
 * There are two different tracing methods:
 * 1. libs/EGL/trace.cpp: Traces all functions to logcat.
 * There are three different tracing methods:
 * 1. libs/EGL/trace.cpp: Traces all functions to systrace.
 *    To enable:
 *      - set system property "debug.egl.trace" to "systrace" to trace all apps.
 * 2. libs/EGL/trace.cpp: Logs a stack trace for GL errors after each function call.
 *    To enable:
 *      - set system property "debug.egl.trace" to "error" to trace all apps.
 * 3. libs/EGL/trace.cpp: Traces all functions to logcat.
 *    To enable:
 *      - set system property "debug.egl.trace" to 1 to trace all apps.
 *      - or call setGLTraceLevel(1) from an app to enable tracing for that app.
 * 2. libs/GLES_trace: Traces all functions via protobuf to host.
 * 4. libs/GLES_trace: Traces all functions via protobuf to host.
 *    To enable:
 *        - set system property "debug.egl.debug_proc" to the application name.
 *      - or call setGLDebugLevel(1) from the app.
@@ -75,10 +81,15 @@ EGLAPI pthread_key_t gGLTraceKey = -1;
static int sEGLTraceLevel;
static int sEGLApplicationTraceLevel;

static bool sEGLSystraceEnabled;
static bool sEGLGetErrorEnabled;

int gEGLDebugLevel;
static int sEGLApplicationDebugLevel;

extern gl_hooks_t gHooksTrace;
extern gl_hooks_t gHooksSystrace;
extern gl_hooks_t gHooksErrorTrace;

static inline void setGlTraceThreadSpecific(gl_hooks_t const *value) {
    pthread_setspecific(gGLTraceKey, value);
@@ -91,6 +102,20 @@ gl_hooks_t const* getGLTraceThreadSpecific() {
void initEglTraceLevel() {
    char value[PROPERTY_VALUE_MAX];
    property_get("debug.egl.trace", value, "0");

    sEGLGetErrorEnabled = !strcasecmp(value, "error");
    if (sEGLGetErrorEnabled) {
        sEGLSystraceEnabled = false;
        sEGLTraceLevel = 0;
        return;
    }

    sEGLSystraceEnabled = !strcasecmp(value, "systrace");
    if (sEGLSystraceEnabled) {
        sEGLTraceLevel = 0;
        return;
    }

    int propertyLevel = atoi(value);
    int applicationLevel = sEGLApplicationTraceLevel;
    sEGLTraceLevel = propertyLevel > applicationLevel ? propertyLevel : applicationLevel;
@@ -125,7 +150,13 @@ void initEglDebugLevel() {
}

void setGLHooksThreadSpecific(gl_hooks_t const *value) {
    if (sEGLTraceLevel > 0) {
    if (sEGLGetErrorEnabled) {
        setGlTraceThreadSpecific(value);
        setGlThreadSpecific(&gHooksErrorTrace);
    } else if (sEGLSystraceEnabled) {
        setGlTraceThreadSpecific(value);
        setGlThreadSpecific(&gHooksSystrace);
    } else if (sEGLTraceLevel > 0) {
        setGlTraceThreadSpecific(value);
        setGlThreadSpecific(&gHooksTrace);
    } else if (gEGLDebugLevel > 0 && value != &gHooksNoContext) {
+102 −1
Original line number Diff line number Diff line
@@ -26,6 +26,11 @@

#include <cutils/log.h>

#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <utils/Trace.h>

#include <utils/CallStack.h>

#include "egl_tls.h"
#include "hooks.h"

@@ -314,6 +319,10 @@ static void TraceGL(const char* name, int numArgs, ...) {
    va_end(argp);
}

///////////////////////////////////////////////////////////////////////////
// Log trace
///////////////////////////////////////////////////////////////////////////

#undef TRACE_GL_VOID
#undef TRACE_GL

@@ -349,7 +358,6 @@ EGLAPI gl_hooks_t gHooksTrace = {
};
#undef GL_ENTRY


#undef TRACE_GL_VOID
#undef TRACE_GL

@@ -372,6 +380,99 @@ extern "C" {
#include "../debug.in"
}

///////////////////////////////////////////////////////////////////////////
// Systrace
///////////////////////////////////////////////////////////////////////////

#undef TRACE_GL_VOID
#undef TRACE_GL

#define TRACE_GL_VOID(_api, _args, _argList, ...)                         \
static void Systrace_ ## _api _args {                                     \
    ATRACE_NAME(#_api);                                                   \
    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
    _c->_api _argList;                                                    \
}

#define TRACE_GL(_type, _api, _args, _argList, ...)                       \
static _type Systrace_ ## _api _args {                                    \
    ATRACE_NAME(#_api);                                                   \
    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
    return _c->_api _argList;                                             \
}

extern "C" {
#include "../trace.in"
}

#undef TRACE_GL_VOID
#undef TRACE_GL

#define GL_ENTRY(_r, _api, ...) Systrace_ ## _api,
EGLAPI gl_hooks_t gHooksSystrace = {
    {
        #include "entries.in"
    },
    {
        {0}
    }
};
#undef GL_ENTRY

///////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////

#undef TRACE_GL_VOID
#undef TRACE_GL

#define CHECK_ERROR(_c, _api)                                             \
    GLenum status = GL_NO_ERROR;                                          \
    bool error = false;                                                   \
    while ((status = _c->glGetError()) != GL_NO_ERROR) {                  \
        ALOGD("[" #_api "] 0x%x", status);                                \
        error = true;                                                     \
    }                                                                     \
    if (error) {                                                          \
        CallStack s;                                                      \
        s.update();                                                       \
        s.dump("glGetError:" #_api);                                      \
    }                                                                     \

#define TRACE_GL_VOID(_api, _args, _argList, ...)                         \
static void ErrorTrace_ ## _api _args {                                   \
    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
    _c->_api _argList;                                                    \
    CHECK_ERROR(_c, _api);                                                \
}

#define TRACE_GL(_type, _api, _args, _argList, ...)                       \
static _type ErrorTrace_ ## _api _args {                                  \
    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
    _type _r = _c->_api _argList;                                         \
    CHECK_ERROR(_c, _api);                                                \
    return _r;                                                            \
}

extern "C" {
#include "../trace.in"
}

#undef TRACE_GL_VOID
#undef TRACE_GL

#define GL_ENTRY(_r, _api, ...) ErrorTrace_ ## _api,
EGLAPI gl_hooks_t gHooksErrorTrace = {
    {
        #include "entries.in"
    },
    {
        {0}
    }
};
#undef GL_ENTRY
#undef CHECK_ERROR

#undef TRACE_GL_VOID
#undef TRACE_GL

+0 −37
Original line number Diff line number Diff line
@@ -26,11 +26,6 @@
#include <cutils/log.h>
#include <cutils/properties.h>

#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <utils/Trace.h>

#include <utils/CallStack.h>

#include "hooks.h"
#include "egl_impl.h"

@@ -44,10 +39,6 @@ using namespace android;
#undef CALL_GL_API
#undef CALL_GL_API_RETURN

#define DEBUG_CALL_GL_API 0
#define DEBUG_PRINT_CALL_STACK_ON_ERROR 0
#define SYSTRACE_CALL_GL_API 0

#if USE_FAST_TLS_KEY

    #ifdef HAVE_ARM_TLS_REGISTER
@@ -83,38 +74,10 @@ using namespace android;

    #define API_ENTRY(_api) _api

#if DEBUG_CALL_GL_API

    #define CALL_GL_API(_api, ...)                                       \
        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
        _c->_api(__VA_ARGS__); \
        GLenum status = GL_NO_ERROR; \
        bool error = false; \
        while ((status = glGetError()) != GL_NO_ERROR) { \
            ALOGD("[" #_api "] 0x%x", status); \
            error = true; \
        } \
        if (DEBUG_PRINT_CALL_STACK_ON_ERROR && error) { \
            CallStack s; \
            s.update(); \
            s.dump("glGetError:" #_api); \
        }

#elif SYSTRACE_CALL_GL_API

    #define CALL_GL_API(_api, ...)                                       \
        ATRACE_CALL();                                                   \
        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
        _c->_api(__VA_ARGS__);

#else

    #define CALL_GL_API(_api, ...)                                       \
        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
        _c->_api(__VA_ARGS__);

#endif

    #define CALL_GL_API_RETURN(_api, ...)                                \
        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
        return _c->_api(__VA_ARGS__)