Bug 1347731 - Simplify WGL initialization code. - r=daoshengmu draft
authorJeff Gilbert <jgilbert@mozilla.com>
Tue, 02 Jan 2018 18:30:15 -0800
changeset 715187 1673f0dd998a83cdeb5d712f6e511798dfc2f592
parent 713743 62dd5404cf55e29412d5fff8fe9105076b1ca437
child 744727 fc2223a801bdc1bc657b7848b5a340aec4a660f4
push id94087
push userbmo:jgilbert@mozilla.com
push dateWed, 03 Jan 2018 02:30:34 +0000
reviewersdaoshengmu
bugs1347731
milestone59.0a1
Bug 1347731 - Simplify WGL initialization code. - r=daoshengmu MozReview-Commit-ID: DpS0nkTghXD
gfx/gl/GLContextProviderWGL.cpp
gfx/gl/GLContextWGL.h
gfx/gl/WGLLibrary.h
--- a/gfx/gl/GLContextProviderWGL.cpp
+++ b/gfx/gl/GLContextProviderWGL.cpp
@@ -26,73 +26,50 @@
 namespace mozilla {
 namespace gl {
 
 using namespace mozilla::gfx;
 using namespace mozilla::widget;
 
 WGLLibrary sWGLLib;
 
-HWND
-WGLLibrary::CreateDummyWindow(HDC* aWindowDC)
+
+
+/*
+ScopedWindow::~ScopedWindow()
 {
-    WNDCLASSW wc;
+    if (mDC) {
+        MOZ_ALWAYS_TRUE( ReleaseDC(mDC) );
+    }
+    if (mWindow) {
+        MOZ_ALWAYS_TRUE( DestroyWindow(mWindow) );
+    }
+}
+*/
+static HWND
+CreateDummyWindow()
+{
+    WNDCLASSW wc{};
     if (!GetClassInfoW(GetModuleHandle(nullptr), L"GLContextWGLClass", &wc)) {
-        ZeroMemory(&wc, sizeof(WNDCLASSW));
+        wc = {};
         wc.style = CS_OWNDC;
         wc.hInstance = GetModuleHandle(nullptr);
         wc.lpfnWndProc = DefWindowProc;
         wc.lpszClassName = L"GLContextWGLClass";
         if (!RegisterClassW(&wc)) {
             NS_WARNING("Failed to register GLContextWGLClass?!");
             // er. failed to register our class?
             return nullptr;
         }
     }
 
-    HWND win = CreateWindowW(L"GLContextWGLClass", L"GLContextWGL", 0,
-                             0, 0, 16, 16,
-                             nullptr, nullptr, GetModuleHandle(nullptr),
-                             nullptr);
-    NS_ENSURE_TRUE(win, nullptr);
-
-    HDC dc = GetDC(win);
-    NS_ENSURE_TRUE(dc, nullptr);
-
-    if (mWindowPixelFormat == 0) {
-        PIXELFORMATDESCRIPTOR pfd;
-        ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
-        pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
-        pfd.nVersion = 1;
-        pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
-        pfd.iPixelType = PFD_TYPE_RGBA;
-        pfd.cColorBits = 24;
-        pfd.cRedBits = 8;
-        pfd.cGreenBits = 8;
-        pfd.cBlueBits = 8;
-        pfd.cAlphaBits = 8;
-        pfd.cDepthBits = gfxVars::UseWebRender() ? 24 : 0;
-        pfd.iLayerType = PFD_MAIN_PLANE;
-
-        mWindowPixelFormat = ChoosePixelFormat(dc, &pfd);
-    }
-
-    if (!mWindowPixelFormat ||
-        !SetPixelFormat(dc, mWindowPixelFormat, nullptr))
-    {
-        NS_WARNING("SetPixelFormat failed!");
-        DestroyWindow(win);
-        return nullptr;
-    }
-
-    if (aWindowDC) {
-        *aWindowDC = dc;
-    }
-
-    return win;
+    return CreateWindowW(L"GLContextWGLClass", L"GLContextWGL", 0,
+                         0, 0, 1, 1,
+                         nullptr, nullptr, GetModuleHandle(nullptr),
+                         nullptr);
 }
 
 static inline bool
 HasExtension(const char* aExtensions, const char* aRequiredExtension)
 {
     return GLContext::ListHasExtension(
         reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension);
 }
@@ -132,147 +109,173 @@ WGLLibrary::EnsureInitialized()
         END_OF_SYMBOLS
     };
 
     if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &earlySymbols[0])) {
         NS_WARNING("Couldn't find required entry points in OpenGL DLL (early init)");
         return false;
     }
 
