blob: bd6c348dc8d046cff8fc1e57758d2d3c0252996f [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
Mathias Agopianf56a9602011-05-23 17:26:14 -070029#include "egl_tls.h"
Jack Palevichd4d0fb92010-10-26 15:21:24 -070030#include "hooks.h"
31
32// ----------------------------------------------------------------------------
33namespace android {
34// ----------------------------------------------------------------------------
35
36struct GLenumString {
37 GLenum e;
38 const char* s;
39};
40
41#undef GL_ENUM
42#define GL_ENUM(VAL,NAME) {VAL, #NAME},
43
44static GLenumString g_enumnames[] = {
45#include "enums.in"
46};
47#undef GL_ENUM
48
49static int compareGLEnum(const void* a, const void* b) {
50 return ((const GLenumString*) a)->e - ((const GLenumString*) b)->e;
51}
52
53static 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
Jack Palevichad4c6092010-10-27 15:34:11 -070065static const char* GLbooleanToString(GLboolean arg) {
66 return arg ? "GL_TRUE" : "GL_FALSE";
67}
68
Jack Palevichd4d0fb92010-10-26 15:21:24 -070069static GLenumString g_bitfieldNames[] = {
70 {0x00004000, "GL_COLOR_BUFFER_BIT"},
71 {0x00000400, "GL_STENCIL_BUFFER_BIT"},
72 {0x00000100, "GL_DEPTH_BUFFER_BIT"}
73};
74
Jack Palevichad4c6092010-10-27 15:34:11 -070075class StringBuilder {
76 static const int lineSize = 500;
77 char line[lineSize];
78 int line_index;
79public:
80 StringBuilder() {
81 line_index = 0;
82 line[0] = '\0';
83 }
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 }
90 const char* getString() {
91 line_index = 0;
92 line[lineSize-1] = '\0';
93 return line;
94 }
95};
96
Jack Palevichd4d0fb92010-10-26 15:21:24 -070097
98static 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
Jack Palevichad4c6092010-10-27 15:34:11 -0700128static 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
164static 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
170static 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
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700177static void TraceGL(const char* name, int numArgs, ...) {
178 va_list argp;
179 va_start(argp, numArgs);
Jack Palevichad4c6092010-10-27 15:34:11 -0700180 int nameLen = strlen(name);
181
182 // glShaderSource
183 if (nameLen == 14 && strcmp(name, "glShaderSource") == 0) {
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700184 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*);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700192 va_end(argp);
Jack Palevichad4c6092010-10-27 15:34:11 -0700193 TraceGLShaderSource(shader, count, string, length);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700194 return;
195 }
Jack Palevichad4c6092010-10-27 15:34:11 -0700196
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);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700233 for (int i = 0; i < numArgs; i++) {
234 if (i > 0) {
Jack Palevichad4c6092010-10-27 15:34:11 -0700235 builder.append(", ");
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700236 }
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*);
Jack Palevichad4c6092010-10-27 15:34:11 -0700242 builder.append("(%s) 0x%08x", type, (size_t) arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700243 } 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 {
Jack Palevichad4c6092010-10-27 15:34:11 -0700252 builder.append(" | ");
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700253 }
Jack Palevichad4c6092010-10-27 15:34:11 -0700254 builder.append("%s", b->s);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700255 arg &= ~b->e;
256 }
257 }
258 if (first || arg != 0) {
259 if (!first) {
Jack Palevichad4c6092010-10-27 15:34:11 -0700260 builder.append(" | ");
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700261 }
Jack Palevichad4c6092010-10-27 15:34:11 -0700262 builder.append("0x%08x", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700263 }
264 } else if (strcmp(type, "GLboolean") == 0) {
Jack Palevichad4c6092010-10-27 15:34:11 -0700265 GLboolean arg = va_arg(argp, int);
266 builder.append("%s", GLbooleanToString(arg));
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700267 } else if (strcmp(type, "GLclampf") == 0) {
268 double arg = va_arg(argp, double);
Jack Palevichad4c6092010-10-27 15:34:11 -0700269 builder.append("%g", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700270 } else if (strcmp(type, "GLenum") == 0) {
271 GLenum arg = va_arg(argp, int);
272 const char* s = GLEnumToString(arg);
273 if (s) {
Jack Palevichad4c6092010-10-27 15:34:11 -0700274 builder.append("%s", s);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700275 } else {
Jack Palevichad4c6092010-10-27 15:34:11 -0700276 builder.append("0x%x", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700277 }
278 } else if (strcmp(type, "GLfixed") == 0) {
279 int arg = va_arg(argp, int);
Jack Palevichad4c6092010-10-27 15:34:11 -0700280 builder.append("0x%08x", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700281 } else if (strcmp(type, "GLfloat") == 0) {
282 double arg = va_arg(argp, double);
Jack Palevichad4c6092010-10-27 15:34:11 -0700283 builder.append("%g", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700284 } 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) {
Jack Palevichad4c6092010-10-27 15:34:11 -0700291 builder.append("%s", s);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700292 } else {
Jack Palevichad4c6092010-10-27 15:34:11 -0700293 builder.append("%d", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700294 }
295 } else if (strcmp(type, "GLintptr") == 0) {
296 int arg = va_arg(argp, unsigned int);
Jack Palevichad4c6092010-10-27 15:34:11 -0700297 builder.append("%u", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700298 } else if (strcmp(type, "GLsizei") == 0) {
299 int arg = va_arg(argp, size_t);
Jack Palevichad4c6092010-10-27 15:34:11 -0700300 builder.append("%u", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700301 } else if (strcmp(type, "GLsizeiptr") == 0) {
302 int arg = va_arg(argp, size_t);
Jack Palevichad4c6092010-10-27 15:34:11 -0700303 builder.append("%u", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700304 } else if (strcmp(type, "GLuint") == 0) {
305 int arg = va_arg(argp, unsigned int);
Jack Palevichad4c6092010-10-27 15:34:11 -0700306 builder.append("%u", arg);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700307 } else {
Jack Palevichad4c6092010-10-27 15:34:11 -0700308 builder.append("/* ??? %s */", type);
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700309 break;
310 }
311 }
Jack Palevichad4c6092010-10-27 15:34:11 -0700312 builder.append(");");
313 LOGD("%s", builder.getString());
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700314 va_end(argp);
315}
316
317#undef TRACE_GL_VOID
318#undef TRACE_GL
319
320#define TRACE_GL_VOID(_api, _args, _argList, ...) \
321static 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, ...) \
328static _type Tracing_ ## _api _args { \
David Li28ca2ab2011-03-01 16:08:10 -0800329 TraceGL(#_api, __VA_ARGS__); \
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700330 gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
331 return _c->_api _argList; \
332}
333
334extern "C" {
335#include "../trace.in"
336}
David Li28ca2ab2011-03-01 16:08:10 -0800337
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700338#undef TRACE_GL_VOID
339#undef TRACE_GL
340
341#define GL_ENTRY(_r, _api, ...) Tracing_ ## _api,
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700342EGLAPI gl_hooks_t gHooksTrace = {
343 {
344 #include "entries.in"
345 },
346 {
347 {0}
348 }
349};
350#undef GL_ENTRY
351
David Li28ca2ab2011-03-01 16:08:10 -0800352
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, ...) \
358static 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, ...) \
365static _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
371extern "C" {
372#include "../debug.in"
373}
374
375#undef TRACE_GL_VOID
376#undef TRACE_GL
377
Jack Palevichd4d0fb92010-10-26 15:21:24 -0700378// ----------------------------------------------------------------------------
379}; // namespace android
380// ----------------------------------------------------------------------------
381
382#endif // EGL_TRACE