Backed out 7 changesets (bug 1390386) for Android crashes in testSettingsPages
authorPhil Ringnalda <philringnalda@gmail.com>
Thu, 17 Aug 2017 21:06:05 -0700
changeset 375450 fdbcfc9b798737b01e06b953441c4a2ffb5c168a
parent 375449 fbf0e8609abb4b978070dd0cbfcab6de7b2cda73
child 375451 575f17791f381e617533b753e4383b8dc3e24ba9
push id93911
push userphilringnalda@gmail.com
push dateFri, 18 Aug 2017 04:06:15 +0000
treeherdermozilla-inbound@fdbcfc9b7987 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1390386
milestone57.0a1
backs out22b11f9aedd32869b6876c9aacbcb83017924a6d
caffdbefd4273f360152ccff085ec5ee8244046d
3364e65897318d1324c9772222811173e802501d
ed6857bdc17b39575b57504a472d02704b6b836f
1314405cf812ecb8757a1e0d9ce632d042c3916d
9d16670edeb5a831913ae92469c5754a768b9b07
d1286d0d2c792751472c807f75996c9fc34220d1
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
Backed out 7 changesets (bug 1390386) for Android crashes in testSettingsPages Backed out changeset 22b11f9aedd3 (bug 1390386) Backed out changeset caffdbefd427 (bug 1390386) Backed out changeset 3364e6589731 (bug 1390386) Backed out changeset ed6857bdc17b (bug 1390386) Backed out changeset 1314405cf812 (bug 1390386) Backed out changeset 9d16670edeb5 (bug 1390386) Backed out changeset d1286d0d2c79 (bug 1390386) MozReview-Commit-ID: 3V3ZFwrNaGE
dom/canvas/WebGLContext.cpp
dom/canvas/WebGLContext.h
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextCGL.h
gfx/gl/GLContextEAGL.h
gfx/gl/GLContextEGL.h
gfx/gl/GLContextGLX.h
gfx/gl/GLContextProviderCGL.mm
gfx/gl/GLContextProviderEAGL.mm
gfx/gl/GLContextProviderEGL.cpp
gfx/gl/GLContextProviderGLX.cpp
gfx/gl/GLContextProviderWGL.cpp
gfx/gl/GLContextWGL.h
gfx/thebes/gfxPlatform.cpp
mfbt/ThreadLocal.h
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -1080,17 +1080,17 @@ WebGLContext::SetDimensions(int32_t sign
     if (!gl->Caps().stencil)
         mOptions.stencil = false;
 
     mOptions.antialias = gl->Caps().antialias;
 
     //////
     // Initial setup.
 
-    gl->mImplicitMakeCurrent = true;
+    MakeContextCurrent();
 
     gl->fViewport(0, 0, mWidth, mHeight);
     mViewportX = mViewportY = 0;
     mViewportWidth = mWidth;
     mViewportHeight = mHeight;
 
     gl->fScissor(0, 0, mWidth, mHeight);
     gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
@@ -1926,16 +1926,22 @@ WebGLContext::ForceRestoreContext()
     printf_stderr("WebGL(%p)::ForceRestoreContext\n", this);
     mContextStatus = ContextLostAwaitingRestore;
     mAllowContextRestore = true; // Hey, you did say 'force'.
 
     // Queue up a task, since we know the status changed.
     EnqueueUpdateContextLossStatus();
 }
 
+void
+WebGLContext::MakeContextCurrent() const
+{
+    gl->MakeCurrent();
+}
+
 already_AddRefed<mozilla::gfx::SourceSurface>
 WebGLContext::GetSurfaceSnapshot(gfxAlphaType* const out_alphaType)
 {
     if (!gl)
         return nullptr;
 
     const auto surfFormat = mOptions.alpha ? SurfaceFormat::B8G8R8A8
                                            : SurfaceFormat::B8G8R8X8;
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -1710,17 +1710,17 @@ public:
                                  uint8_t** const out_bytes, size_t* const out_byteLen);
 
 protected:
     ////
 
     void Invalidate();
     void DestroyResourcesAndContext();
 
