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

Commit d4d0fb96 authored by Jack Palevich's avatar Jack Palevich
Browse files

OpenGL tracing.

Enable with:

adb shell setprop debug.egl.trace 1

Change-Id: Icfbc795f5260141510975228e72234e9aab56a85
parent f0a896b3
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ include $(CLEAR_VARS)

LOCAL_SRC_FILES:= 	       \
	EGL/egl.cpp 	       \
	EGL/trace.cpp              \
	EGL/getProcAddress.cpp.arm \
	EGL/hooks.cpp 	       \
	EGL/Loader.cpp 	       \
@@ -33,6 +34,7 @@ endif
LOCAL_CFLAGS += -DLOG_TAG=\"libEGL\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
LOCAL_CFLAGS += -fvisibility=hidden
LOCAL_CFLAGS += -DEGL_TRACE=1

ifeq ($(TARGET_BOARD_PLATFORM),msm7k)
LOCAL_CFLAGS += -DADRENO130=1
+73 −6
Original line number Diff line number Diff line
@@ -285,6 +285,58 @@ EGLAPI gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS];
EGLAPI gl_hooks_t gHooksNoContext;
EGLAPI pthread_key_t gGLWrapperKey = -1;

#if EGL_TRACE

EGLAPI pthread_key_t gGLTraceKey = -1;

// ----------------------------------------------------------------------------

static int gEGLTraceLevel;
static int gEGLApplicationTraceLevel;
extern EGLAPI gl_hooks_t gHooksTrace;

static inline void setGlTraceThreadSpecific(gl_hooks_t const *value) {
    pthread_setspecific(gGLTraceKey, value);
}

gl_hooks_t const* getGLTraceThreadSpecific() {
    return static_cast<gl_hooks_t*>(pthread_getspecific(gGLTraceKey));
}

static void initEglTraceLevel() {
    char value[PROPERTY_VALUE_MAX];
    property_get("debug.egl.trace", value, "0");
    int propertyLevel = atoi(value);
    int applicationLevel = gEGLApplicationTraceLevel;
    gEGLTraceLevel = propertyLevel > applicationLevel ? propertyLevel : applicationLevel;
}

static void setGLHooksThreadSpecific(gl_hooks_t const *value) {
    if (gEGLTraceLevel > 0) {
        setGlTraceThreadSpecific(value);
        setGlThreadSpecific(&gHooksTrace);
    } else {
        setGlThreadSpecific(value);
    }
}

/*
 * Global entry point to allow applications to modify their own trace level.
 * The effective trace level is the max of this level and the value of debug.egl.trace.
 */
extern "C"
void setGLTraceLevel(int level) {
    gEGLApplicationTraceLevel = level;
}

#else

static inline void setGLHooksThreadSpecific(gl_hooks_t const *value) {
    setGlThreadSpecific(value);
}

#endif

// ----------------------------------------------------------------------------

static __attribute__((noinline))
@@ -458,6 +510,10 @@ static void early_egl_init(void)
{
#if !USE_FAST_TLS_KEY
    pthread_key_create(&gGLWrapperKey, NULL);
#endif
#if EGL_TRACE
    pthread_key_create(&gGLTraceKey, NULL);
    initEglTraceLevel();
#endif
    uint32_t addr = (uint32_t)((void*)gl_no_context);
    android_memset32(
@@ -465,7 +521,7 @@ static void early_egl_init(void)
            addr, 
            sizeof(gHooksNoContext));

    setGlThreadSpecific(&gHooksNoContext);
    setGLHooksThreadSpecific(&gHooksNoContext);
}

static pthread_once_t once_control = PTHREAD_ONCE_INIT;
@@ -678,7 +734,15 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
        return EGL_TRUE;
    }

    setGlThreadSpecific(&gHooksNoContext);
#if EGL_TRACE

    // Called both at early_init time and at this time. (Early_init is pre-zygote, so
    // the information from that call may be stale.)
    initEglTraceLevel();

#endif

    setGLHooksThreadSpecific(&gHooksNoContext);

    // initialize each EGL and
    // build our own extension string first, based on the extension we know
