Bug 70348: implement ARB_robustness with WGL r=bjacob
authorDoug Sherk <dsherk@mozilla.com>
Fri, 02 Dec 2011 23:50:11 -0800
changeset 81223 9920eee7dba9
parent 81222 8555cf2ffac8
child 81224 66f61be58aa3
push id21564
push usermak77@bonardo.net
push date2011-12-03 11:10 +0000
treeherdermozilla-central@a68c96c1d8e0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbjacob
bugs70348
milestone11.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 70348: implement ARB_robustness with WGL r=bjacob WGL has its own ARB_robustness implementation which we support with this patch. I was able to confirm that it was correctly being activated and was polling status correctly (i.e. the framework is running), but WGL itself doesn't actually seem to stop the DoS correctly when a robust context is created.
gfx/gl/GLContextProviderWGL.cpp
gfx/gl/WGLLibrary.h
--- a/gfx/gl/GLContextProviderWGL.cpp
+++ b/gfx/gl/GLContextProviderWGL.cpp
@@ -117,16 +117,23 @@ CreateDummyWindow(HDC *aWindowDC = nsnul
 
     if (aWindowDC) {
         *aWindowDC = dc;
     }
 
     return win;
 }
 
+static inline bool
+HasExtension(const char* aExtensions, const char* aRequiredExtension)
+{
+    return GLContext::ListHasExtension(
+        reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension);
+}
+
 bool
 WGLLibrary::EnsureInitialized()
 {
     if (mInitialized)
         return true;
 
     mozilla::ScopedGfxFeatureReporter reporter("WGL");
 
@@ -200,19 +207,57 @@ WGLLibrary::EnsureInitialized()
 
     if (!LibrarySymbolLoader::LoadSymbols(mOGLLibrary, &pixFmtSymbols[0],
          (LibrarySymbolLoader::PlatformLookupFunction)fGetProcAddress))
     {
         // this isn't an error, just means that we don't have the pixel format extension
         fChoosePixelFormat = nsnull;
     }
 
+    LibrarySymbolLoader::SymLoadStruct extensionsSymbols[] = {
+        { (PRFuncPtr *) &fGetExtensionsString, { "wglGetExtensionsStringARB", NULL} },
+        { NULL, { NULL } }
+    };
+
+    LibrarySymbolLoader::SymLoadStruct robustnessSymbols[] = {
+        { (PRFuncPtr *) &fCreateContextAttribs, { "wglCreateContextAttribsARB", NULL} },
+        { NULL, { NULL } }
+    };
+
+    if (LibrarySymbolLoader::LoadSymbols(mOGLLibrary, &extensionsSymbols[0],
+        (LibrarySymbolLoader::PlatformLookupFunction)fGetProcAddress)) {
+        const char *wglExts = fGetExtensionsString(gSharedWindowDC);
+        if (wglExts && HasExtension(wglExts, "WGL_ARB_create_context")) {
+            LibrarySymbolLoader::LoadSymbols(mOGLLibrary, &robustnessSymbols[0],
+            (LibrarySymbolLoader::PlatformLookupFunction)fGetProcAddress);
+            if (HasExtension(wglExts, "WGL_ARB_create_context_robustness")) {
+                mHasRobustness = true;
+            }
+        }
+    }
+
     // reset back to the previous context, just in case
     fMakeCurrent(curDC, curCtx);
 
+    if (mHasRobustness) {
+        fDeleteContext(gSharedWindowGLContext);
+
+        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,
+            NULL
+        };
+
+        gSharedWindowGLContext = fCreateContextAttribs(gSharedWindowDC, NULL, attribs);
+        if (!gSharedWindowGLContext) {
+            mHasRobustness = false;
+            gSharedWindowGLContext = fCreateContext(gSharedWindowDC);
+        }
+    }
+
     mInitialized = true;
 
     // Call this to create the global GLContext instance,
     // and to check for errors.  Note that this must happen /after/
     // setting mInitialized to TRUE, or an infinite loop results.
     if (GLContextProviderWGL::GetGlobalContext() == nsnull) {
         mInitialized = false;
         return false;
@@ -304,17 +349,17 @@ public:
     }
 
     virtual bool IsDoubleBuffered() {
         return mIsDoubleBuffered;
     }
 
     bool SupportsRobustness()
     {
-        return false;
+        return sWGLLibrary.HasRobustness();
     }
 
     virtual bool SwapBuffers() {
         if (!mIsDoubleBuffered)
             return false;
         return ::SwapBuffers(mDC);
     }
 
