[PATCH v2 08/18] mt trace: track GL context create/destroy calls

Imre Deak imre.deak at intel.com
Tue May 15 07:11:03 PDT 2012


This is needed for muti-threaded tracing to work properly.

Tracing multi-threaded GL apps requires that we track the lifetime of
the GL context objects and store thread specific state like the currently
active GL context on thread-local memory area.

Signed-off-by: Imre Deak <imre.deak at intel.com>
---
 wrappers/egltrace.py       |    5 +++
 wrappers/gltrace.hpp       |   17 +++++++++-
 wrappers/gltrace_state.cpp |   71 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 91 insertions(+), 2 deletions(-)
 create mode 100644 wrappers/gltrace_state.cpp

diff --git a/wrappers/egltrace.py b/wrappers/egltrace.py
index 4858e2f..b958a0c 100644
--- a/wrappers/egltrace.py
+++ b/wrappers/egltrace.py
@@ -52,6 +52,9 @@ class EglTracer(GlTracer):
     def traceFunctionImplBody(self, function):
         GlTracer.traceFunctionImplBody(self, function)
 
+        if function.name == 'eglCreateContext':
+            print '    gltrace::createContext((unsigned long)_result);'
+
         if function.name == 'eglMakeCurrent':
             print '    // update the profile'
             print '    if (ctx != EGL_NO_CONTEXT) {'
@@ -67,6 +70,8 @@ class EglTracer(GlTracer):
             print '            tr->profile = gltrace::PROFILE_ES2;'
             print '    }'
 
+        if function.name == 'eglDestroyContext':
+            print '    gltrace::destroyContext((unsigned long)_result);'
 
 if __name__ == '__main__':
     print '#include <stdlib.h>'
diff --git a/wrappers/gltrace.hpp b/wrappers/gltrace.hpp
index cd602cb..627b2f7 100644
--- a/wrappers/gltrace.hpp
+++ b/wrappers/gltrace.hpp
@@ -39,13 +39,26 @@ enum Profile {
     PROFILE_ES2,
 };
 
-struct Context {
+class Context {
+public:
     enum Profile profile;
     bool user_arrays;
     bool user_arrays_arb;
     bool user_arrays_nv;
+
+    Context(void) : profile(PROFILE_COMPAT), user_arrays(false),
+                    user_arrays_arb(false), user_arrays_nv(false) { }
 };
-    
+
+void
+createContext(unsigned long context_id);
+
+void
+destroyContext(unsigned long context_id);
+
+void
+setContext(unsigned long context_id);
+
 Context *
 getContext(void);
 
diff --git a/wrappers/gltrace_state.cpp b/wrappers/gltrace_state.cpp
new file mode 100644
index 0000000..cce4e14
--- /dev/null
+++ b/wrappers/gltrace_state.cpp
@@ -0,0 +1,71 @@
+#include <gltrace.hpp>
+#include <os_thread.hpp>
+#include <assert.h>
+
+namespace gltrace {
+
+static std::map<unsigned long, Context *> context_map;
+
+class ThreadState {
+public:
+	Context *current_context;
+	Context dummy_context;
+
+	ThreadState(void) : current_context(NULL) { }
+};
+
+static os::thread_specific_ptr<struct ThreadState> thread_state;
+
+static ThreadState *get_ts(void)
+{
+	struct ThreadState *ts = thread_state.get();
+
+	if (!ts) {
+		ts = new ThreadState;
+		thread_state.reset(ts);
+	}
+
+	return ts;
+}
+
+void createContext(unsigned long context_id)
+{
+	assert(context_map.find(context_id) == context_map.end());
+	context_map[context_id] = new Context();
+}
+
+void destroyContext(unsigned long context_id)
+{
+	struct ThreadState *ts = get_ts();
+	Context *ctx;
+
+	ctx = context_map[context_id];
+	if (ctx == ts->current_context)
+		ts->current_context = NULL;
+
+	context_map.erase(context_id);
+	delete ctx;
+}
+
+void setContext(unsigned long context_id)
+{
+	struct ThreadState *ts = get_ts();
+
+	ts->current_context = context_map[context_id];
+}
+
+Context *getContext(void)
+{
+	struct ThreadState *ts = get_ts();
+	Context *ctx = ts->current_context;
+
+	/*
+	 * We are called from some gl* function at which point the behaviour
+	 * is undefined if there is no active context. So in this case return
+	 * a dummy context so that at least the apitrace internal book-keeping
+	 * - which is context dependent - won't crash.
+	 */
+	return ctx ? ctx : &ts->dummy_context;
+}
+
+}
-- 
1.7.5.4



More information about the apitrace mailing list