@@ -1238,11 +1302,11 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,

        // cur_c has to be valid here (but could be terminated)
        if (ctx != EGL_NO_CONTEXT) {
            setGlThreadSpecific(c->cnx->hooks[c->version]);
            setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
            setContext(ctx);
            _c.acquire();
        } else {
            setGlThreadSpecific(&gHooksNoContext);
            setGLHooksThreadSpecific(&gHooksNoContext);
            setContext(EGL_NO_CONTEXT);
        }
        _cur_c.release();
@@ -1434,6 +1498,9 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
                    // Extensions are independent of the bound context
                    cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] =
                    cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] =
#if EGL_TRACE
                    gHooksTrace.ext.extensions[slot] =
#endif
                            cnx->egl.eglGetProcAddress(procname);
                }
            }
+247 −0
Original line number Diff line number Diff line
/*
 ** Copyright 2010, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 ** You may obtain a copy of the License at
 **
 **     http://www.apache.org/licenses/LICENSE-2.0
 **
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */

#if EGL_TRACE

#include <stdarg.h>
#include <stdlib.h>

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES/gl.h>
#include <GLES/glext.h>

#include <cutils/log.h>

#include "hooks.h"

// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------

struct GLenumString {
    GLenum e;
    const char* s;
};

#undef GL_ENUM
#define GL_ENUM(VAL,NAME) {VAL, #NAME},

static GLenumString g_enumnames[] = {
#include "enums.in"
};
#undef GL_ENUM

static int compareGLEnum(const void* a, const void* b) {
    return ((const GLenumString*) a)->e - ((const GLenumString*) b)->e;
}

static const char* GLEnumToString(GLenum e) {
    GLenumString key = {e, ""};
    const GLenumString* result = (const GLenumString*) bsearch(
        &key, g_enumnames,
        sizeof(g_enumnames) / sizeof(g_enumnames[0]),
        sizeof(g_enumnames[0]), compareGLEnum);
    if (result) {
        return result->s;
    }
    return NULL;
}

static GLenumString g_bitfieldNames[] = {
    {0x00004000, "GL_COLOR_BUFFER_BIT"},
    {0x00000400, "GL_STENCIL_BUFFER_BIT"},
    {0x00000100, "GL_DEPTH_BUFFER_BIT"}
};


static void TraceGLShaderSource(GLuint shader, GLsizei count,
    const GLchar** string, const GLint* length) {
    LOGD("const char* shaderSrc[] = {");
    for (GLsizei i = 0; i < count; i++) {
        const char* comma = i < count-1 ? "," : "";
        const GLchar* s = string[i];
        if (length) {
            GLint len = length[i];
            LOGD("    \"%*s\"%s", len, s, comma);
        } else {
            LOGD("    \"%s\"%s", s, comma);
        }
    }
    LOGD("};");
    if (length) {
        LOGD("const GLint* shaderLength[] = {");
        for (GLsizei i = 0; i < count; i++) {
            const char* comma = i < count-1 ? "," : "";
            GLint len = length[i];
            LOGD("    \"%d\"%s", len, comma);
        }
        LOGD("};");
        LOGD("glShaderSource(%u, %u, shaderSrc, shaderLength);",
            shader, count);
    } else {
        LOGD("glShaderSource(%u, %u, shaderSrc, (const GLint*) 0);",
            shader, count);
    }
}

