• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "egl_tls.h"
30 #include "hooks.h"
31 
32 // ----------------------------------------------------------------------------
33 namespace android {
34 // ----------------------------------------------------------------------------
35 
36 struct GLenumString {
37     GLenum e;
38     const char* s;
39 };
40 
41 #undef GL_ENUM
42 #define GL_ENUM(VAL,NAME) {VAL, #NAME},
43 
44 static GLenumString g_enumnames[] = {
45 #include "enums.in"
46 };
47 #undef GL_ENUM
48 
compareGLEnum(const void * a,const void * b)49 static int compareGLEnum(const void* a, const void* b) {
50     return ((const GLenumString*) a)->e - ((const GLenumString*) b)->e;
51 }
52 
GLEnumToString(GLenum e)53 static const char* GLEnumToString(GLenum e) {
54     GLenumString key = {e, ""};
55     const GLenumString* result = (const GLenumString*) bsearch(
56         &key, g_enumnames,
57         sizeof(g_enumnames) / sizeof(g_enumnames[0]),
58         sizeof(g_enumnames[0]), compareGLEnum);
59     if (result) {
60         return result->s;
61     }
62     return NULL;
63 }
64 
GLbooleanToString(GLboolean arg)65 static const char* GLbooleanToString(GLboolean arg) {
66     return arg ? "GL_TRUE" : "GL_FALSE";
67 }
68 
69 static GLenumString g_bitfieldNames[] = {
70     {0x00004000, "GL_COLOR_BUFFER_BIT"},
71     {0x00000400, "GL_STENCIL_BUFFER_BIT"},
72     {0x00000100, "GL_DEPTH_BUFFER_BIT"}
73 };
74 
75 class StringBuilder {
76     static const int lineSize = 500;
77     char line[lineSize];
78     int line_index;
79 public:
StringBuilder()80     StringBuilder() {
81         line_index = 0;
82         line[0] = '\0';
83     }
append(const char * fmt,...)84     void append(const char* fmt, ...) {
85         va_list argp;
86         va_start(argp, fmt);
87         line_index += vsnprintf(line + line_index, lineSize-line_index, fmt, argp);
88         va_end(argp);
89     }
getString()90     const char* getString() {
91         line_index = 0;
92         line[lineSize-1] = '\0';
93         return line;
94     }
95 };
96 
97 
TraceGLShaderSource(GLuint shader,GLsizei count,const GLchar ** string,const GLint * length)98 static void TraceGLShaderSource(GLuint shader, GLsizei count,
99     const GLchar** string, const GLint* length) {
100     LOGD("const char* shaderSrc[] = {");
101     for (GLsizei i = 0; i < count; i++) {
102         const char* comma = i < count-1 ? "," : "";
103         const GLchar* s = string[i];
104         if (length) {
105             GLint len = length[i];
106             LOGD("    \"%*s\"%s", len, s, comma);
107         } else {
108             LOGD("    \"%s\"%s", s, comma);
109         }
110     }
111     LOGD("};");
112     if (length) {
113         LOGD("const GLint* shaderLength[] = {");
114         for (GLsizei i = 0; i < count; i++) {
115             const char* comma = i < count-1 ? "," : "";
116             GLint len = length[i];
117             LOGD("    \"%d\"%s", len, comma);
118         }
119         LOGD("};");
120         LOGD("glShaderSource(%u, %u, shaderSrc, shaderLength);",
121             shader, count);
122     } else {
123         LOGD("glShaderSource(%u, %u, shaderSrc, (const GLint*) 0);",
124             shader, count);
125     }
126 }
127 
TraceValue(int elementCount,char type,GLsizei chunkCount,GLsizei chunkSize,const void * value)128 static void TraceValue(int elementCount, char type,
129         GLsizei chunkCount, GLsizei chunkSize, const void* value) {
130     StringBuilder stringBuilder;
131     GLsizei count = chunkCount * chunkSize;
132     bool isFloat = type == 'f';
133     const char* typeString = isFloat ? "GLfloat" : "GLint";
134     LOGD("const %s value[] = {", typeString);
135     for (GLsizei i = 0; i < count; i++) {
136         StringBuilder builder;
137         builder.append("    ");
138         for (int e = 0; e < elementCount; e++) {
139             const char* comma = ", ";
140             if (e == elementCount-1) {
141                 if (i == count - 1) {
142                     comma = "";
143                 } else {
144                     comma = ",";
145                 }
146             }
147             if (isFloat) {
148                 builder.append("%g%s", * (GLfloat*) value, comma);
149                 value = (void*) (((GLfloat*) value) + 1);
150             } else {
151                 builder.append("%d%s", * (GLint*) value, comma);
152                 value = (void*) (((GLint*) value) + 1);
153             }
154         }
155         LOGD("%s", builder.getString());
156         if (chunkSize > 1 && i < count-1
157                 && (i % chunkSize) == (chunkSize-1)) {
158             LOGD("%s", ""); // Print a blank line.
159         }
160     }
161     LOGD("};");
162 }
163 
TraceUniformv(int elementCount,char type,GLuint location,GLsizei count,const void * value)164 static void TraceUniformv(int elementCount, char type,
165         GLuint location, GLsizei count, const void* value) {
166     TraceValue(elementCount, type, count, 1, value);
167     LOGD("glUniform%d%c(%u, %u, value);", elementCount, type, location, count);
168 }
169 
TraceUniformMatrix(int matrixSideLength,GLuint location,GLsizei count,GLboolean transpose,const void * value)170 static void TraceUniformMatrix(int matrixSideLength,
171         GLuint location, GLsizei count, GLboolean transpose, const void* value) {
172     TraceValue(matrixSideLength, 'f', count, matrixSideLength, value);
173     LOGD("glUniformMatrix%dfv(%u, %u, %s, value);", matrixSideLength, location, count,
174             GLbooleanToString(transpose));
175 }
176 
TraceGL(const char * name,int numArgs,...)177 static void TraceGL(const char* name, int numArgs, ...) {
178     va_list argp;
179     va_start(argp, numArgs);
180     int nameLen = strlen(name);
181 
182     // glShaderSource
183     if (nameLen == 14 && strcmp(name, "glShaderSource") == 0) {
184         va_arg(argp, const char*);
185         GLuint shader = va_arg(argp, GLuint);
186         va_arg(argp, const char*);
187         GLsizei count = va_arg(argp, GLsizei);
188         va_arg(argp, const char*);
189         const GLchar** string = (const GLchar**) va_arg(argp, void*);
190         va_arg(argp, const char*);
191         const GLint* length = (const GLint*) va_arg(argp, void*);
192         va_end(argp);
193         TraceGLShaderSource(shader, count, string, length);
194         return;
195     }
196 
197     // glUniformXXv
198 
199     if (nameLen == 12 && strncmp(name, "glUniform", 9) == 0 && name[11] == 'v') {
200         int elementCount = name[9] - '0'; // 1..4
201         char type = name[10]; // 'f' or 'i'
202         va_arg(argp, const char*);
203         GLuint location = va_arg(argp, GLuint);
204         va_arg(argp, const char*);
205         GLsizei count = va_arg(argp, GLsizei);
206         va_arg(argp, const char*);
207         const void* value = (const void*) va_arg(argp, void*);
208         va_end(argp);
209         TraceUniformv(elementCount, type, location, count, value);
210         return;
211     }
212 
213     // glUniformMatrixXfv
214 
215     if (nameLen == 18 && strncmp(name, "glUniformMatrix", 15) == 0
216             && name[16] == 'f' && name[17] == 'v') {
217         int matrixSideLength = name[15] - '0'; // 2..4
218         va_arg(argp, const char*);
219         GLuint location = va_arg(argp, GLuint);
220         va_arg(argp, const char*);
221         GLsizei count = va_arg(argp, GLsizei);
222         va_arg(argp, const char*);
223         GLboolean transpose = (GLboolean) va_arg(argp, int);
224         va_arg(argp, const char*);
225         const void* value = (const void*) va_arg(argp, void*);
226         va_end(argp);
227         TraceUniformMatrix(matrixSideLength, location, count, transpose, value);
228         return;
229     }
230 
231     StringBuilder builder;
232     builder.append("%s(", name);
233     for (int i = 0; i < numArgs; i++) {
234         if (i > 0) {
235             builder.append(", ");
236         }
237         const char* type = va_arg(argp, const char*);
238         bool isPtr = type[strlen(type)-1] == '*'
239             || strcmp(type, "GLeglImageOES") == 0;
240         if (isPtr) {
241             const void* arg = va_arg(argp, const void*);
242             builder.append("(%s) 0x%08x", type, (size_t) arg);
243         } else if (strcmp(type, "GLbitfield") == 0) {
244             size_t arg = va_arg(argp, size_t);
245             bool first = true;
246             for (size_t i = 0; i < sizeof(g_bitfieldNames) / sizeof(g_bitfieldNames[0]); i++) {
247                 const GLenumString* b = &g_bitfieldNames[i];
248                 if (b->e & arg) {
249                     if (first) {
250                         first = false;
251                     } else {
252                         builder.append(" | ");
253                     }
254                     builder.append("%s", b->s);
255                     arg &= ~b->e;
256                 }
257             }
258             if (first || arg != 0) {
259                 if (!first) {
260                     builder.append(" | ");
261                 }
262                 builder.append("0x%08x", arg);
263             }
264         } else if (strcmp(type, "GLboolean") == 0) {
265             GLboolean arg = va_arg(argp, int);
266             builder.append("%s", GLbooleanToString(arg));
267         } else if (strcmp(type, "GLclampf") == 0) {
268             double arg = va_arg(argp, double);
269             builder.append("%g", arg);
270         } else if (strcmp(type, "GLenum") == 0) {
271             GLenum arg = va_arg(argp, int);
272             const char* s = GLEnumToString(arg);
273             if (s) {
274                 builder.append("%s", s);
275             } else {
276                 builder.append("0x%x", arg);
277             }
278         } else if (strcmp(type, "GLfixed") == 0) {
279             int arg = va_arg(argp, int);
280             builder.append("0x%08x", arg);
281         } else if (strcmp(type, "GLfloat") == 0) {
282             double arg = va_arg(argp, double);
283             builder.append("%g", arg);
284         } else if (strcmp(type, "GLint") == 0) {
285             int arg = va_arg(argp, int);
286             const char* s = NULL;
287             if (strcmp(name, "glTexParameteri") == 0) {
288                 s = GLEnumToString(arg);
289             }
290             if (s) {
291                 builder.append("%s", s);
292             } else {
293                 builder.append("%d", arg);
294             }
295         } else if (strcmp(type, "GLintptr") == 0) {
296             int arg = va_arg(argp, unsigned int);
297             builder.append("%u", arg);
298         } else if (strcmp(type, "GLsizei") == 0) {
299             int arg = va_arg(argp, size_t);
300             builder.append("%u", arg);
301         } else if (strcmp(type, "GLsizeiptr") == 0) {
302             int arg = va_arg(argp, size_t);
303             builder.append("%u", arg);
304         } else if (strcmp(type, "GLuint") == 0) {
305             int arg = va_arg(argp, unsigned int);
306             builder.append("%u", arg);
307         } else {
308             builder.append("/* ??? %s */", type);
309             break;
310         }
311     }
312     builder.append(");");
313     LOGD("%s", builder.getString());
314     va_end(argp);
315 }
316 
317 #undef TRACE_GL_VOID
318 #undef TRACE_GL
319 
320 #define TRACE_GL_VOID(_api, _args, _argList, ...)                         \
321 static void Tracing_ ## _api _args {                                      \
322     TraceGL(#_api, __VA_ARGS__);                                          \
323     gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
324     _c->_api _argList;                                                    \
325 }
326 
327 #define TRACE_GL(_type, _api, _args, _argList, ...)                       \
328 static _type Tracing_ ## _api _args {                                     \
329     TraceGL(#_api, __VA_ARGS__);                                        \
330     gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
331     return _c->_api _argList;                                             \
332 }
333 
334 extern "C" {
335 #include "../trace.in"
336 }
337 
338 #undef TRACE_GL_VOID
339 #undef TRACE_GL
340 
341 #define GL_ENTRY(_r, _api, ...) Tracing_ ## _api,
342 EGLAPI gl_hooks_t gHooksTrace = {
343     {
344         #include "entries.in"
345     },
346     {
347         {0}
348     }
349 };
350 #undef GL_ENTRY
351 
352 
353 #undef TRACE_GL_VOID
354 #undef TRACE_GL
355 
356 // define the ES 1.0 Debug_gl* functions as Tracing_gl functions
357 #define TRACE_GL_VOID(_api, _args, _argList, ...)                         \
358 static void Debug_ ## _api _args {                                      \
359     TraceGL(#_api, __VA_ARGS__);                                          \
360     gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
361     _c->_api _argList;                                                    \
362 }
363 
364 #define TRACE_GL(_type, _api, _args, _argList, ...)                       \
365 static _type Debug_ ## _api _args {                                     \
366     TraceGL(#_api, __VA_ARGS__);                                        \
367     gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
368     return _c->_api _argList;                                             \
369 }
370 
371 extern "C" {
372 #include "../debug.in"
373 }
374 
375 #undef TRACE_GL_VOID
376 #undef TRACE_GL
377 
378 // declare all Debug_gl* functions
379 #define GL_ENTRY(_r, _api, ...) _r Debug_##_api ( __VA_ARGS__ );
380 #include "glesv2dbg_functions.h"
381 #undef GL_ENTRY
382 
383 #define GL_ENTRY(_r, _api, ...) Debug_ ## _api,
384 EGLAPI gl_hooks_t gHooksDebug = {
385     {
386         #include "entries.in"
387     },
388     {
389         {0}
390     }
391 };
392 #undef GL_ENTRY
393 
394 // ----------------------------------------------------------------------------
395 }; // namespace android
396 // ----------------------------------------------------------------------------
397 
398 #endif // EGL_TRACE
399