From: José Fonseca Date: Thu, 12 Jul 2012 12:44:59 +0000 (+0100) Subject: Merge commit '5c298db8fe117e0a445af051335aa0da91c3a31b' X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=ba3756bb4b57746e6c811e4194504e4aae004e3e;hp=537c507874cdde0b507d306ac058767f506da8e2;p=apitrace Merge commit '5c298db8fe117e0a445af051335aa0da91c3a31b' --- diff --git a/wrappers/CMakeLists.txt b/wrappers/CMakeLists.txt index 259c7fb..17aff4c 100644 --- a/wrappers/CMakeLists.txt +++ b/wrappers/CMakeLists.txt @@ -250,6 +250,7 @@ if (WIN32) add_library (wgltrace MODULE opengl32.def wgltrace.cpp glcaps.cpp + gltrace_state.cpp ) add_dependencies (wgltrace glproc) target_link_libraries (wgltrace @@ -284,6 +285,7 @@ elseif (APPLE) add_library (cgltrace SHARED cgltrace.cpp glcaps.cpp + gltrace_state.cpp ) add_dependencies (cgltrace glproc) @@ -325,6 +327,7 @@ elseif (X11_FOUND) add_library (glxtrace SHARED glxtrace.cpp glcaps.cpp + gltrace_state.cpp ) add_dependencies (glxtrace glproc) @@ -372,6 +375,7 @@ if (ENABLE_EGL AND NOT WIN32 AND NOT APPLE) add_library (egltrace SHARED egltrace.cpp glcaps.cpp + gltrace_state.cpp ) add_dependencies (egltrace glproc) diff --git a/wrappers/cgltrace.py b/wrappers/cgltrace.py index e9dee97..e7cbd7b 100644 --- a/wrappers/cgltrace.py +++ b/wrappers/cgltrace.py @@ -39,6 +39,45 @@ class CglTracer(GlTracer): # all OpenGL symbols are visible on MacOSX return True + def traceFunctionImplBody(self, function): + if function.name == 'CGLReleaseContext': + # Unlike other GL APIs like EGL or GLX, CGL will make the context + # not current if it's the current context. + print ' if (_CGLGetContextRetainCount(ctx) == 1) {' + print ' if (gltrace::releaseContext((uintptr_t)ctx)) {' + print ' if (_CGLGetCurrentContext() == ctx) {' + print ' gltrace::clearContext();' + print ' }' + print ' }' + print ' }' + + if function.name == 'CGLDestroyContext': + # The same rule applies here about the as for CGLReleaseContext. + print ' if (gltrace::releaseContext((uintptr_t)ctx)) {' + print ' if (_CGLGetCurrentContext() == ctx) {' + print ' gltrace::clearContext();' + print ' }' + print ' }' + + GlTracer.traceFunctionImplBody(self, function) + + if function.name == 'CGLCreateContext': + print ' if (_result == kCGLNoError) {' + print ' gltrace::createContext((uintptr_t)*ctx);' + print ' }' + + if function.name == 'CGLSetCurrentContext': + print ' if (_result == kCGLNoError) {' + print ' if (ctx != NULL) {' + print ' gltrace::setContext((uintptr_t)ctx);' + print ' } else {' + print ' gltrace::clearContext();' + print ' }' + print ' }' + + if function.name == 'CGLRetainContext': + print ' gltrace::retainContext((uintptr_t)ctx);' + if __name__ == '__main__': print diff --git a/wrappers/egltrace.py b/wrappers/egltrace.py index 81ae3c2..1805846 100644 --- a/wrappers/egltrace.py +++ b/wrappers/egltrace.py @@ -52,21 +52,34 @@ class EglTracer(GlTracer): def traceFunctionImplBody(self, function): GlTracer.traceFunctionImplBody(self, function) + if function.name == 'eglCreateContext': + print ' if (_result != EGL_NO_CONTEXT)' + print ' gltrace::createContext((uintptr_t)_result);' + if function.name == 'eglMakeCurrent': - print ' // update the profile' - print ' if (ctx != EGL_NO_CONTEXT) {' - print ' EGLint api = EGL_OPENGL_ES_API, version = 1;' - 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 = gltrace::PROFILE_COMPAT;' - print ' else if (version == 1)' - print ' tr->profile = gltrace::PROFILE_ES1;' - print ' else' - print ' tr->profile = gltrace::PROFILE_ES2;' + print ' if (_result) {' + print ' // update the profile' + print ' if (ctx != EGL_NO_CONTEXT) {' + print ' EGLint api = EGL_OPENGL_ES_API, version = 1;' + print ' gltrace::setContext((uintptr_t)ctx);' + 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 = gltrace::PROFILE_COMPAT;' + print ' else if (version == 1)' + print ' tr->profile = gltrace::PROFILE_ES1;' + print ' else' + print ' tr->profile = gltrace::PROFILE_ES2;' + print ' } else {' + print ' gltrace::clearContext();' + print ' }' print ' }' + if function.name == 'eglDestroyContext': + print ' if (_result) {' + print ' gltrace::releaseContext((uintptr_t)ctx);' + print ' }' if __name__ == '__main__': print '#include ' diff --git a/wrappers/gltrace.hpp b/wrappers/gltrace.hpp index cd602cb..db824bb 100644 --- a/wrappers/gltrace.hpp +++ b/wrappers/gltrace.hpp @@ -39,14 +39,39 @@ enum Profile { PROFILE_ES2, }; -struct Context { +class Context { +public: enum Profile profile; bool user_arrays; bool user_arrays_arb; bool user_arrays_nv; + unsigned retain_count; + + Context(void) : + profile(PROFILE_COMPAT), + user_arrays(false), + user_arrays_arb(false), + user_arrays_nv(false), + retain_count(0) + { } }; - -Context * + +void +createContext(uintptr_t context_id); + +void +retainContext(uintptr_t context_id); + +bool +releaseContext(uintptr_t context_id); + +void +setContext(uintptr_t context_id); + +void +clearContext(void); + +gltrace::Context * getContext(void); const GLubyte * diff --git a/wrappers/gltrace.py b/wrappers/gltrace.py index 8588d1f..901e9d7 100644 --- a/wrappers/gltrace.py +++ b/wrappers/gltrace.py @@ -121,14 +121,6 @@ class GlTracer(Tracer): print ' VERTEX_ATTRIB_NV,' print '};' print - print 'gltrace::Context *' - print 'gltrace::getContext(void)' - print '{' - print ' // TODO return the context set by other APIs (GLX, EGL, and etc.)' - 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 ' gltrace::Context *ctx = gltrace::getContext();' print ' if (ctx->user_arrays_arb || ctx->user_arrays_nv) {' diff --git a/wrappers/gltrace_state.cpp b/wrappers/gltrace_state.cpp new file mode 100644 index 0000000..cb8e08b --- /dev/null +++ b/wrappers/gltrace_state.cpp @@ -0,0 +1,156 @@ +/********************************************************************* + * + * Copyright 2012 Intel Corporation + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + *********************************************************************/ + +#include + +#include +#if defined(_MSC_VER) +#include +#else +#include +#endif + +#include +#include + +namespace gltrace { + +typedef std::tr1::shared_ptr context_ptr_t; +static std::map context_map; +static os::recursive_mutex context_map_mutex; + +class ThreadState { +public: + context_ptr_t current_context; + context_ptr_t dummy_context; /* + * For cases when there is no current + * context, but the app still calls some + * GL function that expects one. + */ + ThreadState() : dummy_context(new Context) + { + current_context = dummy_context; + } +}; + +static os::thread_specific_ptr thread_state; + +static ThreadState *get_ts(void) +{ + ThreadState *ts = thread_state.get(); + + if (!ts) { + ts = new ThreadState; + thread_state.reset(ts); + } + + return ts; +} + +static void _retainContext(context_ptr_t ctx) +{ + ctx->retain_count++; +} + +void retainContext(uintptr_t context_id) +{ + context_map_mutex.lock(); + if (context_map.find(context_id) != context_map.end()) + _retainContext(context_map[context_id]); + context_map_mutex.unlock(); +} + +static bool _releaseContext(context_ptr_t ctx) +{ + return !(--ctx->retain_count); +} + +/* + * return true if the context was destroyed, false if only its refcount + * got decreased. Note that even if the context was destroyed it may + * still live, if it's the currently selected context (by setContext). + */ +bool releaseContext(uintptr_t context_id) +{ + bool res; + + context_map_mutex.lock(); + /* + * This can potentially called (from glX) with an invalid context_id, + * so don't assert on it being valid. + */ + if (context_map.find(context_id) != context_map.end()) { + res = _releaseContext(context_map[context_id]); + if (res) + context_map.erase(context_id); + } + context_map_mutex.unlock(); + + return res; +} + +void createContext(uintptr_t context_id) +{ + context_ptr_t ctx(new Context); + + context_map_mutex.lock(); + + _retainContext(ctx); + assert(context_map.find(context_id) == context_map.end()); + context_map[context_id] = ctx; + + context_map_mutex.unlock(); +} + +void setContext(uintptr_t context_id) +{ + ThreadState *ts = get_ts(); + context_ptr_t ctx; + + context_map_mutex.lock(); + + assert(context_map.find(context_id) != context_map.end()); + ctx = context_map[context_id]; + + context_map_mutex.unlock(); + + ts->current_context = ctx; +} + +void clearContext(void) +{ + ThreadState *ts = get_ts(); + + ts->current_context = ts->dummy_context; +} + +Context *getContext(void) +{ + return get_ts()->current_context.get(); +} + +} diff --git a/wrappers/glxtrace.py b/wrappers/glxtrace.py index 029582f..ff3eb4c 100644 --- a/wrappers/glxtrace.py +++ b/wrappers/glxtrace.py @@ -45,6 +45,24 @@ class GlxTracer(GlTracer): "glXGetProcAddressARB", ] + def traceFunctionImplBody(self, function): + if function.name == 'glXDestroyContext': + print ' gltrace::releaseContext((uintptr_t)ctx);' + + GlTracer.traceFunctionImplBody(self, function) + + if function.name == 'glXCreateContext': + print ' if (_result != NULL)' + print ' gltrace::createContext((uintptr_t)_result);' + + if function.name == 'glXMakeCurrent': + print ' if (_result) {' + print ' if (ctx != NULL)' + print ' gltrace::setContext((uintptr_t)ctx);' + print ' else' + print ' gltrace::clearContext();' + print ' }' + if __name__ == '__main__': print diff --git a/wrappers/wgltrace.py b/wrappers/wgltrace.py index f345869..1b00357 100644 --- a/wrappers/wgltrace.py +++ b/wrappers/wgltrace.py @@ -39,6 +39,29 @@ class WglTracer(GlTracer): "wglGetProcAddress", ] + def traceFunctionImplBody(self, function): + if function.name == 'wglDeleteContext': + # Unlike other GL APIs like EGL or GLX, WGL will make the context + # inactive if it's currently the active context. + print ' if (_wglGetCurrentContext() == hglrc) {' + print ' gltrace::clearContext();' + print ' }' + print ' gltrace::releaseContext((uintptr_t)hglrc);' + + GlTracer.traceFunctionImplBody(self, function) + + if function.name == 'wglCreateContext': + print ' if (_result)' + print ' gltrace::createContext((uintptr_t)_result);' + + if function.name == 'wglMakeCurrent': + print ' if (_result) {' + print ' if (hglrc != NULL)' + print ' gltrace::setContext((uintptr_t)hglrc);' + print ' else' + print ' gltrace::clearContext();' + print ' }' + if __name__ == '__main__': print