-    void MakeContextCurrent() const { } // MakeCurrent is implicit now.
+    void MakeContextCurrent() const;
 
     // helpers
 
     bool ConvertImage(size_t width, size_t height, size_t srcStride,
                       size_t dstStride, const uint8_t* src, uint8_t* dst,
                       WebGLTexelFormat srcFormat, bool srcPremultiplied,
                       WebGLTexelFormat dstFormat, bool dstPremultiplied,
                       size_t dstTexelSize);
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -55,17 +55,21 @@
 #endif
 
 namespace mozilla {
 namespace gl {
 
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 
-MOZ_THREAD_LOCAL(const GLContext*) GLContext::sCurrentContext;
+#ifdef MOZ_GL_DEBUG
+unsigned GLContext::sCurrentGLContextTLS = -1;
+#endif
+
+MOZ_THREAD_LOCAL(GLContext*) GLContext::sCurrentContext;
 
 // If adding defines, don't forget to undefine symbols. See #undef block below.
 #define CORE_SYMBOL(x) { (PRFuncPtr*) &mSymbols.f##x, { #x, nullptr } }
 #define CORE_EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, { #x, #x #y, #x #z, nullptr } }
 #define EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, { #x #y, #x #z, nullptr } }
 #define EXT_SYMBOL3(x,y,z,w) { (PRFuncPtr*) &mSymbols.f##x, { #x #y, #x #z, #x #w, nullptr } }
 #define END_SYMBOLS { nullptr, { nullptr } }
 
@@ -258,18 +262,17 @@ ChooseDebugFlags(CreateContextFlags crea
     }
 #endif
 
     return debugFlags;
 }
 
 GLContext::GLContext(CreateContextFlags flags, const SurfaceCaps& caps,
                      GLContext* sharedContext, bool isOffscreen, bool useTLSIsCurrent)
-  : mImplicitMakeCurrent(false),
-    mIsOffscreen(isOffscreen),
+  : mIsOffscreen(isOffscreen),
     mContextLost(false),
     mUseTLSIsCurrent(ShouldUseTLSIsCurrent(useTLSIsCurrent)),
     mVersion(0),
     mProfile(ContextProfile::Unknown),
     mShadingLanguageVersion(0),
     mVendor(GLVendor::Other),
     mRenderer(GLRenderer::Other),
     mTopError(LOCAL_GL_NO_ERROR),
@@ -3021,100 +3024,55 @@ GetBytesPerTexel(GLenum format, GLenum t
     {
         return 2;
     }
 
     gfxCriticalError() << "Unknown texture type " << type << " or format " << format;
     return 0;
 }
 
-bool
-GLContext::MakeCurrent(bool aForce) const
+bool GLContext::MakeCurrent(bool aForce)
 {
-    if (MOZ_UNLIKELY( IsDestroyed() ))
+    if (IsDestroyed())
         return false;
 
-    if (MOZ_LIKELY( !aForce )) {
-        bool isCurrent;
-        if (mUseTLSIsCurrent) {
-            isCurrent = (sCurrentContext.get() == this);
-        } else {
-            isCurrent = IsCurrentImpl();
-        }
-        if (MOZ_LIKELY( isCurrent )) {
-            MOZ_ASSERT(IsCurrentImpl());
-            return true;
-        }
+#ifdef MOZ_GL_DEBUG
+    PR_SetThreadPrivate(sCurrentGLContextTLS, this);
+
+    // XXX this assertion is disabled because it's triggering on Mac;
+    // we need to figure out why and reenable it.
+#if 0
+    // IsOwningThreadCurrent is a bit of a misnomer;
+    // the "owning thread" is the creation thread,
+    // and the only thread that can own this.  We don't
+    // support contexts used on multiple threads.
+    NS_ASSERTION(IsOwningThreadCurrent(),
+                 "MakeCurrent() called on different thread than this context was created on!");
+#endif
+#endif
+    if (mUseTLSIsCurrent && !aForce && sCurrentContext.get() == this) {
+        MOZ_ASSERT(IsCurrent());
+        return true;
     }
 
-    if (!MakeCurrentImpl())
+    if (!MakeCurrentImpl(aForce))
         return false;
 
     if (mUseTLSIsCurrent) {
         sCurrentContext.set(this);
     }
+
     return true;
 }
 
 void
 GLContext::ResetSyncCallCount(const char* resetReason) const
 {
     if (ShouldSpew()) {
         printf_stderr("On %s, mSyncGLCallCount = %" PRIu64 "\n",
                        resetReason, mSyncGLCallCount);
     }
 
     mSyncGLCallCount = 0;
 }
 
-// --
-
-void
-GLContext::BeforeGLCall_Debug(const char* const funcName) const
-{
-    MOZ_ASSERT(mDebugFlags);
-
-    FlushErrors();
-
-    if (mDebugFlags & DebugFlagTrace) {
-        printf_stderr("[gl:%p] > %s\n", this, funcName);
-    }
-}
-
-void
-GLContext::AfterGLCall_Debug(const char* const funcName) const
-{
-    MOZ_ASSERT(mDebugFlags);
-
-    // calling fFinish() immediately after every GL call makes sure that if this GL command crashes,
-    // the stack trace will actually point to it. Otherwise, OpenGL being an asynchronous API, stack traces
-    // tend to be meaningless
-    mSymbols.fFinish();
-    GLenum err = FlushErrors();
-
-    if (mDebugFlags & DebugFlagTrace) {
-        printf_stderr("[gl:%p] < %s [%s (0x%04x)]\n", this, funcName,
-                      GLErrorToString(err), err);
-    }
-
-    if (err != LOCAL_GL_NO_ERROR &&
-        !mLocalErrorScopeStack.size())
-    {
-        printf_stderr("[gl:%p] %s: Generated unexpected %s error."
-                      " (0x%04x)\n", this, funcName,
-                      GLErrorToString(err), err);
-
-        if (mDebugFlags & DebugFlagAbortOnError) {
-            MOZ_CRASH("Unexpected error with MOZ_GL_DEBUG_ABORT_ON_ERROR. (Run"
-                      " with MOZ_GL_DEBUG_ABORT_ON_ERROR=0 to disable)");
-        }
-    }
-}
-
-/*static*/ void
-GLContext::OnImplicitMakeCurrentFailure(const char* const funcName)
-{
-    gfxCriticalError() << "Ignoring call to " << funcName << " with failed"
-                       << " mImplicitMakeCurrent.";
-}
-
 } /* namespace gl */
 } /* namespace mozilla */
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -192,19 +192,17 @@ enum class GLRenderer {
 
 class GLContext
     : public GLLibraryLoader
     , public GenericAtomicRefCounted
     , public SupportsWeakPtr<GLContext>
 {
 public:
     MOZ_DECLARE_WEAKREFERENCE_TYPENAME(GLContext)
-    static MOZ_THREAD_LOCAL(const GLContext*) sCurrentContext;
-
-    bool mImplicitMakeCurrent;
+    static MOZ_THREAD_LOCAL(GLContext*) sCurrentContext;
 
 // -----------------------------------------------------------------------------
 // basic getters
 public:
 
     /**
      * Returns true if the context is using ANGLE. This should only be overridden
      * for an ANGLE implementation.
@@ -294,38 +292,28 @@ public:
      * If this context is double-buffered, returns TRUE.
      */
     virtual bool IsDoubleBuffered() const {
         return false;
     }
 
     virtual GLContextType GetContextType() const = 0;
 
-    virtual bool IsCurrentImpl() const = 0;
-    virtual bool MakeCurrentImpl() const = 0;
-
-    bool IsCurrent() const {
-        if (mImplicitMakeCurrent)
-            return MakeCurrent();
-
-        return IsCurrentImpl();
-    }
-
-    bool MakeCurrent(bool aForce = false) const;
+    virtual bool IsCurrent() = 0;
 
     /**
      * Get the default framebuffer for this context.
      */
     virtual GLuint GetDefaultFramebuffer() {
         return 0;
     }
 
 protected:
     bool mIsOffscreen;
-    mutable bool mContextLost;
+    bool mContextLost;
     const bool mUseTLSIsCurrent;
 
     /**
      * mVersion store the OpenGL's version, multiplied by 100. For example, if
      * the context is an OpenGL 2.1 context, mVersion value will be 210.
      */
     uint32_t mVersion;
     ContextProfile mProfile;
@@ -548,42 +536,51 @@ public:
             case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION:
                 return "GL_INVALID_FRAMEBUFFER_OPERATION";
             default:
                 return "";
         }
     }
 
 private:
