From: José Fonseca Date: Wed, 15 Feb 2012 23:33:35 +0000 (+0000) Subject: Implmenet GL_EXT_debug_marker on OpenGL ES contexts X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;ds=sidebyside;h=f028a8fe0d8bef4a0c27115798d3e9d11703b09b;p=apitrace Implmenet GL_EXT_debug_marker on OpenGL ES contexts --- diff --git a/README.markdown b/README.markdown index 732f935..26f89e4 100644 --- a/README.markdown +++ b/README.markdown @@ -140,10 +140,10 @@ Note that although Mac OS X has an `LD_PRELOAD` equivalent, page for more details about these environment flags. -Emitting annotations to the trace from GL applications ------------------------------------------------------- +Emitting annotations to the trace +--------------------------------- -You can emit string and frame annotations through the +From OpenGL applications you can embed annotations in the trace file through the [`GL_GREMEDY_string_marker`](http://www.opengl.org/registry/specs/GREMEDY/string_marker.txt) and [`GL_GREMEDY_frame_terminator`](http://www.opengl.org/registry/specs/GREMEDY/frame_terminator.txt) @@ -173,6 +173,15 @@ detect and use GL extensions, you could easily accomplish this by doing: This has the added advantage of working equally well with gDEBugger. +From OpenGL ES applications you can embed annotations in the trace file through the +[`GL_EXT_debug_marker`](http://www.khronos.org/registry/gles/extensions/EXT/EXT_debug_marker.txt) +extension. + + +For Direct3D applications you can follow the same procedure used for +[instrumenting an application for PIX](http://technet.microsoft.com/en-us/query/ee417250) + + Dump GL state at a particular call ---------------------------------- diff --git a/egltrace.py b/egltrace.py index e16367a..1787c0b 100644 --- a/egltrace.py +++ b/egltrace.py @@ -53,15 +53,15 @@ class EglTracer(GlTracer): print ' // update the profile' print ' if (ctx != EGL_NO_CONTEXT) {' print ' EGLint api = EGL_OPENGL_ES_API, version = 1;' - print ' tracer_context *tr = __get_context();' + print ' gltrace::Context *tr = gltrace::getContext();' print ' __eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_TYPE, &api);' print ' __eglQueryContext(dpy, ctx, EGL_CONTEXT_CLIENT_VERSION, &version);' print ' if (api == EGL_OPENGL_API)' - print ' tr->profile = PROFILE_COMPAT;' + print ' tr->profile = gltrace::PROFILE_COMPAT;' print ' else if (version == 1)' - print ' tr->profile = PROFILE_ES1;' + print ' tr->profile = gltrace::PROFILE_ES1;' print ' else' - print ' tr->profile = PROFILE_ES2;' + print ' tr->profile = gltrace::PROFILE_ES2;' print ' }' def wrapRet(self, function, instance): diff --git a/glcaps.cpp b/glcaps.cpp index 2f16b63..f6f70f3 100644 --- a/glcaps.cpp +++ b/glcaps.cpp @@ -53,11 +53,55 @@ static ExtensionsMap extensionsMap; // Additional extensions to be advertised -static const char *extra_extensions[] = { +static const char * +extraExtension_stringsFull[] = { "GL_GREMEDY_string_marker", "GL_GREMEDY_frame_terminator", }; -#define NUM_EXTRA_EXTENSIONS (sizeof(extra_extensions)/sizeof(extra_extensions[0])) + +static const char * +extraExtension_stringsES[] = { + "GL_EXT_debug_marker", +}; + +// Description of additional extensions we want to advertise +struct ExtensionsDesc +{ + unsigned numStrings; + const char **strings; +}; + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) + +const struct ExtensionsDesc +extraExtensionsFull = { + ARRAY_SIZE(extraExtension_stringsFull), + extraExtension_stringsFull +}; + +const struct ExtensionsDesc +extraExtensionsES = { + ARRAY_SIZE(extraExtension_stringsES), + extraExtension_stringsES +}; + + +const struct ExtensionsDesc * +getExtraExtensions(void) +{ + Context *ctx = getContext(); + + switch (ctx->profile) { + case PROFILE_COMPAT: + return &extraExtensionsFull; + case PROFILE_ES1: + case PROFILE_ES2: + return &extraExtensionsES; + default: + assert(0); + return &extraExtensionsFull; + } +} /** @@ -66,6 +110,7 @@ static const char *extra_extensions[] = { static const char * overrideExtensionsString(const char *extensions) { + const ExtensionsDesc *desc = getExtraExtensions(); size_t i; ExtensionsMap::const_iterator it = extensionsMap.find(extensions); @@ -73,46 +118,46 @@ overrideExtensionsString(const char *extensions) return it->second; } - size_t extensions_len = strlen(extensions); + size_t extensionsLen = strlen(extensions); - size_t extra_extensions_len = 0; - for (i = 0; i < NUM_EXTRA_EXTENSIONS; ++i) { - const char * extra_extension = extra_extensions[i]; - size_t extra_extension_len = strlen(extra_extension); - extra_extensions_len += extra_extension_len + 1; + size_t extraExtensionsLen = 0; + for (i = 0; i < desc->numStrings; ++i) { + const char * extraExtension = desc->strings[i]; + size_t extraExtensionLen = strlen(extraExtension); + extraExtensionsLen += extraExtensionLen + 1; } // We use malloc memory instead of a std::string because we need to ensure // that extensions strings will not move in memory as the extensionsMap is // updated. - size_t new_extensions_len = extensions_len + 1 + extra_extensions_len + 1; - char *new_extensions = (char *)malloc(new_extensions_len); - if (!new_extensions) { + size_t newExtensionsLen = extensionsLen + 1 + extraExtensionsLen + 1; + char *newExtensions = (char *)malloc(newExtensionsLen); + if (!newExtensions) { return extensions; } - if (extensions_len) { - memcpy(new_extensions, extensions, extensions_len); + if (extensionsLen) { + memcpy(newExtensions, extensions, extensionsLen); // Add space separator if necessary - if (new_extensions[extensions_len - 1] != ' ') { - new_extensions[extensions_len++] = ' '; + if (newExtensions[extensionsLen - 1] != ' ') { + newExtensions[extensionsLen++] = ' '; } } - for (i = 0; i < NUM_EXTRA_EXTENSIONS; ++i) { - const char * extra_extension = extra_extensions[i]; - size_t extra_extension_len = strlen(extra_extension); - memcpy(new_extensions + extensions_len, extra_extension, extra_extension_len); - extensions_len += extra_extension_len; - new_extensions[extensions_len++] = ' '; + for (i = 0; i < desc->numStrings; ++i) { + const char * extraExtension = desc->strings[i]; + size_t extraExtensionLen = strlen(extraExtension); + memcpy(newExtensions + extensionsLen, extraExtension, extraExtensionLen); + extensionsLen += extraExtensionLen; + newExtensions[extensionsLen++] = ' '; } - new_extensions[extensions_len++] = '\0'; - assert(extensions_len <= new_extensions_len); + newExtensions[extensionsLen++] = '\0'; + assert(extensionsLen <= newExtensionsLen); - extensionsMap[extensions] = new_extensions; + extensionsMap[extensions] = newExtensions; - return new_extensions; + return newExtensions; } @@ -143,7 +188,10 @@ __glGetIntegerv_override(GLenum pname, GLint *params) if (params) { switch (pname) { case GL_NUM_EXTENSIONS: - *params += NUM_EXTRA_EXTENSIONS; + { + const ExtensionsDesc *desc = getExtraExtensions(); + *params += desc->numStrings; + } break; default: break; @@ -158,10 +206,11 @@ __glGetStringi_override(GLenum name, GLuint index) switch (name) { case GL_EXTENSIONS: { - GLint num_extensions = 0; - __glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); - if ((GLuint)num_extensions <= index && index < (GLuint)num_extensions + NUM_EXTRA_EXTENSIONS) { - return (const GLubyte *)extra_extensions[index - (GLuint)num_extensions]; + const ExtensionsDesc *desc = getExtraExtensions(); + GLint numExtensions = 0; + __glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions); + if ((GLuint)numExtensions <= index && index < (GLuint)numExtensions + desc->numStrings) { + return (const GLubyte *)desc->strings[index - (GLuint)numExtensions]; } } break; diff --git a/gltrace.hpp b/gltrace.hpp index 53c8039..e4fefc3 100644 --- a/gltrace.hpp +++ b/gltrace.hpp @@ -33,6 +33,22 @@ namespace gltrace { +enum Profile { + PROFILE_COMPAT, + PROFILE_ES1, + PROFILE_ES2, +}; + +struct Context { + enum Profile profile; + bool user_arrays; + bool user_arrays_arb; + bool user_arrays_nv; +}; + +Context * +getContext(void); + const GLubyte * __glGetString_override(GLenum name); diff --git a/gltrace.py b/gltrace.py index d2babe4..2125ac3 100644 --- a/gltrace.py +++ b/gltrace.py @@ -112,19 +112,6 @@ class GlTracer(Tracer): print '#include "gltrace.hpp"' print - print 'enum tracer_context_profile {' - print ' PROFILE_COMPAT,' - print ' PROFILE_ES1,' - print ' PROFILE_ES2,' - print '};' - print - print 'struct tracer_context {' - print ' enum tracer_context_profile profile;' - print ' bool user_arrays;' - print ' bool user_arrays_arb;' - print ' bool user_arrays_nv;' - print '};' - print # Which glVertexAttrib* variant to use print 'enum vertex_attrib {' @@ -133,15 +120,16 @@ class GlTracer(Tracer): print ' VERTEX_ATTRIB_NV,' print '};' print - print 'static tracer_context *__get_context(void)' + print 'gltrace::Context *' + print 'gltrace::getContext(void)' print '{' print ' // TODO return the context set by other APIs (GLX, EGL, and etc.)' - print ' static tracer_context __ctx = { PROFILE_COMPAT, false, false, false };' + print ' static gltrace::Context __ctx = { gltrace::PROFILE_COMPAT, false, false, false };' print ' return &__ctx;' print '}' print print 'static vertex_attrib __get_vertex_attrib(void) {' - print ' tracer_context *ctx = __get_context();' + print ' gltrace::Context *ctx = gltrace::getContext();' print ' if (ctx->user_arrays_arb || ctx->user_arrays_nv) {' print ' GLboolean __vertex_program = GL_FALSE;' print ' __glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &__vertex_program);' @@ -163,7 +151,7 @@ class GlTracer(Tracer): # Whether we need user arrays print 'static inline bool __need_user_arrays(void)' print '{' - print ' tracer_context *ctx = __get_context();' + print ' gltrace::Context *ctx = gltrace::getContext();' print ' if (!ctx->user_arrays) {' print ' return false;' print ' }' @@ -171,9 +159,9 @@ class GlTracer(Tracer): for camelcase_name, uppercase_name in self.arrays: # in which profile is the array available? - profile_check = 'ctx->profile == PROFILE_COMPAT' + profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT' if camelcase_name in self.arrays_es1: - profile_check = '(' + profile_check + ' || ctx->profile == PROFILE_ES1)'; + profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)'; function_name = 'gl%sPointer' % camelcase_name enable_name = 'GL_%s_ARRAY' % uppercase_name @@ -194,7 +182,7 @@ class GlTracer(Tracer): print print ' // ES1 does not support generic vertex attributes' - print ' if (ctx->profile == PROFILE_ES1)' + print ' if (ctx->profile == gltrace::PROFILE_ES1)' print ' return false;' print print ' vertex_attrib __vertex_attrib = __get_vertex_attrib();' @@ -322,8 +310,8 @@ class GlTracer(Tracer): # states such as GL_UNPACK_ROW_LENGTH are not available in GLES print 'static inline bool' print 'can_unpack_subimage(void) {' - print ' tracer_context *ctx = __get_context();' - print ' return (ctx->profile == PROFILE_COMPAT);' + print ' gltrace::Context *ctx = gltrace::getContext();' + print ' return (ctx->profile == gltrace::PROFILE_COMPAT);' print '}' print @@ -412,7 +400,7 @@ class GlTracer(Tracer): print ' GLint __array_buffer = 0;' print ' __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);' print ' if (!__array_buffer) {' - print ' tracer_context *ctx = __get_context();' + print ' gltrace::Context *ctx = gltrace::getContext();' print ' ctx->user_arrays = true;' if function.name == "glVertexAttribPointerARB": print ' ctx->user_arrays_arb = true;' @@ -548,9 +536,15 @@ class GlTracer(Tracer): Tracer.traceFunctionImplBody(self, function) - gremedy_functions = [ + marker_functions = [ + # GL_GREMEDY_string_marker 'glStringMarkerGREMEDY', + # GL_GREMEDY_frame_terminator 'glFrameTerminatorGREMEDY', + # GL_EXT_debug_marker + 'glInsertEventMarkerEXT', + 'glPushGroupMarkerEXT', + 'glPopGroupMarkerEXT', ] def invokeFunction(self, function): @@ -558,18 +552,20 @@ class GlTracer(Tracer): # These functions have been dispatched already return - # We implement the GREMEDY extensions, not the driver - if function.name in self.gremedy_functions: + # We implement GL_EXT_debug_marker, GL_GREMEDY_*, etc., and not the + # driver + if function.name in self.marker_functions: return if function.name in ('glXGetProcAddress', 'glXGetProcAddressARB', 'wglGetProcAddress'): - if_ = 'if' - for gremedy_function in self.gremedy_functions: - print ' %s (strcmp("%s", (const char *)%s) == 0) {' % (if_, gremedy_function, function.args[0].name) - print ' __result = (%s)&%s;' % (function.type, gremedy_function) - print ' }' - if_ = 'else if' - print ' else {' + else_ = '' + for marker_function in self.marker_functions: + if self.api.get_function_by_name(marker_function): + print ' %sif (strcmp("%s", (const char *)%s) == 0) {' % (else_, marker_function, function.args[0].name) + print ' __result = (%s)&%s;' % (function.type, marker_function) + print ' }' + else_ = 'else ' + print ' %s{' % else_ Tracer.invokeFunction(self, function) print ' }' return @@ -698,9 +694,9 @@ class GlTracer(Tracer): or (isinstance(arg.type, stdapi.Const) \ and isinstance(arg.type.type, stdapi.Blob))): print ' {' - print ' tracer_context *ctx = __get_context();' + print ' gltrace::Context *ctx = gltrace::getContext();' print ' GLint __unpack_buffer = 0;' - print ' if (ctx->profile == PROFILE_COMPAT)' + print ' if (ctx->profile == gltrace::PROFILE_COMPAT)' print ' __glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &__unpack_buffer);' print ' if (__unpack_buffer) {' print ' trace::localWriter.writeOpaque(%s);' % arg.name @@ -734,13 +730,13 @@ class GlTracer(Tracer): # update the state print 'static void __trace_user_arrays(GLuint maxindex)' print '{' - print ' tracer_context *ctx = __get_context();' + print ' gltrace::Context *ctx = gltrace::getContext();' for camelcase_name, uppercase_name in self.arrays: # in which profile is the array available? - profile_check = 'ctx->profile == PROFILE_COMPAT' + profile_check = 'ctx->profile == gltrace::PROFILE_COMPAT' if camelcase_name in self.arrays_es1: - profile_check = '(' + profile_check + ' || ctx->profile == PROFILE_ES1)'; + profile_check = '(' + profile_check + ' || ctx->profile == gltrace::PROFILE_ES1)'; function_name = 'gl%sPointer' % camelcase_name enable_name = 'GL_%s_ARRAY' % uppercase_name @@ -799,7 +795,7 @@ class GlTracer(Tracer): # alias, and they need to be considered independently. # print ' // ES1 does not support generic vertex attributes' - print ' if (ctx->profile == PROFILE_ES1)' + print ' if (ctx->profile == gltrace::PROFILE_ES1)' print ' return;' print print ' vertex_attrib __vertex_attrib = __get_vertex_attrib();' @@ -878,7 +874,7 @@ class GlTracer(Tracer): print ' GLint client_active_texture = 0;' print ' __glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &client_active_texture);' print ' GLint max_texture_coords = 0;' - print ' if (ctx->profile == PROFILE_COMPAT)' + print ' if (ctx->profile == gltrace::PROFILE_COMPAT)' print ' __glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);' print ' else' print ' __glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_coords);'