blob: bac6ba8ecf116e3731468456223c480a39b6dc17 [file] [log] [blame]
Jack Palevicha2dd6cf2010-10-26 15:21:24 -07001/*
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>
Jack Palevicha2dd6cf2010-10-26 15:21:24 -070024
25#include <cutils/log.h>
26
Romain Guy16928bf2012-10-18 16:16:10 -070027#define ATRACE_TAG ATRACE_TAG_GRAPHICS
28#include <utils/Trace.h>
29
30#include <utils/CallStack.h>
31
Mathias Agopian1cadb252011-05-23 17:26:14 -070032#include "egl_tls.h"
Jack Palevicha2dd6cf2010-10-26 15:21:24 -070033#include "hooks.h"
34
35// ----------------------------------------------------------------------------
36namespace android {
37// ----------------------------------------------------------------------------
38
39struct GLenumString {
Jesse Hall47743382013-02-08 11:13:46 -080040 // The GL_TIMEOUT_IGNORED "enum" doesn't fit in a GLenum, so use GLuint64
41 GLuint64 e;
Jack Palevicha2dd6cf2010-10-26 15:21:24 -070042 const char* s;
43};
44
45#undef GL_ENUM
46#define GL_ENUM(VAL,NAME) {VAL, #NAME},
47
48static GLenumString g_enumnames[] = {
49#include "enums.in"
50};
51#undef GL_ENUM
52
53static int compareGLEnum(const void* a, const void* b) {
54 return ((const GLenumString*) a)->e - ((const GLenumString*) b)->e;
55}
56
57static 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
Jack Palevich6132b372010-10-27 15:34:11 -070069static const char* GLbooleanToString(GLboolean arg) {
70 return arg ? "GL_TRUE" : "GL_FALSE";
71}
72
Jack Palevicha2dd6cf2010-10-26 15:21:24 -070073static GLenumString g_bitfieldNames[] = {
74 {0x00004000, "GL_COLOR_BUFFER_BIT"},
75 {0x00000400, "GL_STENCIL_BUFFER_BIT"},
76 {0x00000100, "GL_DEPTH_BUFFER_BIT"}
77};
78
Jack Palevich6132b372010-10-27 15:34:11 -070079class StringBuilder {
80 static const int lineSize = 500;
81 char line[lineSize];
82 int line_index;
83public:
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
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700101
102static void TraceGLShaderSource(GLuint shader, GLsizei count,
103 const GLchar** string, const GLint* length) {
Steve Block9d453682011-12-20 16:23:08 +0000104 ALOGD("const char* shaderSrc[] = {");
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700105 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];
Steve Block9d453682011-12-20 16:23:08 +0000110 ALOGD(" \"%*s\"%s", len, s, comma);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700111 } else {
Steve Block9d453682011-12-20 16:23:08 +0000112 ALOGD(" \"%s\"%s", s, comma);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700113 }
114 }
Steve Block9d453682011-12-20 16:23:08 +0000115 ALOGD("};");
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700116 if (length) {
Steve Block9d453682011-12-20 16:23:08 +0000117 ALOGD("const GLint* shaderLength[] = {");
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700118 for (GLsizei i = 0; i < count; i++) {
119 const char* comma = i < count-1 ? "," : "";
120 GLint len = length[i];
Steve Block9d453682011-12-20 16:23:08 +0000121 ALOGD(" \"%d\"%s", len, comma);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700122 }
Steve Block9d453682011-12-20 16:23:08 +0000123 ALOGD("};");
124 ALOGD("glShaderSource(%u, %u, shaderSrc, shaderLength);",
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700125 shader, count);
126 } else {
Steve Block9d453682011-12-20 16:23:08 +0000127 ALOGD("glShaderSource(%u, %u, shaderSrc, (const GLint*) 0);",
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700128 shader, count);
129 }
130}
131
Jack Palevich6132b372010-10-27 15:34:11 -0700132static 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";
Steve Block9d453682011-12-20 16:23:08 +0000138 ALOGD("const %s value[] = {", typeString);
Jack Palevich6132b372010-10-27 15:34:11 -0700139 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 }
Steve Block9d453682011-12-20 16:23:08 +0000159 ALOGD("%s", builder.getString());
Jack Palevich6132b372010-10-27 15:34:11 -0700160 if (chunkSize > 1 && i < count-1
161 && (i % chunkSize) == (chunkSize-1)) {
Steve Block9d453682011-12-20 16:23:08 +0000162 ALOGD("%s", ""); // Print a blank line.
Jack Palevich6132b372010-10-27 15:34:11 -0700163 }
164 }
Steve Block9d453682011-12-20 16:23:08 +0000165 ALOGD("};");
Jack Palevich6132b372010-10-27 15:34:11 -0700166}
167
168static void TraceUniformv(int elementCount, char type,
169 GLuint location, GLsizei count, const void* value) {
170 TraceValue(elementCount, type, count, 1, value);
Steve Block9d453682011-12-20 16:23:08 +0000171 ALOGD("glUniform%d%c(%u, %u, value);", elementCount, type, location, count);
Jack Palevich6132b372010-10-27 15:34:11 -0700172}
173
174static void TraceUniformMatrix(int matrixSideLength,
175 GLuint location, GLsizei count, GLboolean transpose, const void* value) {
176 TraceValue(matrixSideLength, 'f', count, matrixSideLength, value);
Steve Block9d453682011-12-20 16:23:08 +0000177 ALOGD("glUniformMatrix%dfv(%u, %u, %s, value);", matrixSideLength, location, count,
Jack Palevich6132b372010-10-27 15:34:11 -0700178 GLbooleanToString(transpose));
179}
180
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700181static void TraceGL(const char* name, int numArgs, ...) {
182 va_list argp;
183 va_start(argp, numArgs);
Jack Palevich6132b372010-10-27 15:34:11 -0700184 int nameLen = strlen(name);
185
186 // glShaderSource
187 if (nameLen == 14 && strcmp(name, "glShaderSource") == 0) {
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700188 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*);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700196 va_end(argp);
Jack Palevich6132b372010-10-27 15:34:11 -0700197 TraceGLShaderSource(shader, count, string, length);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700198 return;
199 }
Jack Palevich6132b372010-10-27 15:34:11 -0700200
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);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700237 for (int i = 0; i < numArgs; i++) {
238 if (i > 0) {
Jack Palevich6132b372010-10-27 15:34:11 -0700239 builder.append(", ");
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700240 }
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*);
Jack Palevich6132b372010-10-27 15:34:11 -0700246 builder.append("(%s) 0x%08x", type, (size_t) arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700247 } 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 {
Jack Palevich6132b372010-10-27 15:34:11 -0700256 builder.append(" | ");
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700257 }
Jack Palevich6132b372010-10-27 15:34:11 -0700258 builder.append("%s", b->s);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700259 arg &= ~b->e;
260 }
261 }
262 if (first || arg != 0) {
263 if (!first) {
Jack Palevich6132b372010-10-27 15:34:11 -0700264 builder.append(" | ");
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700265 }
Jack Palevich6132b372010-10-27 15:34:11 -0700266 builder.append("0x%08x", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700267 }
268 } else if (strcmp(type, "GLboolean") == 0) {
Jack Palevich6132b372010-10-27 15:34:11 -0700269 GLboolean arg = va_arg(argp, int);
270 builder.append("%s", GLbooleanToString(arg));
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700271 } else if (strcmp(type, "GLclampf") == 0) {
272 double arg = va_arg(argp, double);
Jack Palevich6132b372010-10-27 15:34:11 -0700273 builder.append("%g", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700274 } else if (strcmp(type, "GLenum") == 0) {
275 GLenum arg = va_arg(argp, int);
276 const char* s = GLEnumToString(arg);
277 if (s) {
Jack Palevich6132b372010-10-27 15:34:11 -0700278 builder.append("%s", s);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700279 } else {
Jack Palevich6132b372010-10-27 15:34:11 -0700280 builder.append("0x%x", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700281 }
282 } else if (strcmp(type, "GLfixed") == 0) {
283 int arg = va_arg(argp, int);
Jack Palevich6132b372010-10-27 15:34:11 -0700284 builder.append("0x%08x", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700285 } else if (strcmp(type, "GLfloat") == 0) {
286 double arg = va_arg(argp, double);
Jack Palevich6132b372010-10-27 15:34:11 -0700287 builder.append("%g", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700288 } 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) {
Jack Palevich6132b372010-10-27 15:34:11 -0700295 builder.append("%s", s);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700296 } else {
Jack Palevich6132b372010-10-27 15:34:11 -0700297 builder.append("%d", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700298 }
299 } else if (strcmp(type, "GLintptr") == 0) {
300 int arg = va_arg(argp, unsigned int);
Jack Palevich6132b372010-10-27 15:34:11 -0700301 builder.append("%u", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700302 } else if (strcmp(type, "GLsizei") == 0) {
303 int arg = va_arg(argp, size_t);
Jack Palevich6132b372010-10-27 15:34:11 -0700304 builder.append("%u", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700305 } else if (strcmp(type, "GLsizeiptr") == 0) {
306 int arg = va_arg(argp, size_t);
Jack Palevich6132b372010-10-27 15:34:11 -0700307 builder.append("%u", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700308 } else if (strcmp(type, "GLuint") == 0) {
309 int arg = va_arg(argp, unsigned int);
Jack Palevich6132b372010-10-27 15:34:11 -0700310 builder.append("%u", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700311 } else {
Jack Palevich6132b372010-10-27 15:34:11 -0700312 builder.append("/* ??? %s */", type);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700313 break;
314 }
315 }
Jack Palevich6132b372010-10-27 15:34:11 -0700316 builder.append(");");
Steve Block9d453682011-12-20 16:23:08 +0000317 ALOGD("%s", builder.getString());
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700318 va_end(argp);
319}
320
Romain Guy16928bf2012-10-18 16:16:10 -0700321///////////////////////////////////////////////////////////////////////////
322// Log trace
323///////////////////////////////////////////////////////////////////////////
324
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700325#undef TRACE_GL_VOID
326#undef TRACE_GL
327
328#define TRACE_GL_VOID(_api, _args, _argList, ...) \
329static 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, ...) \
336static _type Tracing_ ## _api _args { \
David Li2f5a6552011-03-01 16:08:10 -0800337 TraceGL(#_api, __VA_ARGS__); \
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700338 gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
339 return _c->_api _argList; \
340}
341
342extern "C" {
343#include "../trace.in"
344}
David Li2f5a6552011-03-01 16:08:10 -0800345
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700346#undef TRACE_GL_VOID
347#undef TRACE_GL
348
349#define GL_ENTRY(_r, _api, ...) Tracing_ ## _api,
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700350EGLAPI gl_hooks_t gHooksTrace = {
351 {
352 #include "entries.in"
353 },
354 {
355 {0}
356 }
357};
358#undef GL_ENTRY
359
David Li2f5a6552011-03-01 16:08:10 -0800360#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, ...) \
365static 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, ...) \
372static _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
378extern "C" {
379#include "../debug.in"
380}
381
Romain Guy16928bf2012-10-18 16:16:10 -0700382///////////////////////////////////////////////////////////////////////////
383// Systrace
384///////////////////////////////////////////////////////////////////////////
385
386#undef TRACE_GL_VOID
387#undef TRACE_GL
388
389#define TRACE_GL_VOID(_api, _args, _argList, ...) \
390static 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, ...) \
397static _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
403extern "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,
411EGLAPI 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.dump("glGetError:" #_api); \
439 } \
440
441#define TRACE_GL_VOID(_api, _args, _argList, ...) \
442static 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, ...) \
449static _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
456extern "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,
464EGLAPI gl_hooks_t gHooksErrorTrace = {
465 {
466 #include "entries.in"
467 },
468 {
469 {0}
470 }
471};
472#undef GL_ENTRY
473#undef CHECK_ERROR
474
David Li2f5a6552011-03-01 16:08:10 -0800475#undef TRACE_GL_VOID
476#undef TRACE_GL
477
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700478// ----------------------------------------------------------------------------
479}; // namespace android
480// ----------------------------------------------------------------------------
481
482#endif // EGL_TRACE