-    mutable GLenum mTopError;
-
-    GLenum RawGetError() const {
+    GLenum mTopError;
+
+    GLenum RawGetError() {
         return mSymbols.fGetError();
     }
 
-    GLenum RawGetErrorAndClear() const {
+    GLenum RawGetErrorAndClear() {
         GLenum err = RawGetError();
 
         if (err)
             while (RawGetError()) {}
 
         return err;
     }
 
-    GLenum FlushErrors() const {
+public:
+    GLenum FlushErrors() {
         GLenum err = RawGetErrorAndClear();
         if (!mTopError)
             mTopError = err;
         return err;
     }
 
+    // We smash all errors together, so you never have to loop on this. We
+    // guarantee that immediately after this call, there are no errors left.
+    GLenum fGetError() {
+        FlushErrors();
+
+        GLenum err = mTopError;
+        mTopError = LOCAL_GL_NO_ERROR;
+        return err;
+    }
+
     ////////////////////////////////////
     // Use this safer option.
-
-public:
     class LocalErrorScope;
 
 private:
     std::stack<const LocalErrorScope*> mLocalErrorScopeStack;
 
 public:
     class LocalErrorScope {
         GLContext& mGL;
@@ -651,105 +648,136 @@ private:
                        GLsizei length,
                        const GLchar* message);
 
 
 // -----------------------------------------------------------------------------
 // MOZ_GL_DEBUG implementation
 private:
 
+#undef BEFORE_GL_CALL
+#undef AFTER_GL_CALL
+
+#ifdef MOZ_GL_DEBUG
+
 #ifndef MOZ_FUNCTION_NAME
 # ifdef __GNUC__
 #  define MOZ_FUNCTION_NAME __PRETTY_FUNCTION__
 # elif defined(_MSC_VER)
 #  define MOZ_FUNCTION_NAME __FUNCTION__
 # else
 #  define MOZ_FUNCTION_NAME __func__  // defined in C99, supported in various C++ compilers. Just raw function name.
 # endif
 #endif
 
-#ifdef MOZ_WIDGET_ANDROID
-// Record the name of the GL call for better hang stacks on Android.
-#define ANDROID_ONLY_PROFILER_LABEL AUTO_PROFILER_LABEL(__func__, GRAPHICS);
-#else
-#define ANDROID_ONLY_PROFILER_LABEL
-#endif
-
-#define BEFORE_GL_CALL \
-        ANDROID_ONLY_PROFILER_LABEL \
-        if (MOZ_LIKELY( BeforeGLCall(MOZ_FUNCTION_NAME) )) { \
-            do { } while (0)
-
-#define AFTER_GL_CALL \
-            AfterGLCall(MOZ_FUNCTION_NAME); \
-        } \
-        do { } while (0)
-
-    void BeforeGLCall_Debug(const char* funcName) const;
-    void AfterGLCall_Debug(const char* funcName) const;
-    static void OnImplicitMakeCurrentFailure(const char* funcName);
-
-    bool BeforeGLCall(const char* const funcName) const {
-        if (mImplicitMakeCurrent) {
-            if (MOZ_UNLIKELY( !MakeCurrent() )) {
-                OnImplicitMakeCurrentFailure(funcName);
-                return false;
+    void BeforeGLCall(const char* funcName) {
+        MOZ_ASSERT(IsCurrent());
+
+        if (mDebugFlags) {
+            FlushErrors();
+
+            if (mDebugFlags & DebugFlagTrace) {
+                printf_stderr("[gl:%p] > %s\n", this, funcName);
+            }
+
+            GLContext* tlsContext = (GLContext*)PR_GetThreadPrivate(sCurrentGLContextTLS);
+            if (this != tlsContext) {
+                printf_stderr("Fatal: %s called on non-current context %p. The"
+                              " current context for this thread is %p.\n",
+                              funcName, this, tlsContext);
+                MOZ_CRASH("GFX: GLContext is not current.");
             }
         }
-        MOZ_ASSERT(IsCurrentImpl());
-
+    }
+
+    void AfterGLCall(const char* funcName) {
         if (mDebugFlags) {
-            BeforeGLCall_Debug(funcName);
-        }
-        return true;
-    }
-
-    void AfterGLCall(const char* const funcName) const {
-        if (mDebugFlags) {
-            AfterGLCall_Debug(funcName);
+            // calling fFinish() immediately after every GL call makes sure that if this GL command crashes,
+            // the stack trace will actually point to it. Otherwise, OpenGL being an asynchronous API, stack traces
+            // tend to be meaningless
+            mSymbols.fFinish();
+            GLenum err = FlushErrors();
+
+            if (mDebugFlags & DebugFlagTrace) {
+                printf_stderr("[gl:%p] < %s [%s (0x%04x)]\n", this, funcName,
+                              GLErrorToString(err), err);
+            }
+
+            if (err != LOCAL_GL_NO_ERROR &&
+                !mLocalErrorScopeStack.size())
+            {
+                printf_stderr("[gl:%p] %s: Generated unexpected %s error."
+                              " (0x%04x)\n", this, funcName,
+                              GLErrorToString(err), err);
+
+                if (mDebugFlags & DebugFlagAbortOnError) {
+                    MOZ_CRASH("Unexpected error with MOZ_GL_DEBUG_ABORT_ON_ERROR. (Run"
+                              " with MOZ_GL_DEBUG_ABORT_ON_ERROR=0 to disable)");
+                }
+            }
         }
     }
 
     GLContext* TrackingContext()
     {
         GLContext* tip = this;
         while (tip->mSharedContext)
             tip = tip->mSharedContext;
         return tip;
     }
 
     static void AssertNotPassingStackBufferToTheGL(const void* ptr);
 
-#ifdef MOZ_GL_DEBUG
+#ifdef MOZ_WIDGET_ANDROID
+// Record the name of the GL call for better hang stacks on Android.
+#define BEFORE_GL_CALL                              \
+            AUTO_PROFILER_LABEL(__func__, GRAPHICS);\
+            BeforeGLCall(MOZ_FUNCTION_NAME)
+#else
+#define BEFORE_GL_CALL                              \
+            do {                                    \
+                BeforeGLCall(MOZ_FUNCTION_NAME);    \
+            } while (0)
+#endif
+
+#define AFTER_GL_CALL                               \
+            do {                                    \
+                AfterGLCall(MOZ_FUNCTION_NAME);     \
+            } while (0)
 
 #define TRACKING_CONTEXT(a)                         \
             do {                                    \
                 TrackingContext()->a;               \
             } while (0)
 
 #define ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(ptr) AssertNotPassingStackBufferToTheGL(ptr)
 
+#else // ifdef MOZ_GL_DEBUG
+
+#ifdef MOZ_WIDGET_ANDROID
+// Record the name of the GL call for better hang stacks on Android.
+#define BEFORE_GL_CALL AUTO_PROFILER_LABEL(__func__, GRAPHICS)
+#else
+#define BEFORE_GL_CALL do { } while (0)
+#endif
+#define AFTER_GL_CALL do { } while (0)
+#define TRACKING_CONTEXT(a) do {} while (0)
+#define ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(ptr) do {} while (0)
+
+#endif // ifdef MOZ_GL_DEBUG
+
 #define ASSERT_SYMBOL_PRESENT(func) \
             do {\
                 MOZ_ASSERT(strstr(MOZ_FUNCTION_NAME, #func) != nullptr, "Mismatched symbol check.");\
                 if (MOZ_UNLIKELY(!mSymbols.func)) {\
                     printf_stderr("RUNTIME ASSERT: Uninitialized GL function: %s\n", #func);\
                     MOZ_CRASH("GFX: Uninitialized GL function");\
                 }\
             } while (0)
 
-#else // ifdef MOZ_GL_DEBUG
-
-#define TRACKING_CONTEXT(a) do {} while (0)
-#define ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(ptr) do {} while (0)
-#define ASSERT_SYMBOL_PRESENT(func) do {} while (0)
-
-#endif // ifdef MOZ_GL_DEBUG
-
-
     // Do whatever setup is necessary to draw to our offscreen FBO, if it's
     // bound.
     void BeforeGLDrawCall() { }
 
     // Do whatever tear-down is necessary after drawing to our offscreen FBO,
     // if it's bound.
     void AfterGLDrawCall();
 
@@ -770,29 +798,16 @@ public:
         return mSyncGLCallCount;
     }
 
     void ResetSyncCallCount(const char* resetReason) const;
 
 // -----------------------------------------------------------------------------
 // GL official entry points
 public:
-    // We smash all errors together, so you never have to loop on this. We
-    // guarantee that immediately after this call, there are no errors left.
-    GLenum fGetError() {
-        GLenum err = LOCAL_GL_CONTEXT_LOST;
-        BEFORE_GL_CALL;
-
-        FlushErrors();
-        err = mTopError;
-        mTopError = LOCAL_GL_NO_ERROR;
-
-        AFTER_GL_CALL;
-        return err;
-    }
 
     void fActiveTexture(GLenum texture) {
         BEFORE_GL_CALL;
         mSymbols.fActiveTexture(texture);
         AFTER_GL_CALL;
     }
 
     void fAttachShader(GLuint program, GLuint shader) {
@@ -1163,19 +1178,18 @@ public:
     void fGetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders) {
         BEFORE_GL_CALL;
         mSymbols.fGetAttachedShaders(program, maxCount, count, shaders);
         OnSyncCall();
         AFTER_GL_CALL;
     }
 
     GLint fGetAttribLocation(GLuint program, const GLchar* name) {
-        GLint retval = 0;
-        BEFORE_GL_CALL;
-        retval = mSymbols.fGetAttribLocation(program, name);
+        BEFORE_GL_CALL;
+        GLint retval = mSymbols.fGetAttribLocation(program, name);
         OnSyncCall();
         AFTER_GL_CALL;
         return retval;
     }
 
 private:
     void raw_fGetIntegerv(GLenum pname, GLint* params) {
         BEFORE_GL_CALL;
@@ -1217,20 +1231,19 @@ public:
     void fGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) {
         BEFORE_GL_CALL;
         mSymbols.fGetBufferParameteriv(target, pname, params);
         OnSyncCall();
         AFTER_GL_CALL;
     }
 
     GLuint fGetDebugMessageLog(GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog) {
-        GLuint ret = 0;
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fGetDebugMessageLog);
-        ret = mSymbols.fGetDebugMessageLog(count, bufsize, sources, types, ids, severities, lengths, messageLog);
+        GLuint ret = mSymbols.fGetDebugMessageLog(count, bufsize, sources, types, ids, severities, lengths, messageLog);
         OnSyncCall();
         AFTER_GL_CALL;
         return ret;
     }
 
     void fGetPointerv(GLenum pname, GLvoid** params) {
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fGetPointerv);
@@ -1289,19 +1302,18 @@ public:
 
     void fTexParameterf(GLenum target, GLenum pname, GLfloat param) {
         BEFORE_GL_CALL;
         mSymbols.fTexParameterf(target, pname, param);
         AFTER_GL_CALL;
     }
 
     const GLubyte* fGetString(GLenum name) {
-        const GLubyte* result = nullptr;
-        BEFORE_GL_CALL;
-        result = mSymbols.fGetString(name);
+        BEFORE_GL_CALL;
+        const GLubyte* result = mSymbols.fGetString(name);
         OnSyncCall();
         AFTER_GL_CALL;
         return result;
     }
 
     void fGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* img) {
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fGetTexImage);
@@ -1351,19 +1363,18 @@ public:
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fGetUniformuiv);
         mSymbols.fGetUniformuiv(program, location, params);
         OnSyncCall();
         AFTER_GL_CALL;
     }
 
     GLint fGetUniformLocation (GLint programObj, const GLchar* name) {
-        GLint retval = 0;
-        BEFORE_GL_CALL;
-        retval = mSymbols.fGetUniformLocation(programObj, name);
+        BEFORE_GL_CALL;
+        GLint retval = mSymbols.fGetUniformLocation(programObj, name);
         OnSyncCall();
         AFTER_GL_CALL;
         return retval;
     }
 
     void fGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* retval) {
         BEFORE_GL_CALL;
         mSymbols.fGetVertexAttribfv(index, pname, retval);
@@ -1387,52 +1398,47 @@ public:
 
     void fHint(GLenum target, GLenum mode) {
         BEFORE_GL_CALL;
         mSymbols.fHint(target, mode);
         AFTER_GL_CALL;
     }
 
     realGLboolean fIsBuffer(GLuint buffer) {
-        realGLboolean retval = false;
-        BEFORE_GL_CALL;
-        retval = mSymbols.fIsBuffer(buffer);
+        BEFORE_GL_CALL;
+        realGLboolean retval = mSymbols.fIsBuffer(buffer);
         OnSyncCall();
         AFTER_GL_CALL;
         return retval;
     }
 
     realGLboolean fIsEnabled(GLenum capability) {
-        realGLboolean retval = false;
-        BEFORE_GL_CALL;
-        retval = mSymbols.fIsEnabled(capability);
+        BEFORE_GL_CALL;
+        realGLboolean retval = mSymbols.fIsEnabled(capability);
         AFTER_GL_CALL;
         return retval;
     }
 
     realGLboolean fIsProgram(GLuint program) {
-        realGLboolean retval = false;
-        BEFORE_GL_CALL;
-        retval = mSymbols.fIsProgram(program);
+        BEFORE_GL_CALL;
+        realGLboolean retval = mSymbols.fIsProgram(program);
         AFTER_GL_CALL;
         return retval;
     }
 
     realGLboolean fIsShader(GLuint shader) {
-        realGLboolean retval = false;
-        BEFORE_GL_CALL;
-        retval = mSymbols.fIsShader(shader);
+        BEFORE_GL_CALL;
+        realGLboolean retval = mSymbols.fIsShader(shader);
         AFTER_GL_CALL;
         return retval;
     }
 
     realGLboolean fIsTexture(GLuint texture) {
-        realGLboolean retval = false;
-        BEFORE_GL_CALL;
-        retval = mSymbols.fIsTexture(texture);
+        BEFORE_GL_CALL;
+        realGLboolean retval = mSymbols.fIsTexture(texture);
         AFTER_GL_CALL;
         return retval;
     }
 
     void fLineWidth(GLfloat width) {
         BEFORE_GL_CALL;
         mSymbols.fLineWidth(width);
         AFTER_GL_CALL;
@@ -1862,33 +1868,16 @@ public:
     }
 
     void fVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
         BEFORE_GL_CALL;
         mSymbols.fVertexPointer(size, type, stride, pointer);
         AFTER_GL_CALL;
     }
 
-    void fViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
-        if (mViewportRect[0] == x &&
-            mViewportRect[1] == y &&
-            mViewportRect[2] == width &&
-            mViewportRect[3] == height)
-        {
-            return;
-        }
-        mViewportRect[0] = x;
-        mViewportRect[1] = y;
-        mViewportRect[2] = width;
-        mViewportRect[3] = height;
-        BEFORE_GL_CALL;
-        mSymbols.fViewport(x, y, width, height);
-        AFTER_GL_CALL;
-    }
-
     void fCompileShader(GLuint shader) {
         BEFORE_GL_CALL;
         mSymbols.fCompileShader(shader);
         AFTER_GL_CALL;
     }
 
 private:
 
@@ -1969,19 +1958,18 @@ private:
 public:
     void fBindRenderbuffer(GLenum target, GLuint renderbuffer) {
         BEFORE_GL_CALL;
         mSymbols.fBindRenderbuffer(target, renderbuffer);
         AFTER_GL_CALL;
     }
 
     GLenum fCheckFramebufferStatus(GLenum target) {
-        GLenum retval = 0;
-        BEFORE_GL_CALL;
-        retval = mSymbols.fCheckFramebufferStatus(target);
+        BEFORE_GL_CALL;
+        GLenum retval = mSymbols.fCheckFramebufferStatus(target);
         OnSyncCall();
         AFTER_GL_CALL;
         return retval;
     }
 
     void fFramebufferRenderbuffer(GLenum target, GLenum attachmentPoint, GLenum renderbufferTarget, GLuint renderbuffer) {
         BEFORE_GL_CALL;
         mSymbols.fFramebufferRenderbuffer(target, attachmentPoint, renderbufferTarget, renderbuffer);
@@ -2014,29 +2002,27 @@ public:
     void fGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* value) {
         BEFORE_GL_CALL;
         mSymbols.fGetRenderbufferParameteriv(target, pname, value);
         OnSyncCall();
         AFTER_GL_CALL;
     }
 
     realGLboolean fIsFramebuffer (GLuint framebuffer) {
-        realGLboolean retval = false;
-        BEFORE_GL_CALL;
-        retval = mSymbols.fIsFramebuffer(framebuffer);
+        BEFORE_GL_CALL;
+        realGLboolean retval = mSymbols.fIsFramebuffer(framebuffer);
         OnSyncCall();
         AFTER_GL_CALL;
         return retval;
     }
 
 public:
     realGLboolean fIsRenderbuffer (GLuint renderbuffer) {
-        realGLboolean retval = false;
-        BEFORE_GL_CALL;
-        retval = mSymbols.fIsRenderbuffer(renderbuffer);
+        BEFORE_GL_CALL;
+        realGLboolean retval = mSymbols.fIsRenderbuffer(renderbuffer);
         OnSyncCall();
         AFTER_GL_CALL;
         return retval;
     }
 
     void fRenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height) {
         BEFORE_GL_CALL;
         mSymbols.fRenderbufferStorage(target, internalFormat, width, height);
@@ -2093,48 +2079,44 @@ public:
         if (IsGLES()) {
             raw_fClearDepthf(v);
         } else {
             raw_fClearDepth(v);
         }
     }
 
     void* fMapBuffer(GLenum target, GLenum access) {
-        void* ret = nullptr;
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fMapBuffer);
-        ret = mSymbols.fMapBuffer(target, access);
+        void* ret = mSymbols.fMapBuffer(target, access);
         OnSyncCall();
         AFTER_GL_CALL;
         return ret;
     }
 
     realGLboolean fUnmapBuffer(GLenum target) {
-        realGLboolean ret = false;
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fUnmapBuffer);
-        ret = mSymbols.fUnmapBuffer(target);
+        realGLboolean ret = mSymbols.fUnmapBuffer(target);
         AFTER_GL_CALL;
         return ret;
     }
 
 
 private:
     GLuint raw_fCreateProgram() {
-        GLuint ret = 0;
-        BEFORE_GL_CALL;
-        ret = mSymbols.fCreateProgram();
+        BEFORE_GL_CALL;
+        GLuint ret = mSymbols.fCreateProgram();
         AFTER_GL_CALL;
         return ret;
     }
 
     GLuint raw_fCreateShader(GLenum t) {
-        GLuint ret = 0;
-        BEFORE_GL_CALL;
-        ret = mSymbols.fCreateShader(t);
+        BEFORE_GL_CALL;
+        GLuint ret = mSymbols.fCreateShader(t);
         AFTER_GL_CALL;
         return ret;
     }
 
     void raw_fGenBuffers(GLsizei n, GLuint* names) {
         BEFORE_GL_CALL;
         mSymbols.fGenBuffers(n, names);
         OnSyncCall();
@@ -2257,61 +2239,57 @@ public:
     }
 
     void fDeleteTextures(GLsizei n, const GLuint* names) {
         raw_fDeleteTextures(n, names);
         TRACKING_CONTEXT(DeletedTextures(this, n, names));
     }
 
     GLenum fGetGraphicsResetStatus() {
-        GLenum ret = 0;
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fGetGraphicsResetStatus);
-        ret = mSymbols.fGetGraphicsResetStatus();
+        GLenum ret = mSymbols.fGetGraphicsResetStatus();
         OnSyncCall();
         AFTER_GL_CALL;
         return ret;
     }
 
 
 // -----------------------------------------------------------------------------
 // Extension ARB_sync (GL)
 public:
     GLsync fFenceSync(GLenum condition, GLbitfield flags) {
-        GLsync ret = 0;
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fFenceSync);
-        ret = mSymbols.fFenceSync(condition, flags);
+        GLsync ret = mSymbols.fFenceSync(condition, flags);
         OnSyncCall();
         AFTER_GL_CALL;
         return ret;
     }
 
     realGLboolean fIsSync(GLsync sync) {
-        realGLboolean ret = false;
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fIsSync);
-        ret = mSymbols.fIsSync(sync);
+        realGLboolean ret = mSymbols.fIsSync(sync);
         OnSyncCall();
         AFTER_GL_CALL;
         return ret;
     }
 
     void fDeleteSync(GLsync sync) {
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fDeleteSync);
         mSymbols.fDeleteSync(sync);
         AFTER_GL_CALL;
     }
 
     GLenum fClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
