OSDN Git Service

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