Bug 1347731 - Simplify WGL initialization code. - r=daoshengmu
authorJeff Gilbert <jgilbert@mozilla.com>
Tue, 02 Jan 2018 18:30:15 -0800
changeset 397924 ba269efce3cedf4a733276b913135febb5be3228
parent 397923 6500c02faddf82983d563a6d1fd9fe47b281884f
child 397925 2e3bcb14cc4e4aa4c1339544dba1968bf0dba051
push id33194
push usertoros@mozilla.com
push dateFri, 05 Jan 2018 09:58:30 +0000
treeherdermozilla-central@81362f7306fe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdaoshengmu
bugs1347731
milestone59.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 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 */