-        GLenum ret = 0;
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fClientWaitSync);
-        ret = mSymbols.fClientWaitSync(sync, flags, timeout);
+        GLenum ret = mSymbols.fClientWaitSync(sync, flags, timeout);
         OnSyncCall();
         AFTER_GL_CALL;
         return ret;
     }
 
     void fWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fWaitSync);
@@ -2579,20 +2557,19 @@ public:
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fUniform4uiv);
         mSymbols.fUniform4uiv(location, count, value);
         AFTER_GL_CALL;
     }
 
     GLint fGetFragDataLocation(GLuint program, const GLchar* name)
     {
-        GLint result = 0;
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fGetFragDataLocation);
-        result = mSymbols.fGetFragDataLocation(program, name);
+        GLint result = mSymbols.fGetFragDataLocation(program, name);
         OnSyncCall();
         AFTER_GL_CALL;
         return result;
     }
 
 
 // -----------------------------------------------------------------------------
 // Package XXX_instanced_arrays
@@ -2677,20 +2654,19 @@ public:
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fGetQueryObjectuiv);
         mSymbols.fGetQueryObjectuiv(id, pname, params);
         OnSyncCall();
         AFTER_GL_CALL;
     }
 
     realGLboolean fIsQuery(GLuint query) {
-        realGLboolean retval = false;
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fIsQuery);
-        retval = mSymbols.fIsQuery(query);
+        realGLboolean retval = mSymbols.fIsQuery(query);
         OnSyncCall();
         AFTER_GL_CALL;
         return retval;
     }
 
 // -----------------------------------------------------------------------------
 // Package XXX_get_query_object_i64v
 /**
@@ -2770,20 +2746,19 @@ public:
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fDeleteTransformFeedbacks);
         mSymbols.fDeleteTransformFeedbacks(n, ids);
         AFTER_GL_CALL;
     }
 
     realGLboolean fIsTransformFeedback(GLuint id)
     {
-        realGLboolean result = false;
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fIsTransformFeedback);
-        result = mSymbols.fIsTransformFeedback(id);
+        realGLboolean result = mSymbols.fIsTransformFeedback(id);
         OnSyncCall();
         AFTER_GL_CALL;
         return result;
     }
 
     void fBindTransformFeedback(GLenum target, GLuint id)
     {
         BEFORE_GL_CALL;
@@ -2882,20 +2857,19 @@ public:
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fGenVertexArrays);
         mSymbols.fGenVertexArrays(n, arrays);
         AFTER_GL_CALL;
     }
 
     realGLboolean fIsVertexArray(GLuint array)
     {
-        realGLboolean ret = false;
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fIsVertexArray);
-        ret = mSymbols.fIsVertexArray(array);
+        realGLboolean ret = mSymbols.fIsVertexArray(array);
         OnSyncCall();
         AFTER_GL_CALL;
         return ret;
     }
 
 // -----------------------------------------------------------------------------
 // Extension NV_fence
 public:
@@ -2920,40 +2894,38 @@ public:
         ASSERT_SYMBOL_PRESENT(fSetFence);
         BEFORE_GL_CALL;
         mSymbols.fSetFence(fence, condition);
         AFTER_GL_CALL;
     }
 
     realGLboolean fTestFence(GLuint fence)
     {
-        realGLboolean ret = false;
         ASSERT_SYMBOL_PRESENT(fTestFence);
         BEFORE_GL_CALL;
-        ret = mSymbols.fTestFence(fence);
+        realGLboolean ret = mSymbols.fTestFence(fence);
         OnSyncCall();
         AFTER_GL_CALL;
         return ret;
     }
 
     void fFinishFence(GLuint fence)
     {
         ASSERT_SYMBOL_PRESENT(fFinishFence);
         BEFORE_GL_CALL;
         mSymbols.fFinishFence(fence);
         OnSyncCall();
         AFTER_GL_CALL;
     }
 
     realGLboolean fIsFence(GLuint fence)
     {
-        realGLboolean ret = false;
         ASSERT_SYMBOL_PRESENT(fIsFence);
         BEFORE_GL_CALL;
-        ret = mSymbols.fIsFence(fence);
+        realGLboolean ret = mSymbols.fIsFence(fence);
         OnSyncCall();
         AFTER_GL_CALL;
         return ret;
     }
 
     void fGetFenceiv(GLuint fence, GLenum pname, GLint* params)
     {
         ASSERT_SYMBOL_PRESENT(fGetFenceiv);
@@ -2988,20 +2960,19 @@ public:
 
 
 // -----------------------------------------------------------------------------
 // Core GL & Extension ARB_map_buffer_range
 public:
     void* fMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
                           GLbitfield access)
     {
-        void* data = nullptr;
         ASSERT_SYMBOL_PRESENT(fMapBufferRange);
         BEFORE_GL_CALL;
-        data = mSymbols.fMapBufferRange(target, offset, length, access);
+        void* data = mSymbols.fMapBufferRange(target, offset, length, access);
         OnSyncCall();
         AFTER_GL_CALL;
         return data;
     }
 
     void fFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) {
         ASSERT_SYMBOL_PRESENT(fFlushMappedBufferRange);
         BEFORE_GL_CALL;
@@ -3026,20 +2997,19 @@ public:
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fDeleteSamplers);
         mSymbols.fDeleteSamplers(count, samplers);
         AFTER_GL_CALL;
     }
 
     realGLboolean fIsSampler(GLuint sampler)
     {
-        realGLboolean result = false;
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fIsSampler);
-        result = mSymbols.fIsSampler(sampler);
+        realGLboolean result = mSymbols.fIsSampler(sampler);
         OnSyncCall();
         AFTER_GL_CALL;
         return result;
     }
 
     void fBindSampler(GLuint unit, GLuint sampler)
     {
         BEFORE_GL_CALL;
@@ -3116,20 +3086,19 @@ public:
         ASSERT_SYMBOL_PRESENT(fGetActiveUniformsiv);
         BEFORE_GL_CALL;
         mSymbols.fGetActiveUniformsiv(program, uniformCount, uniformIndices, pname, params);
         OnSyncCall();
         AFTER_GL_CALL;
     }
 
     GLuint fGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) {
-        GLuint result = 0;
         ASSERT_SYMBOL_PRESENT(fGetUniformBlockIndex);
         BEFORE_GL_CALL;
-        result = mSymbols.fGetUniformBlockIndex(program, uniformBlockName);
+        GLuint result = mSymbols.fGetUniformBlockIndex(program, uniformBlockName);
         OnSyncCall();
         AFTER_GL_CALL;
         return result;
     }
 
     void fGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex,
                                   GLenum pname, GLint* params)
     {
@@ -3246,20 +3215,19 @@ public:
                                           format, imageSize, data);
         AFTER_GL_CALL;
     }
 
 // -----------------------------------------------------------------------------
 // GL3+, ES3+
 
     const GLubyte* fGetStringi(GLenum name, GLuint index) {
-        const GLubyte* ret = nullptr;
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fGetStringi);
-        ret = mSymbols.fGetStringi(name, index);
+        const GLubyte* ret = mSymbols.fGetStringi(name, index);
         OnSyncCall();
         AFTER_GL_CALL;
         return ret;
     }
 
 // -----------------------------------------------------------------------------
 // APPLE_framebuffer_multisample
 
@@ -3275,22 +3243,16 @@ public:
 
     void fPrimitiveRestartIndex(GLuint index) {
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fPrimitiveRestartIndex);
         mSymbols.fPrimitiveRestartIndex(index);
         AFTER_GL_CALL;
     }
 
-#undef BEFORE_GL_CALL
-#undef AFTER_GL_CALL
-#undef ASSERT_SYMBOL_PRESENT
-// #undef TRACKING_CONTEXT // Needed in GLContext.cpp
-#undef ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL
-
 // -----------------------------------------------------------------------------
 // Constructor
 protected:
     explicit GLContext(CreateContextFlags flags, const SurfaceCaps& caps,
                        GLContext* sharedContext = nullptr,
                        bool isOffscreen = false, bool canUseTLSIsCurrent = false);
 
 
@@ -3303,24 +3265,34 @@ public:
     // the GL function pointers!
     void MarkDestroyed();
 
 // -----------------------------------------------------------------------------
 // Everything that isn't standard GL APIs
 protected:
     typedef gfx::SurfaceFormat SurfaceFormat;
 
+    virtual bool MakeCurrentImpl(bool aForce) = 0;
+
 public:
+#ifdef MOZ_GL_DEBUG
+    static void StaticInit() {
+        PR_NewThreadPrivateIndex(&sCurrentGLContextTLS, nullptr);
+    }
+#endif
+
+    bool MakeCurrent(bool aForce = false);
+
     virtual bool Init() = 0;
 
     virtual bool SetupLookupFunction() = 0;
 
     virtual void ReleaseSurface() {}
 
-    bool IsDestroyed() const {
+    bool IsDestroyed() {
         // MarkDestroyed will mark all these as null.
         return mSymbols.fUseProgram == nullptr;
     }
 
     GLContext* GetSharedContext() { return mSharedContext; }
 
     /**
      * Returns true if the thread on which this context was created is the currently
@@ -3445,16 +3417,25 @@ public:
 protected:
     RefPtr<GLContext> mSharedContext;
 
     // The thread id which this context was created.
     PlatformThreadId mOwningThreadId;
 
     GLContextSymbols mSymbols;
 
+#ifdef MOZ_GL_DEBUG
+    // Non-zero debug flags 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 debug flags on an arbitrary thread.
+    static unsigned sCurrentGLContextTLS;
+#endif
+
     UniquePtr<GLBlitHelper> mBlitHelper;
     UniquePtr<GLReadTexImageHelper> mReadTexImageHelper;
 
 public:
     GLBlitHelper* BlitHelper();
     GLBlitTextureImageHelper* BlitTextureImageHelper();
     GLReadTexImageHelper* ReadTexImageHelper();
 
@@ -3607,16 +3588,35 @@ protected:
     }
 
 
 public:
     GLsizei MaxSamples() const {
         return mMaxSamples;
     }
 
+    void fViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
+        if (mViewportRect[0] == x &&
+            mViewportRect[1] == y &&
+            mViewportRect[2] == width &&
+            mViewportRect[3] == height)
+        {
+            return;
+        }
+        mViewportRect[0] = x;
+        mViewportRect[1] = y;
+        mViewportRect[2] = width;
+        mViewportRect[3] = height;
+        BEFORE_GL_CALL;
+        mSymbols.fViewport(x, y, width, height);
+        AFTER_GL_CALL;
+    }
+
+#undef ASSERT_SYMBOL_PRESENT
+
 #ifdef MOZ_GL_DEBUG
     void CreatedProgram(GLContext* aOrigin, GLuint aName);
     void CreatedShader(GLContext* aOrigin, GLuint aName);
     void CreatedBuffers(GLContext* aOrigin, GLsizei aCount, GLuint* aNames);
     void CreatedQueries(GLContext* aOrigin, GLsizei aCount, GLuint* aNames);
     void CreatedTextures(GLContext* aOrigin, GLsizei aCount, GLuint* aNames);
     void CreatedFramebuffers(GLContext* aOrigin, GLsizei aCount, GLuint* aNames);
     void CreatedRenderbuffers(GLContext* aOrigin, GLsizei aCount, GLuint* aNames);
--- a/gfx/gl/GLContextCGL.h
+++ b/gfx/gl/GLContextCGL.h
@@ -40,19 +40,19 @@ public:
         return static_cast<GLContextCGL*>(gl);
     }
 
     bool Init() override;
 
     NSOpenGLContext* GetNSOpenGLContext() const { return mContext; }
     CGLContextObj GetCGLContext() const;
 
-    virtual bool MakeCurrentImpl() const override;
+    virtual bool MakeCurrentImpl(bool aForce) override;
 
-    virtual bool IsCurrentImpl() const override;
+    virtual bool IsCurrent() override;
 
     virtual GLenum GetPreferredARGB32Format() const override;
 
     virtual bool SetupLookupFunction() override;
 
     virtual bool IsDoubleBuffered() const override;
 
     virtual bool SwapBuffers() override;
--- a/gfx/gl/GLContextEAGL.h
+++ b/gfx/gl/GLContextEAGL.h
@@ -38,19 +38,19 @@ public:
     }
 
     bool Init() override;
 
     bool AttachToWindow(nsIWidget* aWidget);
 
     EAGLContext* GetEAGLContext() const { return mContext; }
 
-    virtual bool MakeCurrentImpl() const override;
+    virtual bool MakeCurrentImpl(bool aForce) override;
 
-    virtual bool IsCurrentImpl() const override;
+    virtual bool IsCurrent() override;
 
     virtual bool SetupLookupFunction() override;
 
     virtual bool IsDoubleBuffered() const override;
 
     virtual bool SwapBuffers() override;
 
     virtual void GetWSIInfo(nsCString* const out) const override;
--- a/gfx/gl/GLContextEGL.h
+++ b/gfx/gl/GLContextEGL.h
@@ -68,19 +68,19 @@ public:
 
     virtual bool ReleaseTexImage() override;
 
     void SetEGLSurfaceOverride(EGLSurface surf);
     EGLSurface GetEGLSurfaceOverride() {
         return mSurfaceOverride;
     }
 
-    virtual bool MakeCurrentImpl() const override;
+    virtual bool MakeCurrentImpl(bool aForce) override;
 
-    virtual bool IsCurrentImpl() const override;
+    virtual bool IsCurrent() override;
 
     virtual bool RenewSurface(widget::CompositorWidget* aWidget) override;
 
     virtual void ReleaseSurface() override;
 
     virtual bool SetupLookupFunction() override;
 
     virtual bool SwapBuffers() override;
--- a/gfx/gl/GLContextGLX.h
+++ b/gfx/gl/GLContextGLX.h
@@ -41,19 +41,19 @@ public:
 
     static GLContextGLX* Cast(GLContext* gl) {
         MOZ_ASSERT(gl->GetContextType() == GLContextType::GLX);
         return static_cast<GLContextGLX*>(gl);
     }
 
     bool Init() override;
 
-    virtual bool MakeCurrentImpl() const override;
+    virtual bool MakeCurrentImpl(bool aForce) override;
 
-    virtual bool IsCurrentImpl() const override;
+    virtual bool IsCurrent() override;
 
     virtual bool SetupLookupFunction() override;
 
     virtual bool IsDoubleBuffered() const override;
 
     virtual bool SwapBuffers() override;
 
     virtual void GetWSIInfo(nsCString* const out) const override;
--- a/gfx/gl/GLContextProviderCGL.mm
+++ b/gfx/gl/GLContextProviderCGL.mm
@@ -105,36 +105,39 @@ GLContextCGL::Init()
 
 CGLContextObj
 GLContextCGL::GetCGLContext() const
 {
     return static_cast<CGLContextObj>([mContext CGLContextObj]);
 }
 
 bool
-GLContextCGL::MakeCurrentImpl() const
+GLContextCGL::MakeCurrentImpl(bool aForce)
 {
+    if (!aForce && [NSOpenGLContext currentContext] == mContext) {
+        return true;
+    }
+
     if (mContext) {
         [mContext makeCurrentContext];
-        MOZ_ASSERT(IsCurrentImpl());
+        MOZ_ASSERT(IsCurrent());
         // Use non-blocking swap in "ASAP mode".
         // ASAP mode means that rendering is iterated as fast as possible.
         // ASAP mode is entered when layout.frame_rate=0 (requires restart).
         // If swapInt is 1, then glSwapBuffers will block and wait for a vblank signal.
         // When we're iterating as fast as possible, however, we want a non-blocking
         // glSwapBuffers, which will happen when swapInt==0.
         GLint swapInt = gfxPrefs::LayoutFrameRate() == 0 ? 0 : 1;
         [mContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
     }
     return true;
 }
 
 bool
-GLContextCGL::IsCurrentImpl() const
-{
+GLContextCGL::IsCurrent() {
     return [NSOpenGLContext currentContext] == mContext;
 }
 
 GLenum
 GLContextCGL::GetPreferredARGB32Format() const
 {
     return LOCAL_GL_BGRA;
 }
--- a/gfx/gl/GLContextProviderEAGL.mm
+++ b/gfx/gl/GLContextProviderEAGL.mm
@@ -108,29 +108,32 @@ GLContextEAGL::RecreateRB()
     fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBackbufferFB);
     fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
                              LOCAL_GL_RENDERBUFFER, mBackbufferRB);
 
     return LOCAL_GL_FRAMEBUFFER_COMPLETE == fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
 }
 
 bool
-GLContextEAGL::MakeCurrentImpl() const
+GLContextEAGL::MakeCurrentImpl(bool aForce)
 {
+    if (!aForce && [EAGLContext currentContext] == mContext) {
+        return true;
+    }
+
     if (mContext) {
         if(![EAGLContext setCurrentContext:mContext]) {
             return false;
         }
     }
     return true;
 }
 
 bool
-GLContextEAGL::IsCurrentImpl() const
-{
+GLContextEAGL::IsCurrent() {
     return [EAGLContext currentContext] == mContext;
 }
 
 bool
 GLContextEAGL::SetupLookupFunction()
 {
     return false;
 }
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -334,46 +334,52 @@ GLContextEGL::SetEGLSurfaceOverride(EGLS
     }
 
     mSurfaceOverride = surf;
     DebugOnly<bool> ok = MakeCurrent(true);
     MOZ_ASSERT(ok);
 }
 
 bool
-GLContextEGL::MakeCurrentImpl() const
-{
-    const EGLSurface surface = (mSurfaceOverride != EGL_NO_SURFACE) ? mSurfaceOverride
-                                                                    : mSurface;
-    if (surface == EGL_NO_SURFACE) {
-        MOZ_CRASH("EGL_NO_SURFACE");
-        return false;
-    }
+GLContextEGL::MakeCurrentImpl(bool aForce) {
+    bool succeeded = true;
 
-    const bool succeeded = sEGLLibrary.fMakeCurrent(EGL_DISPLAY(), surface, surface,
-                                                    mContext);
-    if (!succeeded) {
-        const auto eglError = sEGLLibrary.fGetError();
-        if (eglError == LOCAL_EGL_CONTEXT_LOST) {
-            mContextLost = true;
-            NS_WARNING("EGL context has been lost.");
-        } else {
-            NS_WARNING("Failed to make GL context current!");
+    // Assume that EGL has the same problem as WGL does,
+    // where MakeCurrent with an already-current context is
+    // still expensive.
+    bool needsMakeCurrent = (aForce || sEGLLibrary.fGetCurrentContext() != mContext);
+    if (needsMakeCurrent) {
+        EGLSurface surface = mSurfaceOverride != EGL_NO_SURFACE
+                              ? mSurfaceOverride
+                              : mSurface;
+        if (surface == EGL_NO_SURFACE) {
+            return false;
+        }
+        succeeded = sEGLLibrary.fMakeCurrent(EGL_DISPLAY(),
+                                              surface, surface,
+                                              mContext);
+        if (!succeeded) {
+            int eglError = sEGLLibrary.fGetError();
+            if (eglError == LOCAL_EGL_CONTEXT_LOST) {
+                mContextLost = true;
+                NS_WARNING("EGL context has been lost.");
+            } else {
+                NS_WARNING("Failed to make GL context current!");
 #ifdef DEBUG
-            printf_stderr("EGL Error: 0x%04x\n", eglError);
+                printf_stderr("EGL Error: 0x%04x\n", eglError);
 #endif
+            }
         }
     }
 
     return succeeded;
 }
 
 bool
-GLContextEGL::IsCurrentImpl() const
-{
+GLContextEGL::IsCurrent() {
     return sEGLLibrary.fGetCurrentContext() == mContext;
 }
 
 bool
 GLContextEGL::RenewSurface(CompositorWidget* aWidget) {
     if (!mOwnsContext) {
         return false;
     }
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -601,40 +601,50 @@ GLContextGLX::Init()
     // so we'll also check for ARB_framebuffer_object
     if (!IsExtensionSupported(EXT_framebuffer_object) && !IsSupported(GLFeature::framebuffer_object))
         return false;
 
     return true;
 }
 
 bool
-GLContextGLX::MakeCurrentImpl() const
+GLContextGLX::MakeCurrentImpl(bool aForce)
 {
-    if (mGLX->IsMesa()) {
-        // Read into the event queue to ensure that Mesa receives a
-        // DRI2InvalidateBuffers event before drawing. See bug 1280653.
-        Unused << XPending(mDisplay);
+    bool succeeded = true;
+
+    // With the ATI FGLRX driver, glxMakeCurrent is very slow even when the context doesn't change.
+    // (This is not the case with other drivers such as NVIDIA).
+    // So avoid calling it more than necessary. Since GLX documentation says that:
+    //     "glXGetCurrentContext returns client-side information.
+    //      It does not make a round trip to the server."
+    // I assume that it's not worth using our own TLS slot here.
+    if (aForce || mGLX->fGetCurrentContext() != mContext) {
+        if (mGLX->IsMesa()) {
+          // Read into the event queue to ensure that Mesa receives a
+          // DRI2InvalidateBuffers event before drawing. See bug 1280653.
+          Unused << XPending(mDisplay);
+        }
+
+        succeeded = mGLX->fMakeCurrent(mDisplay, mDrawable, mContext);
+        NS_ASSERTION(succeeded, "Failed to make GL context current!");
+
+        if (!IsOffscreen() && mGLX->SupportsSwapControl()) {
+            // Many GLX implementations default to blocking until the next
+            // VBlank when calling glXSwapBuffers. We want to run unthrottled
+            // in ASAP mode. See bug 1280744.
+            const bool isASAP = (gfxPrefs::LayoutFrameRate() == 0);
+            mGLX->fSwapInterval(mDisplay, mDrawable, isASAP ? 0 : 1);
+        }
     }
 
-    const bool succeeded = mGLX->fMakeCurrent(mDisplay, mDrawable, mContext);
-    NS_ASSERTION(succeeded, "Failed to make GL context current!");
-
-    if (!IsOffscreen() && mGLX->SupportsSwapControl()) {
-        // Many GLX implementations default to blocking until the next
-        // VBlank when calling glXSwapBuffers. We want to run unthrottled
-        // in ASAP mode. See bug 1280744.
-        const bool isASAP = (gfxPrefs::LayoutFrameRate() == 0);
-        mGLX->fSwapInterval(mDisplay, mDrawable, isASAP ? 0 : 1);
-    }
     return succeeded;
 }
 
 bool
-GLContextGLX::IsCurrentImpl() const
-{
+GLContextGLX::IsCurrent() {
     return mGLX->fGetCurrentContext() == mContext;
 }
 
 bool
 GLContextGLX::SetupLookupFunction()
 {
     mLookupFunc = (PlatformLookupFunction)sGLXLibrary.GetGetProcAddress();
     return true;
--- a/gfx/gl/GLContextProviderWGL.cpp
+++ b/gfx/gl/GLContextProviderWGL.cpp
@@ -318,25 +318,34 @@ GLContextWGL::Init()
     SetupLookupFunction();
     if (!InitWithPrefix("gl", true))
         return false;
 
     return true;
 }
 
 bool
-GLContextWGL::MakeCurrentImpl() const
+GLContextWGL::MakeCurrentImpl(bool aForce)
 {
-    const bool succeeded = sWGLLib.mSymbols.fMakeCurrent(mDC, mContext);
-    NS_ASSERTION(succeeded, "Failed to make GL context current!");
+    BOOL succeeded = true;
+
+    // wglGetCurrentContext seems to just pull the HGLRC out
+    // of its TLS slot, so no need to do our own tls slot.
+    // You would think that wglMakeCurrent would avoid doing
+    // work if mContext was already current, but not so much..
+    if (aForce || sWGLLib.mSymbols.fGetCurrentContext() != mContext) {
+        succeeded = sWGLLib.mSymbols.fMakeCurrent(mDC, mContext);
+        NS_ASSERTION(succeeded, "Failed to make GL context current!");
+    }
+
     return succeeded;
 }
 
 bool
-GLContextWGL::IsCurrentImpl() const
+GLContextWGL::IsCurrent()
 {
     return sWGLLib.mSymbols.fGetCurrentContext() == mContext;
 }
 
 void
 GLContextWGL::SetIsDoubleBuffered(bool aIsDB)
 {
     mIsDoubleBuffered = aIsDB;
--- a/gfx/gl/GLContextWGL.h
+++ b/gfx/gl/GLContextWGL.h
@@ -40,19 +40,19 @@ public:
 
     static GLContextWGL* Cast(GLContext* gl) {
         MOZ_ASSERT(gl->GetContextType() == GLContextType::WGL);
         return static_cast<GLContextWGL*>(gl);
     }
 
     bool Init() override;
 
-    virtual bool MakeCurrentImpl() const override;
+    virtual bool MakeCurrentImpl(bool aForce) override;
 
-    virtual bool IsCurrentImpl() const override;
+    virtual bool IsCurrent() override;
 
     void SetIsDoubleBuffered(bool aIsDB);
 
     virtual bool IsDoubleBuffered() const override;
 
     virtual bool SwapBuffers() override;
 
     virtual bool SetupLookupFunction() override;
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -743,16 +743,20 @@ gfxPlatform::Init()
 
 #ifdef USE_SKIA
     SkGraphics::Init();
 #  ifdef MOZ_ENABLE_FREETYPE
     SkInitCairoFT(gPlatform->FontHintingEnabled());
 #  endif
 #endif
 
+#ifdef MOZ_GL_DEBUG
+    GLContext::StaticInit();
+#endif
+
     InitLayersIPC();
 
     gPlatform->PopulateScreenInfo();
     gPlatform->ComputeTileSize();
 
     nsresult rv;
     rv = gfxPlatformFontList::Init();
     if (NS_FAILED(rv)) {
--- a/mfbt/ThreadLocal.h
+++ b/mfbt/ThreadLocal.h
@@ -151,32 +151,33 @@ ThreadLocal<T>::init()
 template<typename T>
 inline T
 ThreadLocal<T>::get() const
 {
 #ifdef MOZ_HAS_THREAD_LOCAL
   return mValue;
 #else
   MOZ_ASSERT(initialized());
-  void* h = pthread_getspecific(mKey);
-  return static_cast<T>((typename Helper<T>::Type)h);
+  void* h;
+  h = pthread_getspecific(mKey);
+  return static_cast<T>(reinterpret_cast<typename Helper<T>::Type>(h));
 #endif
 }
 
 template<typename T>
 inline void
 ThreadLocal<T>::set(const T aValue)
 {
 #ifdef MOZ_HAS_THREAD_LOCAL
   mValue = aValue;
 #else
   MOZ_ASSERT(initialized());
-  void* h = (void*)(static_cast<typename Helper<T>::Type>(aValue));
+  void* h = reinterpret_cast<void*>(static_cast<typename Helper<T>::Type>(aValue));
   bool succeeded = !pthread_setspecific(mKey, h);
-  if (MOZ_UNLIKELY( !succeeded )) {
+  if (!succeeded) {
     MOZ_CRASH();
   }
 #endif
 }
 
 #ifdef MOZ_HAS_THREAD_LOCAL
 #if defined(XP_WIN) || defined(MACOSX_HAS_THREAD_LOCAL)
 #define MOZ_THREAD_LOCAL(TYPE) thread_local mozilla::detail::ThreadLocal<TYPE>