blob: f3e101b489d4e90693309adb10c9e24465d5e76b [file] [log] [blame]
Jack Palevichd4d0fb92010-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
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
Jack Palevichad4c6092010-10-27 15:34:11 -070064static const char* GLbooleanToString(GLboolean arg) {
65 return arg ? "GL_TRUE" : "GL_FALSE";
66}
67
Jack Palevichd4d0fb92010-10-26 15:21:24 -070068static GLenumString g_bitfieldNames[] = {
69 {0x00004000, "GL_COLOR_BUFFER_BIT"},
70 {0x00000400, "GL_STENCIL_BUFFER_BIT"},
71 {0x00000100, "GL_DEPTH_BUFFER_BIT"}
72};
73
Jack Palevichad4c6092010-10-27 15:34:11 -070074class StringBuilder {
75 static const int lineSize = 500;
76 char line[lineSize];
77 int line_index;
78public:
79 StringBuilder() {
80 line_index = 0;
81 line[0] = '\0';
82 }
83 void append(const char* fmt, ...) {
84 va_list argp;
85 va_start(argp, fmt);
86 line_index += vsnprintf(line + line_index, lineSize-line_index, fmt, argp);
87 va_end(argp);
88 }
89 const char* getString() {
90 line_index = 0;
91 line[lineSize-1] = '\0';
92 return line;
93 }
94};
95
Jack Palevichd4d0fb92010-10-26 15:21:24 -070096
97static void TraceGLShaderSource(GLuint shader, GLsizei count,
98 const GLchar** string, const GLint* length) {
99 LOGD("const char* shaderSrc[] = {");
100 for (GLsizei i = 0; i < count; i++) {
101 const char* comma = i < count-1 ? "," : "";
102 const GLchar* s = string[i];
103 if (length) {
104 GLint len = length[i];
105 LOGD(" \"%*s\"%s", len, s, comma);
106 } else {
107 LOGD(" \"%s\"%s", s, comma);
108 }
109 }
110 LOGD("};");
111 if (length) {
112 LOGD("const GLint* shaderLength[] = {");
113 for (GLsizei i = 0; i < count; i++) {
114 const char* comma = i < count-1 ? "," : "";
115 GLint len = length[i];
116 LOGD(" \"%d\"%s", len, comma);
117 }
118 LOGD("};");
119 LOGD("glShaderSource(%u, %u, shaderSrc, shaderLength);",
120 shader, count);
121 } else {
122 LOGD("glShaderSource(%u, %u, shaderSrc, (const GLint*) 0);",
123 shader, count);
124 }
125}
126
Jack Palevichad4c6092010-10-27 15:34:11 -0700127static void TraceValue(int elementCount, char type,
128 GLsizei chunkCount, GLsizei chunkSize, const void* value) {
129 StringBuilder stringBuilder;
130 GLsizei count = chunkCount * chunkSize;
131 bool isFloat = type == 'f';
132 const char* typeString = isFloat ? "GLfloat" : "GLint";
133 LOGD("const %s value[] = {", typeString);
134 for (GLsizei i = 0; i < count; i++) {
135 StringBuilder builder;
136 builder.append(" ");
137 for (int e = 0; e < elementCount; e++) {
138 const char* comma = ", ";
139 if (e == elementCount-1) {
140 if (i == count - 1) {
141 comma = "";
142 } else {
143 comma = ",";
144 }
145 }
146 if (isFloat) {
147 builder.append("%g%s", * (GLfloat*) value, comma);
148 value = (void*) (((GLfloat*) value) + 1);
149 } else {
150 builder.append("%d%s", * (GLint*) value, comma);
151 value = (void*) (((GLint*) value) + 1);
152 }
153 }
154 LOGD("%s", builder.getString());
155 if (chunkSize > 1 && i < count-1
156 && (i % chunkSize) == (chunkSize-1)) {
157 LOGD("%s", ""); // Print a blank line.
158 }
159 }
160 LOGD("};");
161}
162
163static void TraceUniformv(int elementCount, char type,
164 GLuint location, GLsizei count, const void* value) {
165 TraceValue(elementCount, type, count, 1, value);
166 LOGD("glUniform%d%c(%u, %u, value);", elementCount, type, location, count);
167}
168
169static void TraceUniformMatrix(int matrixSideLength,
170 GLuint location, GLsizei count, GLboolean transpose, const void* value) {
171 TraceValue(matrixSideLength, 'f', count, matrixSideLength, value);
172 LOGD("glUniformMatrix%dfv(%u, %u, %s, value);", matrixSideLength, location, count,
173 GLbooleanToString(transpose));
174}
175
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700176static void TraceGL(const char* name, int numArgs, ...) {
177 va_list argp;
178 va_start(argp, numArgs);
Jack Palevichad4c6092010-10-27 15:34:11 -0700179 int nameLen = strlen(name);
180
181 // glShaderSource
182 if (nameLen == 14 && strcmp(name, "glShaderSource") == 0) {
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700183 va_arg(argp, const char*);
184 GLuint shader = va_arg(argp, GLuint);
185 va_arg(argp, const char*);
186 GLsizei count = va_arg(argp, GLsizei);
187 va_arg(argp, const char*);
188 const GLchar** string = (const GLchar**) va_arg(argp, void*);
189 va_arg(argp, const char*);
190 const GLint* length = (const GLint*) va_arg(argp, void*);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700191 va_end(argp);
Jack Palevichad4c6092010-10-27 15:34:11 -0700192 TraceGLShaderSource(shader, count, string, length);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700193 return;
194 }
Jack Palevichad4c6092010-10-27 15:34:11 -0700195
196 // glUniformXXv
197
198 if (nameLen == 12 && strncmp(name, "glUniform", 9) == 0 && name[11] == 'v') {
199 int elementCount = name[9] - '0'; // 1..4
200 char type = name[10]; // 'f' or 'i'
201 va_arg(argp, const char*);
202 GLuint location = va_arg(argp, GLuint);
203 va_arg(argp, const char*);
204 GLsizei count = va_arg(argp, GLsizei);
205 va_arg(argp, const char*);
206 const void* value = (const void*) va_arg(argp, void*);
207 va_end(argp);
208 TraceUniformv(elementCount, type, location, count, value);
209 return;
210 }
211
212 // glUniformMatrixXfv
213
214 if (nameLen == 18 && strncmp(name, "glUniformMatrix", 15) == 0
215 && name[16] == 'f' && name[17] == 'v') {
216 int matrixSideLength = name[15] - '0'; // 2..4
217 va_arg(argp, const char*);
218 GLuint location = va_arg(argp, GLuint);
219 va_arg(argp, const char*);
220 GLsizei count = va_arg(argp, GLsizei);
221 va_arg(argp, const char*);
222 GLboolean transpose = (GLboolean) va_arg(argp, int);
223 va_arg(argp, const char*);
224 const void* value = (const void*) va_arg(argp, void*);
225 va_end(argp);
226 TraceUniformMatrix(matrixSideLength, location, count, transpose, value);
227 return;
228 }
229
230 StringBuilder builder;
231 builder.append("%s(", name);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700232 for (int i = 0; i < numArgs; i++) {
233 if (i > 0) {
Jack Palevichad4c6092010-10-27 15:34:11 -0700234 builder.append(", ");
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700235 }
236 const char* type = va_arg(argp, const char*);
237 bool isPtr = type[strlen(type)-1] == '*'
238 || strcmp(type, "GLeglImageOES") == 0;
239 if (isPtr) {
240 const void* arg = va_arg(argp, const void*);
Jack Palevichad4c6092010-10-27 15:34:11 -0700241 builder.append("(%s) 0x%08x", type, (size_t) arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700242 } else if (strcmp(type, "GLbitfield") == 0) {
243 size_t arg = va_arg(argp, size_t);
244 bool first = true;
245 for (size_t i = 0; i < sizeof(g_bitfieldNames) / sizeof(g_bitfieldNames[0]); i++) {
246 const GLenumString* b = &g_bitfieldNames[i];
247 if (b->e & arg) {
248 if (first) {
249 first = false;
250 } else {
Jack Palevichad4c6092010-10-27 15:34:11 -0700251 builder.append(" | ");
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700252 }
Jack Palevichad4c6092010-10-27 15:34:11 -0700253 builder.append("%s", b->s);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700254 arg &= ~b->e;
255 }
256 }
257 if (first || arg != 0) {
258 if (!first) {
Jack Palevichad4c6092010-10-27 15:34:11 -0700259 builder.append(" | ");
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700260 }
Jack Palevichad4c6092010-10-27 15:34:11 -0700261 builder.append("0x%08x", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700262 }
263 } else if (strcmp(type, "GLboolean") == 0) {
Jack Palevichad4c6092010-10-27 15:34:11 -0700264 GLboolean arg = va_arg(argp, int);
265 builder.append("%s", GLbooleanToString(arg));
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700266 } else if (strcmp(type, "GLclampf") == 0) {
267 double arg = va_arg(argp, double);
Jack Palevichad4c6092010-10-27 15:34:11 -0700268 builder.append("%g", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700269 } else if (strcmp(type, "GLenum") == 0) {
270 GLenum arg = va_arg(argp, int);
271 const char* s = GLEnumToString(arg);
272 if (s) {
Jack Palevichad4c6092010-10-27 15:34:11 -0700273 builder.append("%s", s);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700274 } else {
Jack Palevichad4c6092010-10-27 15:34:11 -0700275 builder.append("0x%x", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700276 }
277 } else if (strcmp(type, "GLfixed") == 0) {
278 int arg = va_arg(argp, int);
Jack Palevichad4c6092010-10-27 15:34:11 -0700279 builder.append("0x%08x", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700280 } else if (strcmp(type, "GLfloat") == 0) {
281 double arg = va_arg(argp, double);
Jack Palevichad4c6092010-10-27 15:34:11 -0700282 builder.append("%g", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700283 } else if (strcmp(type, "GLint") == 0) {
284 int arg = va_arg(argp, int);
285 const char* s = NULL;
286 if (strcmp(name, "glTexParameteri") == 0) {
287 s = GLEnumToString(arg);
288 }
289 if (s) {
Jack Palevichad4c6092010-10-27 15:34:11 -0700290 builder.append("%s", s);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700291 } else {
Jack Palevichad4c6092010-10-27 15:34:11 -0700292 builder.append("%d", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700293 }
294 } else if (strcmp(type, "GLintptr") == 0) {
295 int arg = va_arg(argp, unsigned int);
Jack Palevichad4c6092010-10-27 15:34:11 -0700296 builder.append("%u", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700297 } else if (strcmp(type, "GLsizei") == 0) {
298 int arg = va_arg(argp, size_t);
Jack Palevichad4c6092010-10-27 15:34:11 -0700299 builder.append("%u", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700300 } else if (strcmp(type, "GLsizeiptr") == 0) {
301 int arg = va_arg(argp, size_t);
Jack Palevichad4c6092010-10-27 15:34:11 -0700302 builder.append("%u", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700303 } else if (strcmp(type, "GLuint") == 0) {
304 int arg = va_arg(argp, unsigned int);
Jack Palevichad4c6092010-10-27 15:34:11 -0700305 builder.append("%u", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700306 } else {
Jack Palevichad4c6092010-10-27 15:34:11 -0700307 builder.append("/* ??? %s */", type);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700308 break;
309 }
310 }
Jack Palevichad4c6092010-10-27 15:34:11 -0700311 builder.append(");");
312 LOGD("%s", builder.getString());
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700313 va_end(argp);
314}
315
316#undef TRACE_GL_VOID
317#undef TRACE_GL
318
319#define TRACE_GL_VOID(_api, _args, _argList, ...) \
320static void Tracing_ ## _api _args { \
321 TraceGL(#_api, __VA_ARGS__); \
322 gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
323 _c->_api _argList; \
324}
325
326#define TRACE_GL(_type, _api, _args, _argList, ...) \
327static _type Tracing_ ## _api _args { \
David Li28ca2ab2011-03-01 16:08:10 -0800328 TraceGL(#_api, __VA_ARGS__); \
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700329 gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
330 return _c->_api _argList; \
331}
332
333extern "C" {
334#include "../trace.in"
335}
David Li28ca2ab2011-03-01 16:08:10 -0800336
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700337#undef TRACE_GL_VOID
338#undef TRACE_GL
339
340#define GL_ENTRY(_r, _api, ...) Tracing_ ## _api,
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700341EGLAPI gl_hooks_t gHooksTrace = {
342 {
343 #include "entries.in"
344 },
345 {
346 {0}
347 }
348};
349#undef GL_ENTRY
350
David Li28ca2ab2011-03-01 16:08:10 -0800351
352#undef TRACE_GL_VOID
353#undef TRACE_GL
354
355// define the ES 1.0 Debug_gl* functions as Tracing_gl functions
356#define TRACE_GL_VOID(_api, _args, _argList, ...) \
357static void Debug_ ## _api _args { \
358 TraceGL(#_api, __VA_ARGS__); \
359 gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
360 _c->_api _argList; \
361}
362
363#define TRACE_GL(_type, _api, _args, _argList, ...) \
364static _type Debug_ ## _api _args { \
365 TraceGL(#_api, __VA_ARGS__); \
366 gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
367 return _c->_api _argList; \
368}
369
370extern "C" {
371#include "../debug.in"
372}
373
374#undef TRACE_GL_VOID
375#undef TRACE_GL
376
377// declare all Debug_gl* functions
378#define GL_ENTRY(_r, _api, ...) _r Debug_##_api ( __VA_ARGS__ );
David Li5c425f22011-03-10 16:40:37 -0800379#include "glesv2dbg_functions.h"
David Li28ca2ab2011-03-01 16:08:10 -0800380#undef GL_ENTRY
381
382#define GL_ENTRY(_r, _api, ...) Debug_ ## _api,
383EGLAPI gl_hooks_t gHooksDebug = {
384 {
385 #include "entries.in"
386 },
387 {
388 {0}
389 }
390};
391#undef GL_ENTRY
392
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700393// ----------------------------------------------------------------------------
394}; // namespace android
395// ----------------------------------------------------------------------------
396
397#endif // EGL_TRACE