@@ -497,26 +542,45 @@ GLContextProviderWGL::CreateForWindow(ns
        * We need to make sure we call SetPixelFormat -after- calling 
        * EnsureInitialized, otherwise it can load/unload the dll and 
        * wglCreateContext will fail.
        */
 
     HDC dc = (HDC)aWidget->GetNativeData(NS_NATIVE_GRAPHIC);
 
     SetPixelFormat(dc, gSharedWindowPixelFormat, NULL);
-    HGLRC context = sWGLLibrary.fCreateContext(dc);
-    if (!context) {
-        return nsnull;
+    HGLRC context;
+
+    GLContextWGL *shareContext = GetGlobalContextWGL();
+
+    if (sWGLLibrary.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,
+            NULL
+        };
+
+        context = sWGLLibrary.fCreateContextAttribs(dc,
+                                                    shareContext ? shareContext->Context() : nsnull,
+                                                    attribs);
+        if (!context && shareContext) {
+            context = sWGLLibrary.fCreateContextAttribs(dc, nsnull, attribs);
+            if (context) {
+                shareContext = nsnull;
+            }
+        } else {
+            context = sWGLLibrary.fCreateContext(dc);
+            if (context && shareContext && !sWGLLibrary.fShareLists(shareContext->Context(), context)) {
+                shareContext = nsnull;
+            }
+        }
     }
 
-    GLContextWGL *shareContext = GetGlobalContextWGL();
-    if (shareContext &&
-        !sWGLLibrary.fShareLists(shareContext->Context(), context))
-    {
-        shareContext = nsnull;
+    if (!context) {
+        return nsnull;
     }
 
     nsRefPtr<GLContextWGL> glContext = new GLContextWGL(ContextFormat(ContextFormat::BasicRGB24),
                                                         shareContext, dc, context);
     if (!glContext->Init()) {
         return nsnull;
     }
 
@@ -592,17 +656,29 @@ CreatePBufferOffscreenContext(const gfxI
                                                 pbattrs.Elements());
     if (!pbuffer) {
         return nsnull;
     }
 
     HDC pbdc = sWGLLibrary.fGetPbufferDC(pbuffer);
     NS_ASSERTION(pbdc, "expected a dc");
 
-    HGLRC context = sWGLLibrary.fCreateContext(pbdc);
+    HGLRC context;
+    if (sWGLLibrary.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,
+            NULL
+        };
+
+        context = sWGLLibrary.fCreateContextAttribs(pbdc, nsnull, attribs);
+    } else {
+        context = sWGLLibrary.fCreateContext(pbdc);
+    }
+
     if (!context) {
         sWGLLibrary.fDestroyPbuffer(pbuffer);
         return false;
     }
 
     nsRefPtr<GLContextWGL> glContext = new GLContextWGL(aFormat,
                                                         nsnull,
                                                         pbuffer,
@@ -624,25 +700,38 @@ CreateWindowOffscreenContext(const Conte
     
     HDC dc;
     HWND win = CreateDummyWindow(&dc);
     if (!win) {
         return nsnull;
     }
     
     HGLRC context = sWGLLibrary.fCreateContext(dc);
-    if (!context) {
-        return nsnull;
+    if (sWGLLibrary.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,
+            NULL
+        };
+
+        context = sWGLLibrary.fCreateContextAttribs(dc, shareContext->Context(), attribs);
+    } else {
+        context = sWGLLibrary.fCreateContext(dc);
+        if (context && shareContext &&
+            !sWGLLibrary.fShareLists(shareContext->Context(), context))
+        {
+            NS_WARNING("wglShareLists failed!");
+
+            sWGLLibrary.fDeleteContext(context);
+            DestroyWindow(win);
+            return nsnull;
+        }
     }
 
-    if (!sWGLLibrary.fShareLists(shareContext->Context(), context)) {
-        NS_WARNING("wglShareLists failed!");
-
-        sWGLLibrary.fDeleteContext(context);
-        DestroyWindow(win);
+    if (!context) {
         return nsnull;
     }
 
     nsRefPtr<GLContextWGL> glContext = new GLContextWGL(aFormat, shareContext,
                                                         dc, context, win, true);
 
     return glContext.forget();
 }
--- a/gfx/gl/WGLLibrary.h
+++ b/gfx/gl/WGLLibrary.h
@@ -37,17 +37,18 @@
 #include "GLContext.h"
 
 namespace mozilla {
 namespace gl {
 
 class WGLLibrary
 {
 public:
-    WGLLibrary() : mInitialized(false), mOGLLibrary(nsnull) {}
+    WGLLibrary() : mInitialized(false), mOGLLibrary(nsnull),
+    mHasRobustness(false) {}
 
     typedef HGLRC (GLAPIENTRY * PFNWGLCREATECONTEXTPROC) (HDC);
     PFNWGLCREATECONTEXTPROC fCreateContext;
     typedef BOOL (GLAPIENTRY * PFNWGLDELETECONTEXTPROC) (HGLRC);
     PFNWGLDELETECONTEXTPROC fDeleteContext;
     typedef BOOL (GLAPIENTRY * PFNWGLMAKECURRENTPROC) (HDC, HGLRC);
     PFNWGLMAKECURRENTPROC fMakeCurrent;
     typedef PROC (GLAPIENTRY * PFNWGLGETPROCADDRESSPROC) (LPCSTR);
@@ -71,21 +72,30 @@ public:
     typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEPROC) (HANDLE hPbuffer, int iBuffer);
     PFNWGLRELEASETEXIMAGEPROC fReleaseTexImage;
 
     typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATPROC) (HDC hdc, const int* piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
     PFNWGLCHOOSEPIXELFORMATPROC fChoosePixelFormat;
     typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int *piValues);
     PFNWGLGETPIXELFORMATATTRIBIVPROC fGetPixelFormatAttribiv;
 
+    typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGPROC) (HDC hdc);
+    PFNWGLGETEXTENSIONSSTRINGPROC fGetExtensionsString;
+
+    typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSPROC) (HDC hdc, HGLRC hShareContext, const int *attribList);
+    PFNWGLCREATECONTEXTATTRIBSPROC fCreateContextAttribs;
+
     bool EnsureInitialized();
 
+    bool HasRobustness() const { return mHasRobustness; }
+
 private:
     bool mInitialized;
     PRLibrary *mOGLLibrary;
+    bool mHasRobustness;
 };
 
 // a global WGLLibrary instance
 extern WGLLibrary sWGLLibrary;
 
 } /* namespace gl */
 } /* namespace mozilla */