blob: a51b086e401ea1ff79ab0b5819419c29aea814eb [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>
24#include <GLES/gl.h>
25#include <GLES/glext.h>
26
27#include <cutils/log.h>
28
Romain Guy16928bf2012-10-18 16:16:10 -070029#define ATRACE_TAG ATRACE_TAG_GRAPHICS
30#include <utils/Trace.h>
31
32#include <utils/CallStack.h>
33
Mathias Agopian1cadb252011-05-23 17:26:14 -070034#include "egl_tls.h"
Jack Palevicha2dd6cf2010-10-26 15:21:24 -070035#include "hooks.h"
36
37// ----------------------------------------------------------------------------
38namespace android {
39// ----------------------------------------------------------------------------
40
41struct GLenumString {
42 GLenum e;
43 const char* s;
44};
45
46#undef GL_ENUM
47#define GL_ENUM(VAL,NAME) {VAL, #NAME},
48
49static GLenumString g_enumnames[] = {
50#include "enums.in"
51};
52#undef GL_ENUM
53
54static int compareGLEnum(const void* a, const void* b) {
55 return ((const GLenumString*) a)->e - ((const GLenumString*) b)->e;
56}
57
58static const char* GLEnumToString(GLenum e) {
59 GLenumString key = {e, ""};
60 const GLenumString* result = (const GLenumString*) bsearch(
61 &key, g_enumnames,
62 sizeof(g_enumnames) / sizeof(g_enumnames[0]),
63 sizeof(g_enumnames[0]), compareGLEnum);
64 if (result) {
65 return result->s;
66 }
67 return NULL;
68}
69
Jack Palevich6132b372010-10-27 15:34:11 -070070static const char* GLbooleanToString(GLboolean arg) {
71 return arg ? "GL_TRUE" : "GL_FALSE";
72}
73
Jack Palevicha2dd6cf2010-10-26 15:21:24 -070074static GLenumString g_bitfieldNames[] = {
75 {0x00004000, "GL_COLOR_BUFFER_BIT"},
76 {0x00000400, "GL_STENCIL_BUFFER_BIT"},
77 {0x00000100, "GL_DEPTH_BUFFER_BIT"}
78};
79
Jack Palevich6132b372010-10-27 15:34:11 -070080class StringBuilder {
81 static const int lineSize = 500;
82 char line[lineSize];
83 int line_index;
84public:
85 StringBuilder() {
86 line_index = 0;
87 line[0] = '\0';
88 }
89 void append(const char* fmt, ...) {
90 va_list argp;
91 va_start(argp, fmt);
92 line_index += vsnprintf(line + line_index, lineSize-line_index, fmt, argp);
93 va_end(argp);
94 }
95 const char* getString() {
96 line_index = 0;
97 line[lineSize-1] = '\0';
98 return line;
99 }
100};
101
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700102
103static void TraceGLShaderSource(GLuint shader, GLsizei count,
104 const GLchar** string, const GLint* length) {
Steve Block9d453682011-12-20 16:23:08 +0000105 ALOGD("const char* shaderSrc[] = {");
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700106 for (GLsizei i = 0; i < count; i++) {
107 const char* comma = i < count-1 ? "," : "";
108 const GLchar* s = string[i];
109 if (length) {
110 GLint len = length[i];
Steve Block9d453682011-12-20 16:23:08 +0000111 ALOGD(" \"%*s\"%s", len, s, comma);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700112 } else {
Steve Block9d453682011-12-20 16:23:08 +0000113 ALOGD(" \"%s\"%s", s, comma);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700114 }
115 }
Steve Block9d453682011-12-20 16:23:08 +0000116 ALOGD("};");
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700117 if (length) {
Steve Block9d453682011-12-20 16:23:08 +0000118 ALOGD("const GLint* shaderLength[] = {");
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700119 for (GLsizei i = 0; i < count; i++) {
120 const char* comma = i < count-1 ? "," : "";
121 GLint len = length[i];
Steve Block9d453682011-12-20 16:23:08 +0000122 ALOGD(" \"%d\"%s", len, comma);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700123 }
Steve Block9d453682011-12-20 16:23:08 +0000124 ALOGD("};");
125 ALOGD("glShaderSource(%u, %u, shaderSrc, shaderLength);",
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700126 shader, count);
127 } else {
Steve Block9d453682011-12-20 16:23:08 +0000128 ALOGD("glShaderSource(%u, %u, shaderSrc, (const GLint*) 0);",
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700129 shader, count);
130 }
131}
132
Jack Palevich6132b372010-10-27 15:34:11 -0700133static void TraceValue(int elementCount, char type,
134 GLsizei chunkCount, GLsizei chunkSize, const void* value) {
135 StringBuilder stringBuilder;
136 GLsizei count = chunkCount * chunkSize;
137 bool isFloat = type == 'f';
138 const char* typeString = isFloat ? "GLfloat" : "GLint";
Steve Block9d453682011-12-20 16:23:08 +0000139 ALOGD("const %s value[] = {", typeString);
Jack Palevich6132b372010-10-27 15:34:11 -0700140 for (GLsizei i = 0; i < count; i++) {
141 StringBuilder builder;
142 builder.append(" ");
143 for (int e = 0; e < elementCount; e++) {
144 const char* comma = ", ";
145 if (e == elementCount-1) {
146 if (i == count - 1) {
147 comma = "";
148 } else {
149 comma = ",";
150 }
151 }
152 if (isFloat) {
153 builder.append("%g%s", * (GLfloat*) value, comma);
154 value = (void*) (((GLfloat*) value) + 1);
155 } else {
156 builder.append("%d%s", * (GLint*) value, comma);
157 value = (void*) (((GLint*) value) + 1);
158 }
159 }
Steve Block9d453682011-12-20 16:23:08 +0000160 ALOGD("%s", builder.getString());
Jack Palevich6132b372010-10-27 15:34:11 -0700161 if (chunkSize > 1 && i < count-1
162 && (i % chunkSize) == (chunkSize-1)) {
Steve Block9d453682011-12-20 16:23:08 +0000163 ALOGD("%s", ""); // Print a blank line.
Jack Palevich6132b372010-10-27 15:34:11 -0700164 }
165 }
Steve Block9d453682011-12-20 16:23:08 +0000166 ALOGD("};");
Jack Palevich6132b372010-10-27 15:34:11 -0700167}
168
169static void TraceUniformv(int elementCount, char type,
170 GLuint location, GLsizei count, const void* value) {
171 TraceValue(elementCount, type, count, 1, value);
Steve Block9d453682011-12-20 16:23:08 +0000172 ALOGD("glUniform%d%c(%u, %u, value);", elementCount, type, location, count);
Jack Palevich6132b372010-10-27 15:34:11 -0700173}
174
175static void TraceUniformMatrix(int matrixSideLength,
176 GLuint location, GLsizei count, GLboolean transpose, const void* value) {
177 TraceValue(matrixSideLength, 'f', count, matrixSideLength, value);
Steve Block9d453682011-12-20 16:23:08 +0000178 ALOGD("glUniformMatrix%dfv(%u, %u, %s, value);", matrixSideLength, location, count,
Jack Palevich6132b372010-10-27 15:34:11 -0700179 GLbooleanToString(transpose));
180}
181
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700182static void TraceGL(const char* name, int numArgs, ...) {
183 va_list argp;
184 va_start(argp, numArgs);
Jack Palevich6132b372010-10-27 15:34:11 -0700185 int nameLen = strlen(name);
186
187 // glShaderSource
188 if (nameLen == 14 && strcmp(name, "glShaderSource") == 0) {
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700189 va_arg(argp, const char*);
190 GLuint shader = va_arg(argp, GLuint);
191 va_arg(argp, const char*);
192 GLsizei count = va_arg(argp, GLsizei);
193 va_arg(argp, const char*);
194 const GLchar** string = (const GLchar**) va_arg(argp, void*);
195 va_arg(argp, const char*);
196 const GLint* length = (const GLint*) va_arg(argp, void*);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700197 va_end(argp);
Jack Palevich6132b372010-10-27 15:34:11 -0700198 TraceGLShaderSource(shader, count, string, length);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700199 return;
200 }
Jack Palevich6132b372010-10-27 15:34:11 -0700201
202 // glUniformXXv
203
204 if (nameLen == 12 && strncmp(name, "glUniform", 9) == 0 && name[11] == 'v') {
205 int elementCount = name[9] - '0'; // 1..4
206 char type = name[10]; // 'f' or 'i'
207 va_arg(argp, const char*);
208 GLuint location = va_arg(argp, GLuint);
209 va_arg(argp, const char*);
210 GLsizei count = va_arg(argp, GLsizei);
211 va_arg(argp, const char*);
212 const void* value = (const void*) va_arg(argp, void*);
213 va_end(argp);
214 TraceUniformv(elementCount, type, location, count, value);
215 return;
216 }
217
218 // glUniformMatrixXfv
219
220 if (nameLen == 18 && strncmp(name, "glUniformMatrix", 15) == 0
221 && name[16] == 'f' && name[17] == 'v') {
222 int matrixSideLength = name[15] - '0'; // 2..4
223 va_arg(argp, const char*);
224 GLuint location = va_arg(argp, GLuint);
225 va_arg(argp, const char*);
226 GLsizei count = va_arg(argp, GLsizei);
227 va_arg(argp, const char*);
228 GLboolean transpose = (GLboolean) va_arg(argp, int);
229 va_arg(argp, const char*);
230 const void* value = (const void*) va_arg(argp, void*);
231 va_end(argp);
232 TraceUniformMatrix(matrixSideLength, location, count, transpose, value);
233 return;
234 }
235
236 StringBuilder builder;
237 builder.append("%s(", name);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700238 for (int i = 0; i < numArgs; i++) {
239 if (i > 0) {
Jack Palevich6132b372010-10-27 15:34:11 -0700240 builder.append(", ");
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700241 }
242 const char* type = va_arg(argp, const char*);
243 bool isPtr = type[strlen(type)-1] == '*'
244 || strcmp(type, "GLeglImageOES") == 0;
245 if (isPtr) {
246 const void* arg = va_arg(argp, const void*);
Jack Palevich6132b372010-10-27 15:34:11 -0700247 builder.append("(%s) 0x%08x", type, (size_t) arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700248 } else if (strcmp(type, "GLbitfield") == 0) {
249 size_t arg = va_arg(argp, size_t);
250 bool first = true;
251 for (size_t i = 0; i < sizeof(g_bitfieldNames) / sizeof(g_bitfieldNames[0]); i++) {
252 const GLenumString* b = &g_bitfieldNames[i];
253 if (b->e & arg) {
254 if (first) {
255 first = false;
256 } else {
Jack Palevich6132b372010-10-27 15:34:11 -0700257 builder.append(" | ");
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700258 }
Jack Palevich6132b372010-10-27 15:34:11 -0700259 builder.append("%s", b->s);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700260 arg &= ~b->e;
261 }
262 }
263 if (first || arg != 0) {
264 if (!first) {
Jack Palevich6132b372010-10-27 15:34:11 -0700265 builder.append(" | ");
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700266 }
Jack Palevich6132b372010-10-27 15:34:11 -0700267 builder.append("0x%08x", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700268 }
269 } else if (strcmp(type, "GLboolean") == 0) {
Jack Palevich6132b372010-10-27 15:34:11 -0700270 GLboolean arg = va_arg(argp, int);
271 builder.append("%s", GLbooleanToString(arg));
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700272 } else if (strcmp(type, "GLclampf") == 0) {
273 double arg = va_arg(argp, double);
Jack Palevich6132b372010-10-27 15:34:11 -0700274 builder.append("%g", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700275 } else if (strcmp(type, "GLenum") == 0) {
276 GLenum arg = va_arg(argp, int);
277 const char* s = GLEnumToString(arg);
278 if (s) {
Jack Palevich6132b372010-10-27 15:34:11 -0700279 builder.append("%s", s);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700280 } else {
Jack Palevich6132b372010-10-27 15:34:11 -0700281 builder.append("0x%x", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700282 }
283 } else if (strcmp(type, "GLfixed") == 0) {
284 int arg = va_arg(argp, int);
Jack Palevich6132b372010-10-27 15:34:11 -0700285 builder.append("0x%08x", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700286 } else if (strcmp(type, "GLfloat") == 0) {
287 double arg = va_arg(argp, double);
Jack Palevich6132b372010-10-27 15:34:11 -0700288 builder.append("%g", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700289 } else if (strcmp(type, "GLint") == 0) {
290 int arg = va_arg(argp, int);
291 const char* s = NULL;
292 if (strcmp(name, "glTexParameteri") == 0) {
293 s = GLEnumToString(arg);
294 }
295 if (s) {
Jack Palevich6132b372010-10-27 15:34:11 -0700296 builder.append("%s", s);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700297 } else {
Jack Palevich6132b372010-10-27 15:34:11 -0700298 builder.append("%d", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700299 }
300 } else if (strcmp(type, "GLintptr") == 0) {
301 int arg = va_arg(argp, unsigned int);
Jack Palevich6132b372010-10-27 15:34:11 -0700302 builder.append("%u", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700303 } else if (strcmp(type, "GLsizei") == 0) {
304 int arg = va_arg(argp, size_t);
Jack Palevich6132b372010-10-27 15:34:11 -0700305 builder.append("%u", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700306 } else if (strcmp(type, "GLsizeiptr") == 0) {
307 int arg = va_arg(argp, size_t);
Jack Palevich6132b372010-10-27 15:34:11 -0700308 builder.append("%u", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700309 } else if (strcmp(type, "GLuint") == 0) {
310 int arg = va_arg(argp, unsigned int);
Jack Palevich6132b372010-10-27 15:34:11 -0700311 builder.append("%u", arg);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700312 } else {
Jack Palevich6132b372010-10-27 15:34:11 -0700313 builder.append("/* ??? %s */", type);
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700314 break;
315 }
316 }
Jack Palevich6132b372010-10-27 15:34:11 -0700317 builder.append(");");
Steve Block9d453682011-12-20 16:23:08 +0000318 ALOGD("%s", builder.getString());
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700319 va_end(argp);
320}
321
Romain Guy16928bf2012-10-18 16:16:10 -0700322///////////////////////////////////////////////////////////////////////////
323// Log trace
324///////////////////////////////////////////////////////////////////////////
325
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700326#undef TRACE_GL_VOID
327#undef TRACE_GL
328
329#define TRACE_GL_VOID(_api, _args, _argList, ...) \
330static void Tracing_ ## _api _args { \
331 TraceGL(#_api, __VA_ARGS__); \
332 gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
333 _c->_api _argList; \
334}
335
336#define TRACE_GL(_type, _api, _args, _argList, ...) \
337static _type Tracing_ ## _api _args { \
David Li2f5a6552011-03-01 16:08:10 -0800338 TraceGL(#_api, __VA_ARGS__); \
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700339 gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
340 return _c->_api _argList; \
341}
342
343extern "C" {
344#include "../trace.in"
345}
David Li2f5a6552011-03-01 16:08:10 -0800346
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700347#undef TRACE_GL_VOID
348#undef TRACE_GL
349
350#define GL_ENTRY(_r, _api, ...) Tracing_ ## _api,
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700351EGLAPI gl_hooks_t gHooksTrace = {
352 {
353 #include "entries.in"
354 },
355 {
356 {0}
357 }
358};
359#undef GL_ENTRY
360
David Li2f5a6552011-03-01 16:08:10 -0800361#undef TRACE_GL_VOID
362#undef TRACE_GL
363
364// define the ES 1.0 Debug_gl* functions as Tracing_gl functions
365#define TRACE_GL_VOID(_api, _args, _argList, ...) \
366static void Debug_ ## _api _args { \
367 TraceGL(#_api, __VA_ARGS__); \
368 gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
369 _c->_api _argList; \
370}
371
372#define TRACE_GL(_type, _api, _args, _argList, ...) \
373static _type Debug_ ## _api _args { \
374 TraceGL(#_api, __VA_ARGS__); \
375 gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
376 return _c->_api _argList; \
377}
378
379extern "C" {
380#include "../debug.in"
381}
382
Romain Guy16928bf2012-10-18 16:16:10 -0700383///////////////////////////////////////////////////////////////////////////
384// Systrace
385///////////////////////////////////////////////////////////////////////////
386
387#undef TRACE_GL_VOID
388#undef TRACE_GL
389
390#define TRACE_GL_VOID(_api, _args, _argList, ...) \
391static void Systrace_ ## _api _args { \
392 ATRACE_NAME(#_api); \
393 gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
394 _c->_api _argList; \
395}
396
397#define TRACE_GL(_type, _api, _args, _argList, ...) \
398static _type Systrace_ ## _api _args { \
399 ATRACE_NAME(#_api); \
400 gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
401 return _c->_api _argList; \
402}
403
404extern "C" {
405#include "../trace.in"
406}
407
408#undef TRACE_GL_VOID
409#undef TRACE_GL
410
411#define GL_ENTRY(_r, _api, ...) Systrace_ ## _api,
412EGLAPI gl_hooks_t gHooksSystrace = {
413 {
414 #include "entries.in"
415 },
416 {
417 {0}
418 }
419};
420#undef GL_ENTRY
421
422///////////////////////////////////////////////////////////////////////////
423//
424///////////////////////////////////////////////////////////////////////////
425
426#undef TRACE_GL_VOID
427#undef TRACE_GL
428
429#define CHECK_ERROR(_c, _api) \
430 GLenum status = GL_NO_ERROR; \
431 bool error = false; \
432 while ((status = _c->glGetError()) != GL_NO_ERROR) { \
433 ALOGD("[" #_api "] 0x%x", status); \
434 error = true; \
435 } \
436 if (error) { \
437 CallStack s; \
438 s.update(); \
439 s.dump("glGetError:" #_api); \
440 } \
441
442#define TRACE_GL_VOID(_api, _args, _argList, ...) \
443static void ErrorTrace_ ## _api _args { \
444 gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
445 _c->_api _argList; \
446 CHECK_ERROR(_c, _api); \
447}
448
449#define TRACE_GL(_type, _api, _args, _argList, ...) \
450static _type ErrorTrace_ ## _api _args { \
451 gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
452 _type _r = _c->_api _argList; \
453 CHECK_ERROR(_c, _api); \
454 return _r; \
455}
456
457extern "C" {
458#include "../trace.in"
459}
460
461#undef TRACE_GL_VOID
462#undef TRACE_GL
463
464#define GL_ENTRY(_r, _api, ...) ErrorTrace_ ## _api,
465EGLAPI gl_hooks_t gHooksErrorTrace = {
466 {
467 #include "entries.in"
468 },
469 {
470 {0}
471 }
472};
473#undef GL_ENTRY
474#undef CHECK_ERROR
475
David Li2f5a6552011-03-01 16:08:10 -0800476#undef TRACE_GL_VOID
477#undef TRACE_GL
478
Jack Palevicha2dd6cf2010-10-26 15:21:24 -0700479// ----------------------------------------------------------------------------
480}; // namespace android
481// ----------------------------------------------------------------------------
482
483#endif // EGL_TRACE