]> git.cworth.org Git - apitrace/commitdiff
Merge commit '5c298db8fe117e0a445af051335aa0da91c3a31b'
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Thu, 12 Jul 2012 12:44:59 +0000 (13:44 +0100)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Thu, 12 Jul 2012 12:44:59 +0000 (13:44 +0100)
wrappers/CMakeLists.txt
wrappers/cgltrace.py
wrappers/egltrace.py
wrappers/gltrace.hpp
wrappers/gltrace.py
wrappers/gltrace_state.cpp [new file with mode: 0644]
wrappers/glxtrace.py
wrappers/wgltrace.py

index 259c7fb4759d03887ab23457d3f3227ead5d23f1..17aff4c6e3a2e3e81b7dda4d4ba5e32761bab73e 100644 (file)
@@ -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)
index e9dee975db9c212eb22883d835f2b8ede48c3aff..e7cbd7b123fa6c834e2180f04bcd769071ac2237 100644 (file)
@@ -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
index 81ae3c2ec16717ab49c524733dd892f52d5792d7..18058468049154acf0eb2d78d77a9d13368424ed 100644 (file)
@@ -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 <stdlib.h>'
index cd602cb834c1ade00f1036676bfd7b53fc2b885c..db824bb315ffd5f1044b3752104b83e7de466fac 100644 (file)
@@ -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 *
index 8588d1f826473f5f6cad77024b6964a8d8627d96..901e9d749c1d096ca749526b467b6afae17bd6f8 100644 (file)
@@ -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 (file)
index 0000000..cb8e08b
--- /dev/null
@@ -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 <assert.h>
+
+#include <map>
+#if defined(_MSC_VER)
+#include <memory>
+#else
+#include <tr1/memory>
+#endif
+
+#include <gltrace.hpp>
+#include <os_thread.hpp>
+
+namespace gltrace {
+
+typedef std::tr1::shared_ptr<Context> context_ptr_t;
+static std::map<uintptr_t, context_ptr_t> 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<struct ThreadState> 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();
+}
+
+}
index 029582f8981da99b5da3e725fcaf2af42f3efc1b..ff3eb4cd62652ec216b0e83e516aefd011c41241 100644 (file)
@@ -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
index f345869b684f4e6090ad5c169d02f2699a272903..1b0035799fdd648f32bda397b2e4ddb5f86c67e4 100644 (file)
@@ -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