-    // This is ridiculous -- we have to actually create a context to
-    // get the OpenGL ICD to load.
-    mWindow = CreateDummyWindow(&mWindowDC);
-    NS_ENSURE_TRUE(mWindow, false);
+    mDummyWindow = CreateDummyWindow();
+    MOZ_ASSERT(mDummyWindow);
+    if (!mDummyWindow)
+        return false;
+    auto cleanup = MakeScopeExit([&]() {
+        Reset();
+    });
+
+    mRootDc = GetDC(mDummyWindow);
+    MOZ_ASSERT(mRootDc);
+    if (!mRootDc)
+        return false;
+
+    // --
+
+    {
+        PIXELFORMATDESCRIPTOR pfd{};
+        pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
+        pfd.nVersion = 1;
+        pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+        //pfd.iPixelType = PFD_TYPE_RGBA;
+        //pfd.cColorBits = 24;
+        //pfd.cRedBits = 8;
+        //pfd.cGreenBits = 8;
+        //pfd.cBlueBits = 8;
+        //pfd.cAlphaBits = 8;
+        pfd.iLayerType = PFD_MAIN_PLANE;
+
+        const auto pixelFormat = ChoosePixelFormat(mRootDc, &pfd);
+        MOZ_ASSERT(pixelFormat);
+        if (!pixelFormat)
+            return false;
+        const bool setPixelFormatOk = SetPixelFormat(mRootDc, pixelFormat, nullptr);
+        MOZ_ASSERT(setPixelFormatOk);
+        if (!setPixelFormatOk)
+            return false;
+    }
+
+    // --
 
     // create rendering context
-    mWindowGLContext = mSymbols.fCreateContext(mWindowDC);
-    NS_ENSURE_TRUE(mWindowGLContext, false);
+    mDummyGlrc = mSymbols.fCreateContext(mRootDc);
+    if (!mDummyGlrc)
+        return false;
 
-    if (!mSymbols.fMakeCurrent(mWindowDC, mWindowGLContext)) {
+    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);
+    });
 
-    const auto& curCtx = mSymbols.fGetCurrentContext();
-    const auto& curDC = mSymbols.fGetCurrentDC();
-
-    const auto& lookupFunc = (GLLibraryLoader::PlatformLookupFunction)mSymbols.fGetProcAddress;
+    const auto lookupFunc = (GLLibraryLoader::PlatformLookupFunction)mSymbols.fGetProcAddress;
 
     // Now we can grab all the other symbols that we couldn't without having
     // a context current.
-    const GLLibraryLoader::SymLoadStruct pbufferSymbols[] = {
+    const GLLibraryLoader::SymLoadStruct reqExtSymbols[] = {
         { (PRFuncPtr*)&mSymbols.fCreatePbuffer, { "wglCreatePbufferARB", "wglCreatePbufferEXT", nullptr } },
         { (PRFuncPtr*)&mSymbols.fDestroyPbuffer, { "wglDestroyPbufferARB", "wglDestroyPbufferEXT", nullptr } },
         { (PRFuncPtr*)&mSymbols.fGetPbufferDC, { "wglGetPbufferDCARB", "wglGetPbufferDCEXT", nullptr } },
-        { (PRFuncPtr*)&mSymbols.fBindTexImage, { "wglBindTexImageARB", "wglBindTexImageEXT", nullptr } },
-        { (PRFuncPtr*)&mSymbols.fReleaseTexImage, { "wglReleaseTexImageARB", "wglReleaseTexImageEXT", nullptr } },
-        END_OF_SYMBOLS
-    };
-
-    const GLLibraryLoader::SymLoadStruct pixFmtSymbols[] = {
+        { (PRFuncPtr*)&mSymbols.fReleasePbufferDC, { "wglReleasePbufferDCARB", "wglReleasePbufferDCEXT", nullptr } },
+    //    { (PRFuncPtr*)&mSymbols.fBindTexImage, { "wglBindTexImageARB", "wglBindTexImageEXT", nullptr } },
+    //    { (PRFuncPtr*)&mSymbols.fReleaseTexImage, { "wglReleaseTexImageARB", "wglReleaseTexImageEXT", nullptr } },
         { (PRFuncPtr*)&mSymbols.fChoosePixelFormat, { "wglChoosePixelFormatARB", "wglChoosePixelFormatEXT", nullptr } },
-        { (PRFuncPtr*)&mSymbols.fGetPixelFormatAttribiv, { "wglGetPixelFormatAttribivARB", "wglGetPixelFormatAttribivEXT", nullptr } },
-        END_OF_SYMBOLS
-    };
-
-    if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, pbufferSymbols, lookupFunc)) {
-        // this isn't an error, just means that pbuffers aren't supported
-        ClearSymbols(pbufferSymbols);
-    }
-
-    if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, pixFmtSymbols, lookupFunc)) {
-        // this isn't an error, just means that we don't have the pixel format extension
-        ClearSymbols(pixFmtSymbols);
-    }
-
-    const GLLibraryLoader::SymLoadStruct extensionsSymbols[] = {
+    //    { (PRFuncPtr*)&mSymbols.fGetPixelFormatAttribiv, { "wglGetPixelFormatAttribivARB", "wglGetPixelFormatAttribivEXT", nullptr } },
         SYMBOL(GetExtensionsStringARB),
         END_OF_SYMBOLS
     };
-
-    const GLLibraryLoader::SymLoadStruct robustnessSymbols[] = {
-        SYMBOL(CreateContextAttribsARB),
-        END_OF_SYMBOLS
-    };
+    if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, reqExtSymbols, lookupFunc)) {
+        NS_WARNING("reqExtSymbols missing");
+        return false;
+    }
 
