Bug 730079 - Move sCurrentGLContext to TLS to support off main thread GLDebug. r=joe
authorBenoit Girard <b56girard@gmail.com>
Fri, 24 Feb 2012 18:17:27 -0500
changeset 89255 e1763649ed9472d940219b7fddfba7366117158f
parent 89254 eabfd284eb428c009d8c554df61f7ded9e49977c
child 89256 e1c388532626f081c1fcf8f6f7216c7ed7d8bbb5
push id22242
push userkgupta@mozilla.com
push dateWed, 14 Mar 2012 15:19:09 +0000
treeherdermozilla-central@936ef50fa498 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjoe
bugs730079
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 730079 - Move sCurrentGLContext to TLS to support off main thread GLDebug. r=joe
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextProviderEGL.cpp
gfx/thebes/gfxPlatform.cpp
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -58,18 +58,17 @@
 #include "mozilla/Util.h" // for DebugOnly
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace gl {
 
 #ifdef DEBUG
-// see comment near declaration in GLContext.h. Should be thread-local.
-GLContext* GLContext::sCurrentGLContext = nsnull;
+PRUintn GLContext::sCurrentGLContextTLS = -1;
 #endif
 
 PRUint32 GLContext::sDebugMode = 0;
 
 // define this here since it's global to GLContextProvider, not any
 // specific implementation
 const ContextFormat ContextFormat::BasicRGBA32Format(ContextFormat::BasicRGBA32);
 
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -597,19 +597,25 @@ public:
         ContextTypeEGL,
         ContextTypeOSMesa
     };
 
     virtual GLContextType GetContextType() { return ContextTypeUnknown; }
 
     virtual bool MakeCurrentImpl(bool aForce = false) = 0;
 
+#ifdef DEBUG
+    static void StaticInit() {
+        PR_NewThreadPrivateIndex(&sCurrentGLContextTLS, NULL);
+    }
+#endif
+
     bool MakeCurrent(bool aForce = false) {
 #ifdef DEBUG
-        sCurrentGLContext = this;
+        PR_SetThreadPrivate(sCurrentGLContextTLS, this);
 #endif
         return MakeCurrentImpl(aForce);
     }
 
     bool IsContextLost() { return mContextLost; }
 
     virtual bool SetupLookupFunction() = 0;
 
@@ -1505,20 +1511,22 @@ public:
 protected:
 
     ContextFormat mCreationFormat;
     nsRefPtr<GLContext> mSharedContext;
 
     GLContextSymbols mSymbols;
 
 #ifdef DEBUG
-    // this should be thread-local, but that is slightly annoying to implement because on Mac
-    // we don't have any __thread-like keyword. So for now, MOZ_GL_DEBUG assumes (and asserts)
-    // that only the main thread is doing OpenGL calls.
-    static THEBES_API GLContext* sCurrentGLContext;
+    // GLDebugMode will check that we don't send call
+    // to a GLContext that isn't current on the current
+    // thread.
+    // Store the current context when binding to thread local
+    // storage to support DebugMode on an arbitrary thread.
+    static PRUintn sCurrentGLContextTLS;
 #endif
 
     void UpdateActualFormat();
     ContextFormat mActualFormat;
 
     gfxIntSize mOffscreenSize;
     gfxIntSize mOffscreenActualSize;
     GLuint mOffscreenTexture;
@@ -1632,31 +1640,26 @@ public:
 
 protected:
     GLenum mGLError;
 
 public:
 
     void BeforeGLCall(const char* glFunction) {
         if (DebugMode()) {
-            // since the static member variable sCurrentGLContext is not thread-local as it should,
-            // we have to assert that we're in the main thread. Note that sCurrentGLContext is only used
-            // for the OpenGL debug mode.
-            if (!NS_IsMainThread()) {
-                NS_ERROR("OpenGL call from non-main thread. While this is fine in itself, "
-                         "the OpenGL debug mode, which is currently enabled, doesn't support this. "
-                         "It needs to be patched by making GLContext::sCurrentGLContext be thread-local.\n");
-                NS_ABORT();
-            }
+            GLContext *currentGLContext = NULL;
+
+            currentGLContext = (GLContext*)PR_GetThreadPrivate(sCurrentGLContextTLS);
+
             if (DebugMode() & DebugTrace)
                 printf_stderr("[gl:%p] > %s\n", this, glFunction);
-            if (this != sCurrentGLContext) {
+            if (this != currentGLContext) {
                 printf_stderr("Fatal: %s called on non-current context %p. "
                               "The current context for this thread is %p.\n",
-                               glFunction, this, sCurrentGLContext);
+                               glFunction, this, currentGLContext);
                 NS_ABORT();
             }
         }
     }
 
     void AfterGLCall(const char* glFunction) {
         if (DebugMode()) {
             // calling fFinish() immediately after every GL call makes sure that if this GL command crashes,
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -262,25 +262,16 @@ is_power_of_two(int v)
 
 #define AFTER_GL_CALL do {           \
     AfterGLCall(MOZ_FUNCTION_NAME);  \
 } while (0)
 
 static void BeforeGLCall(const char* glFunction)
 {
     if (GLContext::DebugMode()) {
-        // since the static member variable sCurrentGLContext is not thread-local as it should,
-        // we have to assert that we're in the main thread. Note that sCurrentGLContext is only used
-        // for the OpenGL debug mode.
-        if (!NS_IsMainThread()) {
-            NS_ERROR("OpenGL call from non-main thread. While this is fine in itself, "
-                     "the OpenGL debug mode, which is currently enabled, doesn't support this. "
-                     "It needs to be patched by making GLContext::sCurrentGLContext be thread-local.\n");
-            NS_ABORT();
-        }
         if (GLContext::DebugMode() & GLContext::DebugTrace)
             printf_stderr("[egl] > %s\n", glFunction);
     }
 }
 
 static void AfterGLCall(const char* glFunction)
 {
     if (GLContext::DebugMode() & GLContext::DebugTrace) {
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -293,16 +293,20 @@ gfxPlatform::Init()
 #elif defined(XP_OS2)
     gPlatform = new gfxOS2Platform;
 #elif defined(ANDROID)
     gPlatform = new gfxAndroidPlatform;
 #else
     #error "No gfxPlatform implementation available"
 #endif
 
+#ifdef DEBUG
+    mozilla::gl::GLContext::StaticInit();
+#endif
+
     nsresult rv;
 
 #if defined(XP_MACOSX) || defined(XP_WIN) || defined(ANDROID) // temporary, until this is implemented on others
     rv = gfxPlatformFontList::Init();
     if (NS_FAILED(rv)) {
         NS_RUNTIMEABORT("Could not initialize gfxPlatformFontList");
     }
 #endif