123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464 |
- /*
- ** Copyright 2010, The Android Open Source Project
- **
- ** Licensed under the Apache License, Version 2.0 (the "License");
- ** you may not use this file except in compliance with the License.
- ** You may obtain a copy of the License at
- **
- ** http://www.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing, software
- ** distributed under the License is distributed on an "AS IS" BASIS,
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
- #if EGL_TRACE
- #include <stdarg.h>
- #include <stdlib.h>
- #include <EGL/egl.h>
- #include <EGL/eglext.h>
- #include <cutils/log.h>
- #define ATRACE_TAG ATRACE_TAG_GRAPHICS
- #include <utils/Trace.h>
- #include <utils/CallStack.h>
- #include "egl_tls.h"
- #include "hooks.h"
- // ----------------------------------------------------------------------------
- namespace android {
- // ----------------------------------------------------------------------------
- struct GLenumString {
- // The GL_TIMEOUT_IGNORED "enum" doesn't fit in a GLenum, so use GLuint64
- GLuint64 e;
- const char* s;
- };
- #undef GL_ENUM
- #define GL_ENUM(VAL,NAME) {VAL, #NAME},
- static GLenumString g_enumnames[] = {
- #include "enums.in"
- };
- #undef GL_ENUM
- static int compareGLEnum(const void* a, const void* b) {
- return ((const GLenumString*) a)->e - ((const GLenumString*) b)->e;
- }
- static const char* GLEnumToString(GLenum e) {
- GLenumString key = {e, ""};
- const GLenumString* result = (const GLenumString*) bsearch(
- &key, g_enumnames,
- sizeof(g_enumnames) / sizeof(g_enumnames[0]),
- sizeof(g_enumnames[0]), compareGLEnum);
- if (result) {
- return result->s;
- }
- return NULL;
- }
- static const char* GLbooleanToString(GLboolean arg) {
- return arg ? "GL_TRUE" : "GL_FALSE";
- }
- static GLenumString g_bitfieldNames[] = {
- {0x00004000, "GL_COLOR_BUFFER_BIT"},
- {0x00000400, "GL_STENCIL_BUFFER_BIT"},
- {0x00000100, "GL_DEPTH_BUFFER_BIT"}
- };
- class StringBuilder {
- static const int lineSize = 500;
- char line[lineSize];
- int line_index;
- public:
- StringBuilder() {
- line_index = 0;
- line[0] = '\0';
- }
- void append(const char* fmt, ...) {
- va_list argp;
- va_start(argp, fmt);
- line_index += vsnprintf(line + line_index, lineSize-line_index, fmt, argp);
- va_end(argp);
- }
- const char* getString() {
- line_index = 0;
- line[lineSize-1] = '\0';
- return line;
- }
- };
- static void TraceGLShaderSource(GLuint shader, GLsizei count,
- const GLchar** string, const GLint* length) {
- ALOGD("const char* shaderSrc[] = {");
- for (GLsizei i = 0; i < count; i++) {
- const char* comma = i < count-1 ? "," : "";
- const GLchar* s = string[i];
- if (length) {
- GLint len = length[i];
- ALOGD(" \"%*s\"%s", len, s, comma);
- } else {
- ALOGD(" \"%s\"%s", s, comma);
- }
- }
- ALOGD("};");
- if (length) {
- ALOGD("const GLint* shaderLength[] = {");
- for (GLsizei i = 0; i < count; i++) {
- const char* comma = i < count-1 ? "," : "";
- GLint len = length[i];
- ALOGD(" \"%d\"%s", len, comma);
- }
- ALOGD("};");
- ALOGD("glShaderSource(%u, %u, shaderSrc, shaderLength);",
- shader, count);
- } else {
- ALOGD("glShaderSource(%u, %u, shaderSrc, (const GLint*) 0);",
- shader, count);
- }
- }
- static void TraceValue(int elementCount, char type,
- GLsizei chunkCount, GLsizei chunkSize, const void* value) {
- StringBuilder stringBuilder;
- GLsizei count = chunkCount * chunkSize;
- bool isFloat = type == 'f';
- const char* typeString = isFloat ? "GLfloat" : "GLint";
- ALOGD("const %s value[] = {", typeString);
- for (GLsizei i = 0; i < count; i++) {
- StringBuilder builder;
- builder.append(" ");
- for (int e = 0; e < elementCount; e++) {
- const char* comma = ", ";
- if (e == elementCount-1) {
- if (i == count - 1) {
- comma = "";
- } else {
- comma = ",";
- }
- }
- if (isFloat) {
- builder.append("%g%s", * (GLfloat*) value, comma);
- value = (void*) (((GLfloat*) value) + 1);
- } else {
- builder.append("%d%s", * (GLint*) value, comma);
- value = (void*) (((GLint*) value) + 1);
- }
- }
- ALOGD("%s", builder.getString());
- if (chunkSize > 1 && i < count-1
- && (i % chunkSize) == (chunkSize-1)) {
- ALOGD("%s", ""); // Print a blank line.
- }
- }
- ALOGD("};");
- }
- static void TraceUniformv(int elementCount, char type,
- GLuint location, GLsizei count, const void* value) {
- TraceValue(elementCount, type, count, 1, value);
- ALOGD("glUniform%d%c(%u, %u, value);", elementCount, type, location, count);
- }
- static void TraceUniformMatrix(int matrixSideLength,
- GLuint location, GLsizei count, GLboolean transpose, const void* value) {
- TraceValue(matrixSideLength, 'f', count, matrixSideLength, value);
- ALOGD("glUniformMatrix%dfv(%u, %u, %s, value);", matrixSideLength, location, count,
- GLbooleanToString(transpose));
- }
- static void TraceGL(const char* name, int numArgs, ...) {
- va_list argp;
- va_start(argp, numArgs);
- int nameLen = strlen(name);
- // glShaderSource
- if (nameLen == 14 && strcmp(name, "glShaderSource") == 0) {
- va_arg(argp, const char*);
- GLuint shader = va_arg(argp, GLuint);
- va_arg(argp, const char*);
- GLsizei count = va_arg(argp, GLsizei);
- va_arg(argp, const char*);
- const GLchar** string = (const GLchar**) va_arg(argp, void*);
- va_arg(argp, const char*);
- const GLint* length = (const GLint*) va_arg(argp, void*);
- va_end(argp);
- TraceGLShaderSource(shader, count, string, length);
- return;
- }
- // glUniformXXv
- if (nameLen == 12 && strncmp(name, "glUniform", 9) == 0 && name[11] == 'v') {
- int elementCount = name[9] - '0'; // 1..4
- char type = name[10]; // 'f' or 'i'
- va_arg(argp, const char*);
- GLuint location = va_arg(argp, GLuint);
- va_arg(argp, const char*);
- GLsizei count = va_arg(argp, GLsizei);
- va_arg(argp, const char*);
- const void* value = (const void*) va_arg(argp, void*);
- va_end(argp);
- TraceUniformv(elementCount, type, location, count, value);
- return;
- }
- // glUniformMatrixXfv
- if (nameLen == 18 && strncmp(name, "glUniformMatrix", 15) == 0
- && name[16] == 'f' && name[17] == 'v') {
- int matrixSideLength = name[15] - '0'; // 2..4
- va_arg(argp, const char*);
- GLuint location = va_arg(argp, GLuint);
- va_arg(argp, const char*);
- GLsizei count = va_arg(argp, GLsizei);
- va_arg(argp, const char*);
- GLboolean transpose = (GLboolean) va_arg(argp, int);
- va_arg(argp, const char*);
- const void* value = (const void*) va_arg(argp, void*);
- va_end(argp);
- TraceUniformMatrix(matrixSideLength, location, count, transpose, value);
- return;
- }
- StringBuilder builder;
- builder.append("%s(", name);
- for (int i = 0; i < numArgs; i++) {
- if (i > 0) {
- builder.append(", ");
- }
- const char* type = va_arg(argp, const char*);
- bool isPtr = type[strlen(type)-1] == '*'
- || strcmp(type, "GLeglImageOES") == 0;
- if (isPtr) {
- const void* arg = va_arg(argp, const void*);
- builder.append("(%s) 0x%08x", type, (size_t) arg);
- } else if (strcmp(type, "GLbitfield") == 0) {
- size_t arg = va_arg(argp, size_t);
- bool first = true;
- for (size_t i = 0; i < sizeof(g_bitfieldNames) / sizeof(g_bitfieldNames[0]); i++) {
- const GLenumString* b = &g_bitfieldNames[i];
- if (b->e & arg) {
- if (first) {
- first = false;
- } else {
- builder.append(" | ");
- }
- builder.append("%s", b->s);
- arg &= ~b->e;
- }
- }
- if (first || arg != 0) {
- if (!first) {
- builder.append(" | ");
- }
- builder.append("0x%08x", arg);
- }
- } else if (strcmp(type, "GLboolean") == 0) {
- GLboolean arg = va_arg(argp, int);
- builder.append("%s", GLbooleanToString(arg));
- } else if (strcmp(type, "GLclampf") == 0) {
- double arg = va_arg(argp, double);
- builder.append("%g", arg);
- } else if (strcmp(type, "GLenum") == 0) {
- GLenum arg = va_arg(argp, int);
- const char* s = GLEnumToString(arg);
- if (s) {
- builder.append("%s", s);
- } else {
- builder.append("0x%x", arg);
- }
- } else if (strcmp(type, "GLfixed") == 0) {
- int arg = va_arg(argp, int);
- builder.append("0x%08x", arg);
- } else if (strcmp(type, "GLfloat") == 0) {
- double arg = va_arg(argp, double);
- builder.append("%g", arg);
- } else if (strcmp(type, "GLint") == 0) {
- int arg = va_arg(argp, int);
- const char* s = NULL;
- if (strcmp(name, "glTexParameteri") == 0) {
- s = GLEnumToString(arg);
- }
- if (s) {
- builder.append("%s", s);
- } else {
- builder.append("%d", arg);
- }
- } else if (strcmp(type, "GLintptr") == 0) {
- int arg = va_arg(argp, unsigned int);
- builder.append("%u", arg);
- } else if (strcmp(type, "GLsizei") == 0) {
- int arg = va_arg(argp, size_t);
- builder.append("%u", arg);
- } else if (strcmp(type, "GLsizeiptr") == 0) {
- int arg = va_arg(argp, size_t);
- builder.append("%u", arg);
- } else if (strcmp(type, "GLuint") == 0) {
- int arg = va_arg(argp, unsigned int);
- builder.append("%u", arg);
- } else {
- builder.append("/* ??? %s */", type);
- break;
- }
- }
- builder.append(");");
- ALOGD("%s", builder.getString());
- va_end(argp);
- }
- ///////////////////////////////////////////////////////////////////////////
- // Log trace
- ///////////////////////////////////////////////////////////////////////////
- #undef TRACE_GL_VOID
- #undef TRACE_GL
- #define TRACE_GL_VOID(_api, _args, _argList, ...) \
- static void Tracing_ ## _api _args { \
- TraceGL(#_api, __VA_ARGS__); \
- gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
- _c->_api _argList; \
- }
- #define TRACE_GL(_type, _api, _args, _argList, ...) \
- static _type Tracing_ ## _api _args { \
- TraceGL(#_api, __VA_ARGS__); \
- gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
- return _c->_api _argList; \
- }
- extern "C" {
- #include "../trace.in"
- }
- #undef TRACE_GL_VOID
- #undef TRACE_GL
- #define GL_ENTRY(_r, _api, ...) Tracing_ ## _api,
- EGLAPI gl_hooks_t gHooksTrace = {
- {
- #include "entries.in"
- },
- {
- {0}
- }
- };
- #undef GL_ENTRY
- #undef TRACE_GL_VOID
- #undef TRACE_GL
- ///////////////////////////////////////////////////////////////////////////
- // Systrace
- ///////////////////////////////////////////////////////////////////////////
- #undef TRACE_GL_VOID
- #undef TRACE_GL
- #define TRACE_GL_VOID(_api, _args, _argList, ...) \
- static void Systrace_ ## _api _args { \
- ATRACE_NAME(#_api); \
- gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
- _c->_api _argList; \
- }
- #define TRACE_GL(_type, _api, _args, _argList, ...) \
- static _type Systrace_ ## _api _args { \
- ATRACE_NAME(#_api); \
- gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
- return _c->_api _argList; \
- }
- extern "C" {
- #include "../trace.in"
- }
- #undef TRACE_GL_VOID
- #undef TRACE_GL
- #define GL_ENTRY(_r, _api, ...) Systrace_ ## _api,
- EGLAPI gl_hooks_t gHooksSystrace = {
- {
- #include "entries.in"
- },
- {
- {0}
- }
- };
- #undef GL_ENTRY
- ///////////////////////////////////////////////////////////////////////////
- //
- ///////////////////////////////////////////////////////////////////////////
- #undef TRACE_GL_VOID
- #undef TRACE_GL
- #define CHECK_ERROR(_c, _api) \
- GLenum status = GL_NO_ERROR; \
- bool error = false; \
- while ((status = _c->glGetError()) != GL_NO_ERROR) { \
- ALOGD("[" #_api "] 0x%x", status); \
- error = true; \
- } \
- if (error) { \
- CallStack s; \
- s.update(); \
- s.log("glGetError:" #_api); \
- } \
- #define TRACE_GL_VOID(_api, _args, _argList, ...) \
- static void ErrorTrace_ ## _api _args { \
- gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
- _c->_api _argList; \
- CHECK_ERROR(_c, _api); \
- }
- #define TRACE_GL(_type, _api, _args, _argList, ...) \
- static _type ErrorTrace_ ## _api _args { \
- gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl; \
- _type _r = _c->_api _argList; \
- CHECK_ERROR(_c, _api); \
- return _r; \
- }
- extern "C" {
- #include "../trace.in"
- }
- #undef TRACE_GL_VOID
- #undef TRACE_GL
- #define GL_ENTRY(_r, _api, ...) ErrorTrace_ ## _api,
- EGLAPI gl_hooks_t gHooksErrorTrace = {
- {
- #include "entries.in"
- },
- {
- {0}
- }
- };
- #undef GL_ENTRY
- #undef CHECK_ERROR
- #undef TRACE_GL_VOID
- #undef TRACE_GL
- // ----------------------------------------------------------------------------
- }; // namespace android
- // ----------------------------------------------------------------------------
- #endif // EGL_TRACE
|