Bug 1399501 - !MakeCurrent() should clear the current context. - r=kvark
authorJeff Gilbert <jgilbert@mozilla.com>
Thu, 11 Oct 2018 17:18:12 -0700
changeset 491131 7b88a6284d31c87ee25d782d869c936cb0b7648d
parent 491130 c498bd18345d9061826a752b43d95a72e1593ceb
child 491132 5cb0aeccd4cc8d6417d9c92d04c2ee60ce244cbd
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewerskvark
bugs1399501
milestone65.0a1
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
 {