trace.cpp revision 6132b3703da76389e81d26b0023846a78b008603
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#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 64static const char* GLbooleanToString(GLboolean arg) { 65 return arg ? "GL_TRUE" : "GL_FALSE"; 66} 67 68static GLenumString g_bitfieldNames[] = { 69 {0x00004000, "GL_COLOR_BUFFER_BIT"}, 70 {0x00000400, "GL_STENCIL_BUFFER_BIT"}, 71 {0x00000100, "GL_DEPTH_BUFFER_BIT"} 72}; 73 74class 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 96 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 127static 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 176static void TraceGL(const char* name, int numArgs, ...) { 177 va_list argp; 178 va_start(argp, numArgs); 179 int nameLen = strlen(name); 180 181 // glShaderSource 182 if (nameLen == 14 && strcmp(name, "glShaderSource") == 0) { 183 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*); 191 va_end(argp); 192 TraceGLShaderSource(shader, count, string, length); 193 return; 194 } 195 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); 232 for (int i = 0; i < numArgs; i++) { 233 if (i > 0) { 234 builder.append(", "); 235 } 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*); 241 builder.append("(%s) 0x%08x", type, (size_t) arg); 242 } 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 { 251 builder.append(" | "); 252 } 253 builder.append("%s", b->s); 254 arg &= ~b->e; 255 } 256 } 257 if (first || arg != 0) { 258 if (!first) { 259 builder.append(" | "); 260 } 261 builder.append("0x%08x", arg); 262 } 263 } else if (strcmp(type, "GLboolean") == 0) { 264 GLboolean arg = va_arg(argp, int); 265 builder.append("%s", GLbooleanToString(arg)); 266 } else if (strcmp(type, "GLclampf") == 0) { 267 double arg = va_arg(argp, double); 268 builder.append("%g", arg); 269 } else if (strcmp(type, "GLenum") == 0) { 270 GLenum arg = va_arg(argp, int); 271 const char* s = GLEnumToString(arg); 272 if (s) { 273 builder.append("%s", s); 274 } else { 275 builder.append("0x%x", arg); 276 } 277 } else if (strcmp(type, "GLfixed") == 0) { 278 int arg = va_arg(argp, int); 279 builder.append("0x%08x", arg); 280 } else if (strcmp(type, "GLfloat") == 0) { 281 double arg = va_arg(argp, double); 282 builder.append("%g", arg); 283 } 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) { 290 builder.append("%s", s); 291 } else { 292 builder.append("%d", arg); 293 } 294 } else if (strcmp(type, "GLintptr") == 0) { 295 int arg = va_arg(argp, unsigned int); 296 builder.append("%u", arg); 297 } else if (strcmp(type, "GLsizei") == 0) { 298 int arg = va_arg(argp, size_t); 299 builder.append("%u", arg); 300 } else if (strcmp(type, "GLsizeiptr") == 0) { 301 int arg = va_arg(argp, size_t); 302 builder.append("%u", arg); 303 } else if (strcmp(type, "GLuint") == 0) { 304 int arg = va_arg(argp, unsigned int); 305 builder.append("%u", arg); 306 } else { 307 builder.append("/* ??? %s */", type); 308 break; 309 } 310 } 311 builder.append(");"); 312 LOGD("%s", builder.getString()); 313 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 { \ 328 TraceGL(#_api, __VA_ARGS__); \ 329 gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \ 330 return _c->_api _argList; \ 331} 332 333extern "C" { 334#include "../trace.in" 335} 336#undef TRACE_GL_VOID 337#undef TRACE_GL 338 339#define GL_ENTRY(_r, _api, ...) Tracing_ ## _api, 340 341EGLAPI gl_hooks_t gHooksTrace = { 342 { 343 #include "entries.in" 344 }, 345 { 346 {0} 347 } 348}; 349#undef GL_ENTRY 350 351// ---------------------------------------------------------------------------- 352}; // namespace android 353// ---------------------------------------------------------------------------- 354 355#endif // EGL_TRACE 356