Bug 1399501 - !MakeCurrent() should clear the current context. - r=kvark
authorJeff Gilbert <jgilbert@mozilla.com>
Thu, 11 Oct 2018 17:18:12 -0700
changeset 442799 7b88a6284d31c87ee25d782d869c936cb0b7648d
parent 442798 c498bd18345d9061826a752b43d95a72e1593ceb
child 442800 5cb0aeccd4cc8d6417d9c92d04c2ee60ce244cbd
push id109240
push userjgilbert@mozilla.com
push dateWed, 24 Oct 2018 18:29:54 +0000
treeherdermozilla-inbound@7f1abf24702d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskvark
bugs1399501
milestone65.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 1399501 - !MakeCurrent() should clear the current context. - r=kvark Make MarkDestroyed call MakeCurrent(force=true) to clear the current context also. Differential Revision: https://phabricator.services.mozilla.com/D9289
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextCGL.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
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -376,16 +376,20 @@ GLContext::LoadFeatureSymbols(const char
         return false;
     }
     return true;
 };
 
 bool
 GLContext::InitWithPrefixImpl(const char* prefix, bool trygl)
 {
+    // see bug 929506 comment 29. wglGetProcAddress requires a current context.
+    if (!MakeCurrent(true))
+        return false;
+
     mWorkAroundDriverBugs = gfxPrefs::WorkAroundDriverBugs();
 
     const SymLoadStruct coreSymbols[] = {
         { (PRFuncPtr*) &mSymbols.fActiveTexture, { "ActiveTexture", "ActiveTextureARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fAttachShader, { "AttachShader", "AttachShaderARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fBindAttribLocation, { "BindAttribLocation", "BindAttribLocationARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fBindBuffer, { "BindBuffer", "BindBufferARB", nullptr } },
         { (PRFuncPtr*) &mSymbols.fBindTexture, { "BindTexture", "BindTextureARB", nullptr } },
@@ -512,20 +516,16 @@ GLContext::InitWithPrefixImpl(const char
         END_SYMBOLS
     };
 
     if (!LoadGLSymbols(this, prefix, trygl, coreSymbols, "GL"))
         return false;
 
     ////////////////
 
-    if (!MakeCurrent()) {
-        return false;
-    }
-
     const std::string versionStr = (const char*)fGetString(LOCAL_GL_VERSION);
     if (versionStr.find("OpenGL ES") == 0) {
         mProfile = ContextProfile::OpenGLES;
     }
 
     uint32_t majorVer, minorVer;
     if (!ParseVersion(versionStr, &majorVer, &minorVer)) {
         MOZ_ASSERT(false, "Failed to parse GL_VERSION");
@@ -2049,21 +2049,19 @@ GLContext::MarkDestroyed()
         return;
 
     // Null these before they're naturally nulled after dtor, as we want GLContext to
     // still be alive in *their* dtors.
     mScreen = nullptr;
     mBlitHelper = nullptr;
     mReadTexImageHelper = nullptr;
 
-    if (!MakeCurrent()) {
-        NS_WARNING("MakeCurrent() failed during MarkDestroyed! Skipping GL object teardown.");
-    }
-
+    mIsDestroyed = true;
     mSymbols = {};
+    (void)MakeCurrent(true); // Clear current context.
 }
 
 #ifdef MOZ_GL_DEBUG
 /* static */ void
 GLContext::AssertNotPassingStackBufferToTheGL(const void* ptr)
 {
   int somethingOnTheStack;
   const void* someStackPtr = &somethingOnTheStack;
@@ -2939,36 +2937,36 @@ GetBytesPerTexel(GLenum format, GLenum t
         return 2;
     }
 
     gfxCriticalError() << "Unknown texture type " << type << " or format " << format;
     return 0;
 }
 
 bool
-GLContext::MakeCurrent(bool aForce) const
+GLContext::MakeCurrent(const bool aForce) const
 {
-    if (MOZ_UNLIKELY( IsDestroyed() ))
-        return false;
-
-    if (MOZ_LIKELY( !aForce )) {
-        bool isCurrent;
+    if (MOZ_LIKELY( !aForce & !IsDestroyed() )) {
+        bool isCurrent = false;
         if (mUseTLSIsCurrent) {
             isCurrent = (sCurrentContext.get() == reinterpret_cast<uintptr_t>(this));
-        } else {
+        }
+        if (MOZ_UNLIKELY( !isCurrent )) {
             isCurrent = IsCurrentImpl();
         }
         if (MOZ_LIKELY( isCurrent )) {
             MOZ_ASSERT(IsCurrentImpl());
             return true;
         }
     }
 
-    if (!MakeCurrentImpl())
+    if (MOZ_UNLIKELY( !MakeCurrentImpl() )) {
+        ClearGetCurrentContextTLS();
         return false;
+    }
 
     sCurrentContext.set(reinterpret_cast<uintptr_t>(this));
     return true;
 }
 
 void
 GLContext::ResetSyncCallCount(const char* resetReason) const
 {
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -196,16 +196,20 @@ class GLContext
     : public GLLibraryLoader
     , public GenericAtomicRefCounted
     , public SupportsWeakPtr<GLContext>
 {
 public:
     MOZ_DECLARE_WEAKREFERENCE_TYPENAME(GLContext)
     static MOZ_THREAD_LOCAL(uintptr_t) sCurrentContext;
 
+    static void ClearGetCurrentContextTLS() {
+        sCurrentContext.set(0);
+    }
+
     bool mImplicitMakeCurrent = false;
     bool mUseTLSIsCurrent;
 
     class TlsScope final {
         const WeakPtr<GLContext> mGL;
         const bool mWasTlsOk;
     public:
         explicit TlsScope(GLContext* const gl)
@@ -337,16 +341,17 @@ public:
      */
     virtual GLuint GetDefaultFramebuffer() {
         return 0;
     }
 
 protected:
     bool mIsOffscreen;
     mutable bool mContextLost = false;
+    bool mIsDestroyed = false;
 
     /**
      * 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 = 0;
     ContextProfile mProfile = ContextProfile::Unknown;
 
@@ -3373,18 +3378,17 @@ protected:
 public:
     virtual bool Init() = 0;
 
     virtual bool SetupLookupFunction() = 0;
 
     virtual void ReleaseSurface() {}
 
     bool IsDestroyed() const {
-        // MarkDestroyed will mark all these as null.
-        return mSymbols.fUseProgram == nullptr;
+        return mIsDestroyed;
     }
 
     GLContext* GetSharedContext() { return mSharedContext; }
 
     /**
      * Returns true if the thread on which this context was created is the currently
      * executing thread.
      */
--- a/gfx/gl/GLContextCGL.h
+++ b/gfx/gl/GLContextCGL.h
@@ -19,17 +19,17 @@ typedef void NSOpenGLContext;
 
 namespace mozilla {
 namespace gl {
 
 class GLContextCGL : public GLContext
 {
     friend class GLContextProviderCGL;
 
-    NSOpenGLContext* mContext;
+    NSOpenGLContext* const mContext;
 
 public:
     MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextCGL, override)
     GLContextCGL(CreateContextFlags flags, const SurfaceCaps& caps,
                  NSOpenGLContext* context, bool isOffscreen);
 
     ~GLContextCGL();
 
--- a/gfx/gl/GLContextGLX.h
+++ b/gfx/gl/GLContextGLX.h
@@ -82,16 +82,17 @@ private:
                  GLXContext aContext,
                  bool aDeleteDrawable,
                  bool aDoubleBuffered,
                  gfxXlibSurface* aPixmap);
 
     GLXContext mContext;
     Display* mDisplay;
     GLXDrawable mDrawable;
+    Maybe<GLXDrawable> mOverrideDrawable;
     bool mDeleteDrawable;
     bool mDoubleBuffered;
 
     GLXLibrary* mGLX;
 
     RefPtr<gfxXlibSurface> mPixmap;
     bool mOwnsContext = true;
 };
--- a/gfx/gl/GLContextProviderCGL.mm
+++ b/gfx/gl/GLContextProviderCGL.mm
@@ -71,46 +71,39 @@ GLContextCGL::GLContextCGL(CreateContext
     : GLContext(flags, caps, nullptr, isOffscreen)
     , mContext(context)
 {
 }
 
 GLContextCGL::~GLContextCGL()
 {
     MarkDestroyed();
-
-    if (mContext) {
-        if ([NSOpenGLContext currentContext] == mContext) {
-            // Clear the current context before releasing. If we don't do
-            // this, the next time we call [NSOpenGLContext currentContext],
-            // "invalid context" will be printed to the console.
-            [NSOpenGLContext clearCurrentContext];
-        }
-        [mContext release];
-    }
+    [mContext release];
 }
 
 bool
 GLContextCGL::Init()
 {
-    if (!InitWithPrefix("gl", true))
-        return false;
-
-    return true;
+    return InitWithPrefix("gl", true);
 }
 
 CGLContextObj
 GLContextCGL::GetCGLContext() const
 {
     return static_cast<CGLContextObj>([mContext CGLContextObj]);
 }
 
 bool
 GLContextCGL::MakeCurrentImpl() const
 {
+    if (IsDestroyed()) {
+        [NSOpenGLContext clearCurrentContext];
+        return false;
+    }
+
     if (mContext) {
         [mContext makeCurrentContext];
         MOZ_ASSERT(IsCurrentImpl());
         // 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
--- a/gfx/gl/GLContextProviderEAGL.mm
+++ b/gfx/gl/GLContextProviderEAGL.mm
@@ -27,45 +27,36 @@ GLContextEAGL::GLContextEAGL(CreateConte
                              bool isOffscreen)
     : GLContext(flags, caps, sharedContext, isOffscreen)
     , mContext(context)
 {
 }
 
 GLContextEAGL::~GLContextEAGL()
 {
-    MakeCurrent();
+    if (MakeCurrent()) {
+        if (mBackbufferFB) {
+            fDeleteFramebuffers(1, &mBackbufferFB);
+        }
 
-    if (mBackbufferFB) {
-        fDeleteFramebuffers(1, &mBackbufferFB);
-    }
-
-    if (mBackbufferRB) {
-        fDeleteRenderbuffers(1, &mBackbufferRB);
+        if (mBackbufferRB) {
+            fDeleteRenderbuffers(1, &mBackbufferRB);
+        }
     }
 
-    MarkDestroyed();
+    mLayer = nil;
 
-    if (mLayer) {
-      mLayer = nil;
-    }
-
-    if (mContext) {
-      [EAGLContext setCurrentContext:nil];
-      [mContext release];
-    }
+    MarkDestroyed();
+    [mContext release];
 }
 
 bool
 GLContextEAGL::Init()
 {
-    if (!InitWithPrefix("gl", true))
-        return false;
-
-    return true;
+    return InitWithPrefix("gl", true);
 }
 
 bool
 GLContextEAGL::AttachToWindow(nsIWidget* aWidget)
 {
     // This should only be called once
     MOZ_ASSERT(!mBackbufferFB && !mBackbufferRB);
 
@@ -107,22 +98,21 @@ GLContextEAGL::RecreateRB()
                              LOCAL_GL_RENDERBUFFER, mBackbufferRB);
 
     return LOCAL_GL_FRAMEBUFFER_COMPLETE == fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
 }
 
 bool
 GLContextEAGL::MakeCurrentImpl() const
 {
-    if (mContext) {
-        if(![EAGLContext setCurrentContext:mContext]) {
-            return false;
-        }
+    if (IsDestroyed()) {
+        [EAGLContext setCurrentContext:nil];
+        return false;
     }
-    return true;
+    return [EAGLContext setCurrentContext:mContext];
 }
 
 bool
 GLContextEAGL::IsCurrentImpl() const
 {
     return [EAGLContext currentContext] == mContext;
 }
 
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -153,29 +153,26 @@ is_power_of_two(int v)
 
     if (v == 0)
         return true;
 
     return (v & (v-1)) == 0;
 }
 
 static void
-DestroySurface(EGLSurface oldSurface) {
-    auto* egl = gl::GLLibraryEGL::Get();
+DestroySurface(const EGLSurface surf)
+{
+    MOZ_ASSERT(surf);
+    const auto& egl = gl::GLLibraryEGL::Get();
 
-    if (oldSurface != EGL_NO_SURFACE) {
-        // TODO: This breaks TLS MakeCurrent caching.
-        egl->fMakeCurrent(EGL_DISPLAY(),
-                          EGL_NO_SURFACE, EGL_NO_SURFACE,
-                          EGL_NO_CONTEXT);
-        egl->fDestroySurface(EGL_DISPLAY(), oldSurface);
+    // TODO: This breaks TLS MakeCurrent caching.
+    MOZ_ALWAYS_TRUE( egl->fDestroySurface(EGL_DISPLAY(), surf) );
 #if defined(MOZ_WAYLAND)
-        DeleteWaylandGLSurface(oldSurface);
+    DeleteWaylandGLSurface(surf);
 #endif
-    }
 }
 
 static EGLSurface
 CreateFallbackSurface(const EGLConfig& config)
 {
     nsCString discardFailureId;
     if (!GLLibraryEGL::EnsureInitialized(false, &discardFailureId)) {
         gfxCriticalNote << "Failed to load EGL library 3!";
@@ -279,17 +276,17 @@ GLContextEGLFactory::Create(EGLNativeWin
     if (aWebRender) {
         flags |= CreateContextFlags::PREFER_ES3;
     }
     SurfaceCaps caps = SurfaceCaps::Any();
     RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(flags, caps, false, config,
                                                             surface, &discardFailureId);
     if (!gl) {
         gfxCriticalNote << "Failed to create EGLContext!";
-        mozilla::gl::DestroySurface(surface);
+        DestroySurface(surface);
         return nullptr;
     }
 
     gl->MakeCurrent();
     gl->SetIsDoubleBuffered(doubleBuffered);
     if (aWebRender && egl->IsANGLE()) {
         MOZ_ASSERT(doubleBuffered);
         egl->fSwapInterval(EGL_DISPLAY(), 0);
@@ -321,19 +318,22 @@ GLContextEGL::~GLContextEGL()
         return;
     }
 
 #ifdef DEBUG
     printf_stderr("Destroying context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY());
 #endif
 
     mEgl->fDestroyContext(EGL_DISPLAY(), mContext);
-
-    mozilla::gl::DestroySurface(mSurface);
-    mozilla::gl::DestroySurface(mFallbackSurface);
+    if (mSurface) {
+        DestroySurface(mSurface);
+    }
+    if (mFallbackSurface) {
+        DestroySurface(mFallbackSurface);
+    }
 }
 
 bool
 GLContextEGL::Init()
 {
 #if defined(ANDROID)
     // We can't use LoadApitraceLibrary here because the GLContext
     // expects its own handle to the GL library
@@ -346,23 +346,17 @@ GLContextEGL::Init()
                 return false;
             }
 #endif
         }
 
     SetupLookupFunction();
     if (!InitWithPrefix("gl", true))
         return false;
-
-    bool current = MakeCurrent();
-    if (!current) {
-        gfx::LogFailure(NS_LITERAL_CSTRING(
-            "Couldn't get device attachments for device."));
-        return false;
-    }
+    MOZ_ASSERT(IsCurrent());
 
     static_assert(sizeof(GLint) >= sizeof(int32_t), "GLint is smaller than int32_t");
     mMaxTextureImageSize = INT32_MAX;
 
     mShareWithEGLImage = mEgl->HasKHRImageBase() &&
                          mEgl->HasKHRImageTexture2D() &&
                          IsExtensionSupported(OES_EGL_image);
 
@@ -403,36 +397,45 @@ GLContextEGL::ReleaseTexImage()
     if (success == LOCAL_EGL_FALSE)
         return false;
 
     mBound = false;
     return true;
 }
 
 void
-GLContextEGL::SetEGLSurfaceOverride(EGLSurface surf) {
+GLContextEGL::SetEGLSurfaceOverride(const EGLSurface surf)
+{
+    MOZ_ASSERT(!surf || surf != mSurface);
+
     if (Screen()) {
         /* Blit `draw` to `read` if we need to, before we potentially juggle
           * `read` around. If we don't, we might attach a different `read`,
           * and *then* hit AssureBlitted, which will blit a dirty `draw` onto
           * the wrong `read`!
           */
         Screen()->AssureBlitted();
     }
 
     mSurfaceOverride = surf;
-    DebugOnly<bool> ok = MakeCurrent(true);
-    MOZ_ASSERT(ok);
+    MOZ_ALWAYS_TRUE( MakeCurrent(true) );
 }
 
 bool
 GLContextEGL::MakeCurrentImpl() const
 {
-    EGLSurface surface = (mSurfaceOverride != EGL_NO_SURFACE) ? mSurfaceOverride
-                                                              : mSurface;
+    if (IsDestroyed()) {
+        MOZ_ALWAYS_TRUE( mEgl->fMakeCurrent(EGL_DISPLAY(), nullptr, nullptr, nullptr) );
+        return false;
+    }
+
+    auto surface = mSurface;
+    if (mSurfaceOverride) {
+        surface = mSurfaceOverride;
+    }
     if (!surface) {
         surface = mFallbackSurface;
     }
 
     const bool succeeded = mEgl->fMakeCurrent(EGL_DISPLAY(), surface, surface,
                                               mContext);
     if (!succeeded) {
         const auto eglError = mEgl->fGetError();
@@ -452,17 +455,18 @@ GLContextEGL::MakeCurrentImpl() const
 
 bool
 GLContextEGL::IsCurrentImpl() const
 {
     return mEgl->fGetCurrentContext() == mContext;
 }
 
 bool
-GLContextEGL::RenewSurface(CompositorWidget* aWidget) {
+GLContextEGL::RenewSurface(CompositorWidget* const aWidget)
+{
     if (!mOwnsContext) {
         return false;
     }
     // unconditionally release the surface and create a new one. Don't try to optimize this away.
     // If we get here, then by definition we know that we want to get a new surface.
     ReleaseSurface();
     MOZ_ASSERT(aWidget);
 
@@ -474,24 +478,23 @@ GLContextEGL::RenewSurface(CompositorWid
             return false;
         }
     }
 
     return MakeCurrent(true);
 }
 
 void
-GLContextEGL::ReleaseSurface() {
-    if (mOwnsContext) {
-        mozilla::gl::DestroySurface(mSurface);
-    }
-    if (mSurface == mSurfaceOverride) {
-        mSurfaceOverride = EGL_NO_SURFACE;
-    }
-    mSurface = EGL_NO_SURFACE;
+GLContextEGL::ReleaseSurface()
+{
+    if (!mOwnsContext)
+        return;
+
+    mozilla::gl::DestroySurface(mSurface);
+    mSurface = nullptr;
 }
 
 bool
 GLContextEGL::SetupLookupFunction()
 {
     mLookupFunc = mEgl->GetLookupFunction();
     return true;
 }
--- a/gfx/gl/GLContextProviderGLX.cpp
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -582,30 +582,22 @@ GLContextGLX::~GLContextGLX()
 {
     MarkDestroyed();
 
     // Wrapped context should not destroy glxContext/Surface
     if (!mOwnsContext) {
         return;
     }
 
-    // see bug 659842 comment 76
-#ifdef DEBUG
-    bool success =
-#endif
-    mGLX->fMakeCurrent(mDisplay, X11None, nullptr);
-    MOZ_ASSERT(success,
-               "glXMakeCurrent failed to release GL context before we call "
-               "glXDestroyContext!");
-
     mGLX->fDestroyContext(mDisplay, mContext);
 
     if (mDeleteDrawable) {
         mGLX->fDestroyPixmap(mDisplay, mDrawable);
     }
+    MOZ_ASSERT(!mOverrideDrawable);
 }
 
 
 bool
 GLContextGLX::Init()
 {
     SetupLookupFunction();
     if (!InitWithPrefix("gl", true)) {
@@ -624,17 +616,26 @@ bool
 GLContextGLX::MakeCurrentImpl() const
 {
     if (mGLX->IsMesa()) {
         // Read into the event queue to ensure that Mesa receives a
         // DRI2InvalidateBuffers event before drawing. See bug 1280653.
         Unused << XPending(mDisplay);
     }
 
-    const bool succeeded = mGLX->fMakeCurrent(mDisplay, mDrawable, mContext);
+    if (IsDestroyed()) {
+        MOZ_ALWAYS_TRUE( mGLX->fMakeCurrent(mDisplay, X11None, nullptr) );
+        return false; // Did not MakeCurrent mContext, but that's what we wanted!
+    }
+
+    auto drawable = mDrawable;
+    if (mOverrideDrawable) {
+        drawable = mOverrideDrawable.ref();
+    }
+    const bool succeeded = mGLX->fMakeCurrent(mDisplay, drawable, 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);
@@ -689,26 +690,28 @@ GLContextGLX::GetWSIInfo(nsCString* cons
 
     out->AppendLiteral("\nExtensions: ");
     out->Append(sGLXLibrary.fQueryExtensionsString(display, screen));
 }
 
 bool
 GLContextGLX::OverrideDrawable(GLXDrawable drawable)
 {
-    if (Screen())
+    if (Screen()) {
         Screen()->AssureBlitted();
-    Bool result = mGLX->fMakeCurrent(mDisplay, drawable, mContext);
-    return result;
+    }
+    mOverrideDrawable = Some(drawable);
+    return MakeCurrent(true);
 }
 
 bool
 GLContextGLX::RestoreDrawable()
 {
-    return mGLX->fMakeCurrent(mDisplay, mDrawable, mContext);
+    mOverrideDrawable = Nothing();
+    return MakeCurrent(true);
 }
 
 GLContextGLX::GLContextGLX(
                   CreateContextFlags flags,
                   const SurfaceCaps& caps,
                   bool isOffscreen,
                   Display* aDisplay,
                   GLXDrawable aDrawable,
--- a/gfx/gl/GLContextProviderWGL.cpp
+++ b/gfx/gl/GLContextProviderWGL.cpp
@@ -158,17 +158,16 @@ WGLLibrary::EnsureInitialized()
 
     // create rendering context
     mDummyGlrc = mSymbols.fCreateContext(mRootDc);
     if (!mDummyGlrc)
         return false;
 
     const auto curCtx = mSymbols.fGetCurrentContext();
     const auto curDC = mSymbols.fGetCurrentDC();
-
     if (!mSymbols.fMakeCurrent(mRootDc, mDummyGlrc)) {
         NS_WARNING("wglMakeCurrent failed");
         return false;
     }
     const auto resetContext = MakeScopeExit([&]() {
         mSymbols.fMakeCurrent(curDC, curCtx);
     });
 
@@ -294,17 +293,16 @@ GLContextWGL::GLContextWGL(CreateContext
       mPBuffer(aPbuffer),
       mPixelFormat(aPixelFormat)
 {
 }
 
 GLContextWGL::~GLContextWGL()
 {
     MarkDestroyed();
-
     (void)sWGLLib.mSymbols.fDeleteContext(mContext);
 
     if (mPBuffer) {
         (void)sWGLLib.mSymbols.fReleasePbufferDC(mPBuffer, mDC);
         (void)sWGLLib.mSymbols.fDestroyPbuffer(mPBuffer);
     }
     if (mWnd) {
         (void)ReleaseDC(mWnd, mDC);
@@ -313,30 +311,28 @@ GLContextWGL::~GLContextWGL()
 }
 
 bool
 GLContextWGL::Init()
 {
     if (!mDC || !mContext)
         return false;
 
-    // see bug 929506 comment 29. wglGetProcAddress requires a current context.
-    if (!sWGLLib.mSymbols.fMakeCurrent(mDC, mContext))
-        return false;
-
     SetupLookupFunction();
-    if (!InitWithPrefix("gl", true))
-        return false;
-
-    return true;
+    return InitWithPrefix("gl", true);
 }
 
 bool
 GLContextWGL::MakeCurrentImpl() const
 {
+    if (IsDestroyed()) {
+        MOZ_ALWAYS_TRUE( sWGLLib.mSymbols.fMakeCurrent(0, 0) );
+        return false;
+    }
+
     const bool succeeded = sWGLLib.mSymbols.fMakeCurrent(mDC, mContext);
     NS_ASSERTION(succeeded, "Failed to make GL context current!");
     return succeeded;
 }
 
 bool
 GLContextWGL::IsCurrentImpl() const
 {