static void TraceGL(const char* name, int numArgs, ...) {
    va_list argp;
    va_start(argp, numArgs);
    if (strcmp(name, "glShaderSource") == 0) {
        va_arg(argp, const char*);
        GLuint shader = va_arg(argp, GLuint);
        va_arg(argp, const char*);
        GLsizei count = va_arg(argp, GLsizei);
        va_arg(argp, const char*);
        const GLchar** string = (const GLchar**) va_arg(argp, void*);
        va_arg(argp, const char*);
        const GLint* length = (const GLint*) va_arg(argp, void*);
        TraceGLShaderSource(shader, count, string, length);
        va_end(argp);
        return;
    }
    const int lineSize = 500;
    char line[lineSize];
    int line_index = 0;
    #define APPEND(...) \
        line_index += snprintf(line + line_index, lineSize-line_index, __VA_ARGS__);
    APPEND("%s(", name);
    for (int i = 0; i < numArgs; i++) {
        if (i > 0) {
            APPEND(", ");
        }
        const char* type = va_arg(argp, const char*);
        bool isPtr = type[strlen(type)-1] == '*'
            || strcmp(type, "GLeglImageOES") == 0;
        if (isPtr) {
            const void* arg = va_arg(argp, const void*);
            APPEND("(%s) 0x%08x", type, (size_t) arg);
        } else if (strcmp(type, "GLbitfield") == 0) {
            size_t arg = va_arg(argp, size_t);
            bool first = true;
            for (size_t i = 0; i < sizeof(g_bitfieldNames) / sizeof(g_bitfieldNames[0]); i++) {
                const GLenumString* b = &g_bitfieldNames[i];
                if (b->e & arg) {
                    if (first) {
                        first = false;
                    } else {
                        APPEND(" | ");
                    }
                    APPEND("%s", b->s);
                    arg &= ~b->e;
                }
            }
            if (first || arg != 0) {
                if (!first) {
                    APPEND(" | ");
                }
                APPEND("0x%08x", arg);
            }
        } else if (strcmp(type, "GLboolean") == 0) {
            int arg = va_arg(argp, int);
            APPEND("%s", arg ? "GL_TRUE" : "GL_FALSE");
        } else if (strcmp(type, "GLclampf") == 0) {
            double arg = va_arg(argp, double);
            APPEND("%g", arg);
        } else if (strcmp(type, "GLenum") == 0) {
            GLenum arg = va_arg(argp, int);
            const char* s = GLEnumToString(arg);
            if (s) {
                APPEND("%s", s);
            } else {
                APPEND("0x%x", arg);
            }
        } else if (strcmp(type, "GLfixed") == 0) {
            int arg = va_arg(argp, int);
            APPEND("0x%08x", arg);
        } else if (strcmp(type, "GLfloat") == 0) {
            double arg = va_arg(argp, double);
            APPEND("%g", arg);
        } else if (strcmp(type, "GLint") == 0) {
            int arg = va_arg(argp, int);
            const char* s = NULL;
            if (strcmp(name, "glTexParameteri") == 0) {
                s = GLEnumToString(arg);
            }
            if (s) {
                APPEND("%s", s);
            } else {
                APPEND("%d", arg);
            }
        } else if (strcmp(type, "GLintptr") == 0) {
            int arg = va_arg(argp, unsigned int);
            APPEND("%u", arg);
        } else if (strcmp(type, "GLsizei") == 0) {
            int arg = va_arg(argp, size_t);
            APPEND("%u", arg);
        } else if (strcmp(type, "GLsizeiptr") == 0) {
            int arg = va_arg(argp, size_t);
            APPEND("%u", arg);
        } else if (strcmp(type, "GLuint") == 0) {
            int arg = va_arg(argp, unsigned int);
            APPEND("%u", arg);
        } else {
            APPEND("/* ??? %s */", type);
            break;
        }
    }
    APPEND(");");
    line[lineSize-1] = '\0';
    LOGD("%s", line);
    va_end(argp);
}

#undef TRACE_GL_VOID
#undef TRACE_GL

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

#define TRACE_GL(_type, _api, _args, _argList, ...)                       \
static _type Tracing_ ## _api _args {                                     \
    TraceGL(#_api, __VA_ARGS__);                                          \
    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, ...) Tracing_ ## _api,

EGLAPI gl_hooks_t gHooksTrace = {
    {
        #include "entries.in"
    },
    {
        {0}
    }
};
#undef GL_ENTRY

// ----------------------------------------------------------------------------
}; // namespace android
// ----------------------------------------------------------------------------

#endif // EGL_TRACE

opengl/libs/enums.in

0 → 100644
+594 −0

File added.

Preview size limit exceeded, changes collapsed.

+5 −0
Original line number Diff line number Diff line
@@ -141,6 +141,11 @@ static gl_hooks_t const* getGlThreadSpecific() {

#endif

#if EGL_TRACE

extern gl_hooks_t const* getGLTraceThreadSpecific();

#endif

// ----------------------------------------------------------------------------
}; // namespace android
Loading