trace.cpp revision a2dd6cf59962e3a21a47df29b2f243e904839ba7
1/*
2 ** Copyright 2010, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 **     http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
17#if EGL_TRACE
18
19#include <stdarg.h>
20#include <stdlib.h>
21
22#include <EGL/egl.h>
23#include <EGL/eglext.h>
24#include <GLES/gl.h>
25#include <GLES/glext.h>
26
27#include <cutils/log.h>
28
29#include "hooks.h"
30
31// ----------------------------------------------------------------------------
32namespace android {
33// ----------------------------------------------------------------------------
34
35struct GLenumString {
36    GLenum e;
37    const char* s;
38};
39
40#undef GL_ENUM
41#define GL_ENUM(VAL,NAME) {VAL, #NAME},
42
43static GLenumString g_enumnames[] = {
44#include "enums.in"
45};
46#undef GL_ENUM
47
48static int compareGLEnum(const void* a, const void* b) {
49    return ((const GLenumString*) a)->e - ((const GLenumString*) b)->e;
50}
51
52static const char* GLEnumToString(GLenum e) {
53    GLenumString key = {e, ""};
54    const GLenumString* result = (const GLenumString*) bsearch(
55        &key, g_enumnames,
56        sizeof(g_enumnames) / sizeof(g_enumnames[0]),
57        sizeof(g_enumnames[0]), compareGLEnum);
58    if (result) {
59        return result->s;
60    }
61    return NULL;
62}
63
64static GLenumString g_bitfieldNames[] = {
65    {0x00004000, "GL_COLOR_BUFFER_BIT"},
66    {0x00000400, "GL_STENCIL_BUFFER_BIT"},
67    {0x00000100, "GL_DEPTH_BUFFER_BIT"}
68};
69
70
71static void TraceGLShaderSource(GLuint shader, GLsizei count,
72    const GLchar** string, const GLint* length) {
73    LOGD("const char* shaderSrc[] = {");
74    for (GLsizei i = 0; i < count; i++) {
75        const char* comma = i < count-1 ? "," : "";
76        const GLchar* s = string[i];
77        if (length) {
78            GLint len = length[i];
79            LOGD("    \"%*s\"%s", len, s, comma);
80        } else {
81            LOGD("    \"%s\"%s", s, comma);
82        }
83    }
84    LOGD("};");
85    if (length) {
86        LOGD("const GLint* shaderLength[] = {");
87        for (GLsizei i = 0; i < count; i++) {
88            const char* comma = i < count-1 ? "," : "";
89            GLint len = length[i];
90            LOGD("    \"%d\"%s", len, comma);
91        }
92        LOGD("};");
93        LOGD("glShaderSource(%u, %u, shaderSrc, shaderLength);",
94            shader, count);
95    } else {
96        LOGD("glShaderSource(%u, %u, shaderSrc, (const GLint*) 0);",
97            shader, count);
98    }
99}
100
101static void TraceGL(const char* name, int numArgs, ...) {
102    va_list argp;
103    va_start(argp, numArgs);
104    if (strcmp(name, "glShaderSource") == 0) {
105        va_arg(argp, const char*);
106        GLuint shader = va_arg(argp, GLuint);
107        va_arg(argp, const char*);
108        GLsizei count = va_arg(argp, GLsizei);
109        va_arg(argp, const char*);
110        const GLchar** string = (const GLchar**) va_arg(argp, void*);
111        va_arg(argp, const char*);
112        const GLint* length = (const GLint*) va_arg(argp, void*);
113        TraceGLShaderSource(shader, count, string, length);
114        va_end(argp);
115        return;
116    }
117    const int lineSize = 500;
118    char line[lineSize];
119    int line_index = 0;
120    #define APPEND(...) \
121        line_index += snprintf(line + line_index, lineSize-line_index, __VA_ARGS__);
122    APPEND("%s(", name);
123    for (int i = 0; i < numArgs; i++) {
124        if (i > 0) {
125            APPEND(", ");
126        }
127        const char* type = va_arg(argp, const char*);
128        bool isPtr = type[strlen(type)-1] == '*'
129            || strcmp(type, "GLeglImageOES") == 0;
130        if (isPtr) {
131            const void* arg = va_arg(argp, const void*);
132            APPEND("(%s) 0x%08x", type, (size_t) arg);
133        } else if (strcmp(type, "GLbitfield") == 0) {
134            size_t arg = va_arg(argp, size_t);
135            bool first = true;
136            for (size_t i = 0; i < sizeof(g_bitfieldNames) / sizeof(g_bitfieldNames[0]); i++) {
137                const GLenumString* b = &g_bitfieldNames[i];
138                if (b->e & arg) {
139                    if (first) {
140                        first = false;
141                    } else {
142                        APPEND(" | ");
143                    }
144                    APPEND("%s", b->s);
145                    arg &= ~b->e;
146                }
147            }
148            if (first || arg != 0) {
149                if (!first) {
150                    APPEND(" | ");
151                }
152                APPEND("0x%08x", arg);
153            }
154        } else if (strcmp(type, "GLboolean") == 0) {
155            int arg = va_arg(argp, int);
156            APPEND("%s", arg ? "GL_TRUE" : "GL_FALSE");
157        } else if (strcmp(type, "GLclampf") == 0) {
158            double arg = va_arg(argp, double);
159            APPEND("%g", arg);
160        } else if (strcmp(type, "GLenum") == 0) {
161            GLenum arg = va_arg(argp, int);
162            const char* s = GLEnumToString(arg);
163            if (s) {
164                APPEND("%s", s);
165            } else {
166                APPEND("0x%x", arg);
167            }
168        } else if (strcmp(type, "GLfixed") == 0) {
169            int arg = va_arg(argp, int);
170            APPEND("0x%08x", arg);
171        } else if (strcmp(type, "GLfloat") == 0) {
172            double arg = va_arg(argp, double);
173            APPEND("%g", arg);
174        } else if (strcmp(type, "GLint") == 0) {
175            int arg = va_arg(argp, int);
176            const char* s = NULL;
177            if (strcmp(name, "glTexParameteri") == 0) {
178                s = GLEnumToString(arg);
179            }
180            if (s) {
181                APPEND("%s", s);
182            } else {
183                APPEND("%d", arg);
184            }
185        } else if (strcmp(type, "GLintptr") == 0) {
186            int arg = va_arg(argp, unsigned int);
187            APPEND("%u", arg);
188        } else if (strcmp(type, "GLsizei") == 0) {
189            int arg = va_arg(argp, size_t);
190            APPEND("%u", arg);
191        } else if (strcmp(type, "GLsizeiptr") == 0) {
192            int arg = va_arg(argp, size_t);
193            APPEND("%u", arg);
194        } else if (strcmp(type, "GLuint") == 0) {
195            int arg = va_arg(argp, unsigned int);
196            APPEND("%u", arg);
197        } else {
198            APPEND("/* ??? %s */", type);
199            break;
200        }
201    }
202    APPEND(");");
203    line[lineSize-1] = '\0';
204    LOGD("%s", line);
205    va_end(argp);
206}
207
208#undef TRACE_GL_VOID
209#undef TRACE_GL
210
211#define TRACE_GL_VOID(_api, _args, _argList, ...)                         \
212static void Tracing_ ## _api _args {                                      \
213    TraceGL(#_api, __VA_ARGS__);                                          \
214    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
215    _c->_api _argList;                                                    \
216}
217
218#define TRACE_GL(_type, _api, _args, _argList, ...)                       \
219static _type Tracing_ ## _api _args {                                     \
220    TraceGL(#_api, __VA_ARGS__);                                          \
221    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
222    return _c->_api _argList;                                             \
223}
224
225extern "C" {
226#include "../trace.in"
227}
228#undef TRACE_GL_VOID
229#undef TRACE_GL
230
231#define GL_ENTRY(_r, _api, ...) Tracing_ ## _api,
232
233EGLAPI gl_hooks_t gHooksTrace = {
234    {
235        #include "entries.in"
236    },
237    {
238        {0}
239    }
240};
241#undef GL_ENTRY
242
243// ----------------------------------------------------------------------------
244}; // namespace android
245// ----------------------------------------------------------------------------
246
247#endif // EGL_TRACE
248