-    const GLLibraryLoader::SymLoadStruct dxInteropSymbols[] = {
-        SYMBOL(DXSetResourceShareHandleNV),
-        SYMBOL(DXOpenDeviceNV),
-        SYMBOL(DXCloseDeviceNV),
-        SYMBOL(DXRegisterObjectNV),
-        SYMBOL(DXUnregisterObjectNV),
-        SYMBOL(DXObjectAccessNV),
-        SYMBOL(DXLockObjectsNV),
-        SYMBOL(DXUnlockObjectsNV),
-        END_OF_SYMBOLS
-    };
+    // --
 
-    if (GLLibraryLoader::LoadSymbols(mOGLLibrary, extensionsSymbols, lookupFunc)) {
-        const char* extString = mSymbols.fGetExtensionsStringARB(mWindowDC);
-        MOZ_ASSERT(extString);
-        MOZ_ASSERT(HasExtension(extString, "WGL_ARB_extensions_string"));
+    const auto extString = mSymbols.fGetExtensionsStringARB(mRootDc);
+    MOZ_ASSERT(extString);
+    MOZ_ASSERT(HasExtension(extString, "WGL_ARB_extensions_string"));
+
+    // --
 
-        if (HasExtension(extString, "WGL_ARB_create_context")) {
-            if (GLLibraryLoader::LoadSymbols(mOGLLibrary, robustnessSymbols, lookupFunc)) {
-                if (HasExtension(extString, "WGL_ARB_create_context_robustness")) {
-                    mHasRobustness = true;
-                }
-            } else {
-                NS_ERROR("WGL supports ARB_create_context without supplying its functions.");
-                ClearSymbols(robustnessSymbols);
+    if (HasExtension(extString, "WGL_ARB_create_context")) {
+        const GLLibraryLoader::SymLoadStruct createContextSymbols[] = {
+            SYMBOL(CreateContextAttribsARB),
+            END_OF_SYMBOLS
+        };
+        if (GLLibraryLoader::LoadSymbols(mOGLLibrary, createContextSymbols, lookupFunc)) {
+            if (HasExtension(extString, "WGL_ARB_create_context_robustness")) {
+                mHasRobustness = true;
             }
-        }
-
-        ////
-
-        bool hasDXInterop2 = HasExtension(extString, "WGL_NV_DX_interop2");
-        if (gfxVars::DXInterop2Blocked() &&
-            !gfxPrefs::IgnoreDXInterop2Blacklist())
-        {
-            hasDXInterop2 = false;
-        }
-
-        if (hasDXInterop2) {
-            if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, dxInteropSymbols,
-                                              lookupFunc))
-            {
-                NS_ERROR("WGL supports NV_DX_interop(2) without supplying its functions.");
-                ClearSymbols(dxInteropSymbols);
-            }
+        } else {
+            NS_ERROR("WGL_ARB_create_context announced without supplying its functions.");
+            ClearSymbols(createContextSymbols);
         }
     }
 
-    // reset back to the previous context, just in case
-    mSymbols.fMakeCurrent(curDC, curCtx);
+    // --
 
-    if (mHasRobustness) {
-        mSymbols.fDeleteContext(mWindowGLContext);
+    bool hasDXInterop2 = HasExtension(extString, "WGL_NV_DX_interop2");
+    if (gfxVars::DXInterop2Blocked() &&
+        !gfxPrefs::IgnoreDXInterop2Blacklist())
+    {
+        hasDXInterop2 = false;
+    }
 
-        const int attribs[] = {
-            LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
-            LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB,
-            0
+    if (hasDXInterop2) {
+        const GLLibraryLoader::SymLoadStruct dxInteropSymbols[] = {
+            SYMBOL(DXSetResourceShareHandleNV),
+            SYMBOL(DXOpenDeviceNV),
+            SYMBOL(DXCloseDeviceNV),
+            SYMBOL(DXRegisterObjectNV),
+            SYMBOL(DXUnregisterObjectNV),
+            SYMBOL(DXObjectAccessNV),
+            SYMBOL(DXLockObjectsNV),
+            SYMBOL(DXUnlockObjectsNV),
+            END_OF_SYMBOLS
         };
-
-        mWindowGLContext = mSymbols.fCreateContextAttribsARB(mWindowDC, nullptr, attribs);
-        if (!mWindowGLContext) {
-            mHasRobustness = false;
-            mWindowGLContext = mSymbols.fCreateContext(mWindowDC);
+        if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, dxInteropSymbols, lookupFunc)) {
+            NS_ERROR("WGL_NV_DX_interop2 announceed without supplying its functions.");
+            ClearSymbols(dxInteropSymbols);
         }
     }
 
+    // --
+
+    cleanup.release();
+
     mInitialized = true;
 
     reporter.SetSuccessful();
     return true;
 }
 
 #undef SYMBOL
 #undef END_OF_SYMBOLS
 
+void
+WGLLibrary::Reset()
+{
+    if (mDummyGlrc) {
+        (void)mSymbols.fDeleteContext(mDummyGlrc);
+        mDummyGlrc = nullptr;
+    }
+    if (mRootDc) {
+        (void)ReleaseDC(mDummyWindow, mRootDc);
+        mRootDc = nullptr;
+    }
+    if (mDummyWindow) {
+        (void)DestroyWindow(mDummyWindow);
+        mDummyWindow = nullptr;
+    }
+}
+
 GLContextWGL::GLContextWGL(CreateContextFlags flags, const SurfaceCaps& caps,
                            bool isOffscreen, HDC aDC, HGLRC aContext, HWND aWindow)
     : GLContext(flags, caps, nullptr, isOffscreen),
       mDC(aDC),
       mContext(aContext),
       mWnd(aWindow),
       mPBuffer(nullptr),
       mPixelFormat(0),
@@ -292,22 +295,26 @@ GLContextWGL::GLContextWGL(CreateContext
       mIsDoubleBuffered(false)
 {
 }
 
 GLContextWGL::~GLContextWGL()
 {
     MarkDestroyed();
 
-    sWGLLib.mSymbols.fDeleteContext(mContext);
+    (void)sWGLLib.mSymbols.fDeleteContext(mContext);
 
-    if (mPBuffer)
-        sWGLLib.mSymbols.fDestroyPbuffer(mPBuffer);
-    if (mWnd)
+    if (mPBuffer) {
+        (void)sWGLLib.mSymbols.fReleasePbufferDC(mPBuffer, mDC);
+        (void)sWGLLib.mSymbols.fDestroyPbuffer(mPBuffer);
+    }
+    if (mWnd) {
+        (void)ReleaseDC(mWnd, mDC);
         DestroyWindow(mWnd);
+    }
 }
 
 bool
 GLContextWGL::Init()
 {
     if (!mDC || !mContext)
         return false;
 
@@ -331,30 +338,19 @@ GLContextWGL::MakeCurrentImpl() const
 }
 
 bool
 GLContextWGL::IsCurrentImpl() const
 {
     return sWGLLib.mSymbols.fGetCurrentContext() == mContext;
 }
 
-void
-GLContextWGL::SetIsDoubleBuffered(bool aIsDB)
+bool
+GLContextWGL::SwapBuffers()
 {
-    mIsDoubleBuffered = aIsDB;
-}
-
-bool
-GLContextWGL::IsDoubleBuffered() const
-{
-    return mIsDoubleBuffered;
-}
-
-bool
-GLContextWGL::SwapBuffers() {
     if (!mIsDoubleBuffered)
         return false;
     return ::SwapBuffers(mDC);
 }
 
 void
 GLContextWGL::GetWSIInfo(nsCString* const out) const
 {
@@ -370,261 +366,223 @@ GLContextWGL::SetupLookupFunction()
     // the right thing for some core functions.
     MOZ_ASSERT(mLibrary == nullptr);
 
     mLibrary = sWGLLib.GetOGLLibrary();
     mLookupFunc = (PlatformLookupFunction)sWGLLib.mSymbols.fGetProcAddress;
     return true;
 }
 
-static bool
-GetMaxSize(HDC hDC, int format, IntSize& size)
-{
-    int query[] = {LOCAL_WGL_MAX_PBUFFER_WIDTH_ARB, LOCAL_WGL_MAX_PBUFFER_HEIGHT_ARB};
-    int result[2];
-
-    // (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int* piValues)
-    if (!sWGLLib.mSymbols.fGetPixelFormatAttribiv(hDC, format, 0, 2, query, result))
-        return false;
-
-    size.width = result[0];
-    size.height = result[1];
-    return true;
-}
-
-static bool
-IsValidSizeForFormat(HDC hDC, int format,
-                     const IntSize& requested)
-{
-    IntSize max;
-    if (!GetMaxSize(hDC, format, max))
-        return true;
-
-    if (requested.width > max.width)
-        return false;
-    if (requested.height > max.height)
-        return false;
-
-    return true;
-}
-
 already_AddRefed<GLContext>
 GLContextProviderWGL::CreateWrappingExisting(void*, void*)
 {
     return nullptr;
 }
 
-already_AddRefed<GLContext>
-CreateForWidget(HWND aHwnd,
-                bool aWebRender,
-                bool aForceAccelerated)
+HGLRC
+WGLLibrary::CreateContextWithFallback(const HDC dc, const bool tryRobustBuffers) const
 {
-    if (!sWGLLib.EnsureInitialized()) {
-        return nullptr;
-    }
+    if (mHasRobustness) {
+        if (tryRobustBuffers) {
+            const int attribs[] = {
+                LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
+                LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB,
+                0
+            };
+            const auto context = mSymbols.fCreateContextAttribsARB(dc, nullptr, attribs);
+            if (context)
+                return context;
+        }
 
-    /**
-       * We need to make sure we call SetPixelFormat -after- calling
-       * EnsureInitialized, otherwise it can load/unload the dll and
-       * wglCreateContext will fail.
-       */
-
-    HDC dc = ::GetDC(aHwnd);
-
-    SetPixelFormat(dc, sWGLLib.GetWindowPixelFormat(), nullptr);
-    HGLRC context;
-
-    if (sWGLLib.HasRobustness()) {
-        int attribs[] = {
-            LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
+        const int attribs[] = {
             LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB,
             0
         };
-
-        context = sWGLLib.mSymbols.fCreateContextAttribsARB(dc, nullptr, attribs);
-    } else {
-        context = sWGLLib.mSymbols.fCreateContext(dc);
+        const auto context = mSymbols.fCreateContextAttribsARB(dc, nullptr, attribs);
+        if (context)
+            return context;
+    }
+    if (mSymbols.fCreateContextAttribsARB) {
+        const auto context = mSymbols.fCreateContextAttribsARB(dc, nullptr, nullptr);
+        if (context)
+            return context;
     }
+    return mSymbols.fCreateContext(dc);
+}
 
-    if (!context) {
+static RefPtr<GLContext>
+CreateForWidget(const HWND window, const bool isWebRender, const bool requireAccelerated)
+{
+    auto& wgl = sWGLLib;
+    if (!wgl.EnsureInitialized())
+        return nullptr;
+
+    const auto dc = GetDC(window);
+    if (!dc)
         return nullptr;
+    auto cleanupDc = MakeScopeExit([&](){
+        (void)ReleaseDC(window, dc);
+    });
+
+    int chosenFormat;
+    UINT foundFormats = 0;
+
+    if (!foundFormats) {
+        const int kAttribs[] = {
+            LOCAL_WGL_DRAW_TO_WINDOW_ARB, true,
+            LOCAL_WGL_SUPPORT_OPENGL_ARB, true,
+            LOCAL_WGL_DOUBLE_BUFFER_ARB, true,
+            LOCAL_WGL_ACCELERATION_ARB, LOCAL_WGL_FULL_ACCELERATION_ARB,
+            0
+        };
+        if (!wgl.mSymbols.fChoosePixelFormat(wgl.RootDc(), kAttribs, nullptr, 1,
+                                             &chosenFormat, &foundFormats))
+        {
+            foundFormats = 0;
+        }
     }
+    if (!foundFormats) {
+        if (requireAccelerated)
+            return nullptr;
+
+        const int kAttribs[] = {
+            LOCAL_WGL_DRAW_TO_WINDOW_ARB, true,
+            LOCAL_WGL_SUPPORT_OPENGL_ARB, true,
+            LOCAL_WGL_DOUBLE_BUFFER_ARB, true,
+            0
+        };
+        if (!wgl.mSymbols.fChoosePixelFormat(wgl.RootDc(), kAttribs, nullptr, 1,
+                                             &chosenFormat, &foundFormats))
+        {
+            foundFormats = 0;
+        }
+    }
+    if (!foundFormats)
+        return nullptr;
+
+    // We need to make sure we call SetPixelFormat -after- calling
+    // EnsureInitialized, otherwise it can load/unload the dll and
+    // wglCreateContext will fail.
+
+    SetPixelFormat(dc, chosenFormat, nullptr);
+    const auto context = sWGLLib.CreateContextWithFallback(dc, false);
+    if (!context)
+        return nullptr;
 
     SurfaceCaps caps = SurfaceCaps::ForRGBA();
-    RefPtr<GLContextWGL> glContext = new GLContextWGL(CreateContextFlags::NONE, caps,
-                                                      false, dc, context);
-    if (!glContext->Init()) {
+    const RefPtr<GLContextWGL> gl = new GLContextWGL(CreateContextFlags::NONE,
+                                                     SurfaceCaps::ForRGBA(), false,
+                                                     dc, context);
+    cleanupDc.release();
+    gl->mIsDoubleBuffered = true;
+    if (!gl->Init())
         return nullptr;
-    }
 
-    glContext->SetIsDoubleBuffered(true);
-
-    return glContext.forget();
+    return gl;
 }
 
 already_AddRefed<GLContext>
 GLContextProviderWGL::CreateForCompositorWidget(CompositorWidget* aCompositorWidget, bool aForceAccelerated)
 {
     return CreateForWidget(aCompositorWidget->AsWindows()->GetHwnd(),
                            aCompositorWidget->GetCompositorOptions().UseWebRender(),
-                           aForceAccelerated);
+                           aForceAccelerated).forget();
 }
 
 already_AddRefed<GLContext>
 GLContextProviderWGL::CreateForWindow(nsIWidget* aWidget, bool aWebRender, bool aForceAccelerated)
 {
-    return CreateForWidget((HWND)aWidget->GetNativeData(NS_NATIVE_WINDOW), aWebRender, aForceAccelerated);
-}
-
-static already_AddRefed<GLContextWGL>
-CreatePBufferOffscreenContext(CreateContextFlags flags, const IntSize& aSize)
-{
-    WGLLibrary& wgl = sWGLLib;
-
-    const int pfAttribs[] = {
-        LOCAL_WGL_SUPPORT_OPENGL_ARB, LOCAL_GL_TRUE,
-        LOCAL_WGL_ACCELERATION_ARB, LOCAL_WGL_FULL_ACCELERATION_ARB,
-
-        LOCAL_WGL_DRAW_TO_PBUFFER_ARB, LOCAL_GL_TRUE,
-        LOCAL_WGL_DOUBLE_BUFFER_ARB, LOCAL_GL_FALSE,
-        LOCAL_WGL_STEREO_ARB, LOCAL_GL_FALSE,
-
-        0
-    };
-
-    // We only need one!
-    static const uint32_t kMaxFormats = 1024;
-    int formats[kMaxFormats];
-    uint32_t foundFormats;
-    HDC windowDC = wgl.GetWindowDC();
-    if (!wgl.mSymbols.fChoosePixelFormat(windowDC, pfAttribs, nullptr, kMaxFormats,
-                                         formats, &foundFormats)
-        || foundFormats == 0)
-    {
-        return nullptr;
-    }
-
-    // We don't care; just pick the first one.
-    int chosenFormat = formats[0];
-    if (!IsValidSizeForFormat(windowDC, chosenFormat, aSize))
-        return nullptr;
-
-    const int pbAttribs[] = { 0 };
-    HANDLE pbuffer = wgl.mSymbols.fCreatePbuffer(windowDC, chosenFormat, aSize.width,
-                                                 aSize.height, pbAttribs);
-    if (!pbuffer) {
-        return nullptr;
-    }
-
-    HDC pbdc = wgl.mSymbols.fGetPbufferDC(pbuffer);
-    NS_ASSERTION(pbdc, "expected a dc");
-
-    HGLRC context;
-    if (wgl.HasRobustness()) {
-        const int attribs[] = {
-            LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
-            LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB,
-            0
-        };
-        context = wgl.mSymbols.fCreateContextAttribsARB(pbdc, nullptr, attribs);
-    } else {
-        context = wgl.mSymbols.fCreateContext(pbdc);
-    }
-
-    if (!context) {
-        wgl.mSymbols.fDestroyPbuffer(pbuffer);
-        return nullptr;
-    }
-
-    SurfaceCaps dummyCaps = SurfaceCaps::Any();
-    RefPtr<GLContextWGL> glContext = new GLContextWGL(flags, dummyCaps, true, pbuffer,
-                                                      pbdc, context, chosenFormat);
-    return glContext.forget();
-}
-
-static already_AddRefed<GLContextWGL>
-CreateWindowOffscreenContext()
-{
-    HDC dc;
-    HWND win = sWGLLib.CreateDummyWindow(&dc);
-    if (!win) {
-        return nullptr;
-    }
-
-    HGLRC context = sWGLLib.mSymbols.fCreateContext(dc);
-    if (sWGLLib.HasRobustness()) {
-        int attribs[] = {
-            LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
-            LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB,
-            0
-        };
-
-        context = sWGLLib.mSymbols.fCreateContextAttribsARB(dc, nullptr, attribs);
-    } else {
-        context = sWGLLib.mSymbols.fCreateContext(dc);
-    }
-
-    if (!context) {
-        return nullptr;
-    }
-
-    SurfaceCaps caps = SurfaceCaps::ForRGBA();
-    RefPtr<GLContextWGL> glContext = new GLContextWGL(CreateContextFlags::NONE, caps,
-                                                      true, dc, context, win);
-    return glContext.forget();
+    return CreateForWidget((HWND)aWidget->GetNativeData(NS_NATIVE_WINDOW), aWebRender,
+                           aForceAccelerated).forget();
 }
 
 /*static*/ already_AddRefed<GLContext>
-GLContextProviderWGL::CreateHeadless(CreateContextFlags flags,
+GLContextProviderWGL::CreateHeadless(const CreateContextFlags flags,
                                      nsACString* const out_failureId)
 {
-    if (!sWGLLib.EnsureInitialized()) {
+    auto& wgl = sWGLLib;
+    if (!wgl.EnsureInitialized())
         return nullptr;
-    }
 
-    RefPtr<GLContextWGL> glContext;
+    int chosenFormat;
+    UINT foundFormats = 0;
 
-    // Always try to create a pbuffer context first, because we
-    // want the context isolation.
-    if (sWGLLib.mSymbols.fCreatePbuffer &&
-        sWGLLib.mSymbols.fChoosePixelFormat)
-    {
-        IntSize dummySize = IntSize(16, 16);
-        glContext = CreatePBufferOffscreenContext(flags, dummySize);
+    if (!foundFormats) {
+        const int kAttribs[] = {
+            LOCAL_WGL_DRAW_TO_PBUFFER_ARB, true,
+            LOCAL_WGL_SUPPORT_OPENGL_ARB, true,
+            LOCAL_WGL_ACCELERATION_ARB, LOCAL_WGL_FULL_ACCELERATION_ARB,
+            0
+        };
+        if (!wgl.mSymbols.fChoosePixelFormat(wgl.RootDc(), kAttribs, nullptr, 1,
+                                             &chosenFormat, &foundFormats))
+        {
+            foundFormats = 0;
+        }
+    }
+    if (!foundFormats) {
+        const int kAttribs[] = {
+            LOCAL_WGL_DRAW_TO_PBUFFER_ARB, true,
+            LOCAL_WGL_SUPPORT_OPENGL_ARB, true,
+            0
+        };
+        if (!wgl.mSymbols.fChoosePixelFormat(wgl.RootDc(), kAttribs, nullptr, 1,
+                                             &chosenFormat, &foundFormats))
+        {
+            foundFormats = 0;
+        }
     }
-
-    // If it failed, then create a window context and use a FBO.
-    if (!glContext) {
-        glContext = CreateWindowOffscreenContext();
-    }
+    if (!foundFormats)
+        return nullptr;
+    const int kPbufferAttribs[] = {0};
+    const auto pbuffer = wgl.mSymbols.fCreatePbuffer(wgl.RootDc(), chosenFormat, 1, 1,
+                                                     kPbufferAttribs);
+    if (!pbuffer)
+        return nullptr;
+    auto cleanupPbuffer = MakeScopeExit([&]() {
+        (void)wgl.mSymbols.fDestroyPbuffer(pbuffer);
+    });
 
-    if (!glContext ||
-        !glContext->Init())
-    {
+    const auto dc = wgl.mSymbols.fGetPbufferDC(pbuffer);
+    if (!dc)
+        return nullptr;
+    auto cleanupDc = MakeScopeExit([&]() {
+        (void)wgl.mSymbols.fReleasePbufferDC(pbuffer, dc);
+    });
+
+    const auto context = wgl.CreateContextWithFallback(dc, true);
+    if (!context)
         return nullptr;
-    }
 
-    RefPtr<GLContext> retGL = glContext.get();
-    return retGL.forget();
+    const bool isOffscreen = true;
+    const RefPtr<GLContextWGL> gl = new GLContextWGL(flags, SurfaceCaps::Any(),
+                                                     isOffscreen, pbuffer, dc, context,
+                                                     chosenFormat);
+    cleanupPbuffer.release();
+    cleanupDc.release();
+    if (!gl->Init())
+        return nullptr;
+
+    return RefPtr<GLContext>(gl.get()).forget();
 }
 
 /*static*/ already_AddRefed<GLContext>
 GLContextProviderWGL::CreateOffscreen(const IntSize& size,
                                       const SurfaceCaps& minCaps,
                                       CreateContextFlags flags,
                                       nsACString* const out_failureId)
 {
+    *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WGL_INIT");
+
     RefPtr<GLContext> gl = CreateHeadless(flags, out_failureId);
     if (!gl)
         return nullptr;
 
-    if (!gl->InitOffscreen(size, minCaps)) {
-        *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WGL_INIT");
+    if (!gl->InitOffscreen(size, minCaps))
         return nullptr;
-    }
 
     return gl.forget();
 }
 
 /*static*/ GLContext*
 GLContextProviderWGL::GetGlobalContext()
 {
     return nullptr;
--- a/gfx/gl/GLContextWGL.h
+++ b/gfx/gl/GLContextWGL.h
@@ -8,17 +8,17 @@
 #define GLCONTEXTWGL_H_
 
 #include "GLContext.h"
 #include "WGLLibrary.h"
 
 namespace mozilla {
 namespace gl {
 
-class GLContextWGL : public GLContext
+class GLContextWGL final : public GLContext
 {
 public:
     MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextWGL, override)
     // From Window: (possibly for offscreen!)
     GLContextWGL(CreateContextFlags flags,
                  const SurfaceCaps& caps,
                  bool isOffscreen,
                  HDC aDC,
@@ -33,46 +33,33 @@ public:
                  HDC aDC,
                  HGLRC aContext,
                  int aPixelFormat);
 
     ~GLContextWGL();
 
     virtual GLContextType GetContextType() const override { return GLContextType::WGL; }
 
-    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 IsCurrentImpl() const override;
-
-    void SetIsDoubleBuffered(bool aIsDB);
-
-    virtual bool IsDoubleBuffered() const override;
-
+    virtual bool IsDoubleBuffered() const override { return mIsDoubleBuffered; }
     virtual bool SwapBuffers() override;
-
     virtual bool SetupLookupFunction() override;
-
     virtual void GetWSIInfo(nsCString* const out) const override;
-
     HGLRC Context() { return mContext; }
 
 protected:
     friend class GLContextProviderWGL;
 
     HDC mDC;
     HGLRC mContext;
     HWND mWnd;
     HANDLE mPBuffer;
     int mPixelFormat;
+public:
     bool mIsDoubleBuffered;
 };
 
 }
 }
 
 #endif // GLCONTEXTWGL_H_
--- a/gfx/gl/WGLLibrary.h
+++ b/gfx/gl/WGLLibrary.h
@@ -1,57 +1,83 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GLContextTypes.h"
+#include "mozilla/UniquePtr.h"
 #include <windows.h>
 
 struct PRLibrary;
 
 namespace mozilla {
 namespace gl {
+/*
+struct ScopedDC
+{
+    const HDC mDC;
 
+    ScopedDC() = delete;
+    virtual ~ScopedDC() = 0;
+};
+
+struct WindowDC final : public ScopedDC
+{
+    const HWND mWindow;
+
+    WindowDC() = delete;
+    ~WindowDC();
+};
+
+struct PBufferDC final : public ScopedDC
+{
+    const HWND mWindow;
+
+    PBufferDC() = delete;
+    ~PBufferDC();
+};
+*/
 class WGLLibrary
 {
 public:
     WGLLibrary()
-      : mSymbols{nullptr}
-      , mInitialized(false)
-      , mOGLLibrary(nullptr)
-      , mHasRobustness(false)
-      , mWindow (0)
-      , mWindowDC(0)
-      , mWindowGLContext(0)
-      , mWindowPixelFormat(0)
+      : mSymbols{}
     { }
 
+    ~WGLLibrary() {
+        Reset();
+    }
+
+private:
+    void Reset();
+
 public:
     struct {
         HGLRC  (GLAPIENTRY * fCreateContext) (HDC);
         BOOL   (GLAPIENTRY * fDeleteContext) (HGLRC);
         BOOL   (GLAPIENTRY * fMakeCurrent) (HDC, HGLRC);
         PROC   (GLAPIENTRY * fGetProcAddress) (LPCSTR);
         HGLRC  (GLAPIENTRY * fGetCurrentContext) (void);
         HDC    (GLAPIENTRY * fGetCurrentDC) (void);
-        BOOL   (GLAPIENTRY * fShareLists) (HGLRC oldContext, HGLRC newContext);
+        //BOOL   (GLAPIENTRY * fShareLists) (HGLRC oldContext, HGLRC newContext);
         HANDLE (GLAPIENTRY * fCreatePbuffer) (HDC hDC, int iPixelFormat, int iWidth,
                                               int iHeight, const int* piAttribList);
         BOOL (GLAPIENTRY * fDestroyPbuffer) (HANDLE hPbuffer);
         HDC  (GLAPIENTRY * fGetPbufferDC) (HANDLE hPbuffer);
-        BOOL (GLAPIENTRY * fBindTexImage) (HANDLE hPbuffer, int iBuffer);
-        BOOL (GLAPIENTRY * fReleaseTexImage) (HANDLE hPbuffer, int iBuffer);
+        int  (GLAPIENTRY * fReleasePbufferDC) (HANDLE hPbuffer, HDC dc);
+        //BOOL (GLAPIENTRY * fBindTexImage) (HANDLE hPbuffer, int iBuffer);
+        //BOOL (GLAPIENTRY * fReleaseTexImage) (HANDLE hPbuffer, int iBuffer);
         BOOL (GLAPIENTRY * fChoosePixelFormat) (HDC hdc, const int* piAttribIList,
                                                 const FLOAT* pfAttribFList,
                                                 UINT nMaxFormats, int* piFormats,
                                                 UINT* nNumFormats);
-        BOOL (GLAPIENTRY * fGetPixelFormatAttribiv) (HDC hdc, int iPixelFormat,
-                                                     int iLayerPlane, UINT nAttributes,
-                                                     int* piAttributes, int* piValues);
+        //BOOL (GLAPIENTRY * fGetPixelFormatAttribiv) (HDC hdc, int iPixelFormat,
+        //                                             int iLayerPlane, UINT nAttributes,
+        //                                             int* piAttributes, int* piValues);
         const char* (GLAPIENTRY * fGetExtensionsStringARB) (HDC hdc);
         HGLRC (GLAPIENTRY * fCreateContextAttribsARB) (HDC hdc, HGLRC hShareContext,
                                                        const int* attribList);
         // WGL_NV_DX_interop:
         BOOL   (GLAPIENTRY * fDXSetResourceShareHandleNV) (void* dxObject,
                                                            HANDLE shareHandle);
         HANDLE (GLAPIENTRY * fDXOpenDeviceNV) (void* dxDevice);
         BOOL   (GLAPIENTRY * fDXCloseDeviceNV) (HANDLE hDevice);
@@ -62,36 +88,30 @@ public:
         BOOL   (GLAPIENTRY * fDXObjectAccessNV) (HANDLE hObject, GLenum access);
         BOOL   (GLAPIENTRY * fDXLockObjectsNV) (HANDLE hDevice, GLint count,
                                                 HANDLE* hObjects);
         BOOL   (GLAPIENTRY * fDXUnlockObjectsNV) (HANDLE hDevice, GLint count,
                                                   HANDLE* hObjects);
     } mSymbols;
 
     bool EnsureInitialized();
-    HWND CreateDummyWindow(HDC* aWindowDC = nullptr);
+    //UniquePtr<WindowDC> CreateDummyWindow();
+    HGLRC CreateContextWithFallback(HDC dc, bool tryRobustBuffers) const;
 
-    bool HasRobustness() const { return mHasRobustness; }
     bool HasDXInterop2() const { return bool(mSymbols.fDXOpenDeviceNV); }
     bool IsInitialized() const { return mInitialized; }
-    HWND GetWindow() const { return mWindow; }
-    HDC GetWindowDC() const {return mWindowDC; }
-    HGLRC GetWindowGLContext() const {return mWindowGLContext; }
-    int GetWindowPixelFormat() const { return mWindowPixelFormat; }
-    PRLibrary* GetOGLLibrary() { return mOGLLibrary; }
+    auto GetOGLLibrary() const { return mOGLLibrary; }
+    auto RootDc() const { return mRootDc; }
 
 private:
-    bool mInitialized;
+    bool mInitialized = false;
     PRLibrary* mOGLLibrary;
     bool mHasRobustness;
-
-    HWND mWindow;
-    HDC mWindowDC;
-    HGLRC mWindowGLContext;
-    int mWindowPixelFormat;
-
+    HWND mDummyWindow;
+    HDC mRootDc;
+    HGLRC mDummyGlrc;
 };
 
 // a global WGLLibrary instance
 extern WGLLibrary sWGLLib;
 
 } /* namespace gl */
 } /* namespace mozilla */