Bug 632867 - Mesa versions up to 7.10 cause a BadLength error during the first GLX call when the server GLX version < 1.3. - r=karlt, a=hardblocker
authorBenoit Jacob <bjacob@mozilla.com>
Fri, 11 Feb 2011 18:11:30 -0500
changeset 62486 be64c2d2b30690f1333ca7afc009035b6d6dc9cf
parent 62485 65ea4af6833a65bcce2526b441ae85e66edfa8f4
child 62487 0275087f8fb9a7cbf56867bed9c4df5b4b85bae4
push idunknown
push userunknown
push dateunknown
reviewerskarlt, hardblocker
bugs632867
milestone2.0b12pre
Bug 632867 - Mesa versions up to 7.10 cause a BadLength error during the first GLX call when the server GLX version < 1.3. - r=karlt, a=hardblocker
gfx/src/X11Util.cpp
gfx/src/X11Util.h
gfx/thebes/GLContextProviderGLX.cpp
--- a/gfx/src/X11Util.cpp
+++ b/gfx/src/X11Util.cpp
@@ -67,17 +67,22 @@ ScopedXErrorHandler::~ScopedXErrorHandle
     sXErrorPtr = mOldXErrorPtr;
     XSetErrorHandler(mOldErrorHandler);
 }
 
 bool
 ScopedXErrorHandler::SyncAndGetError(Display *dpy, XErrorEvent *ev)
 {
     XSync(dpy, False);
+    return GetError(ev);
+}
+
+bool
+ScopedXErrorHandler::GetError(XErrorEvent *ev)
+{
     bool retval = mXError.mError.error_code != 0;
     if (ev)
         *ev = mXError.mError;
     mXError = ErrorEvent(); // reset
     return retval;
 }
 
-
 } // namespace mozilla
--- a/gfx/src/X11Util.h
+++ b/gfx/src/X11Util.h
@@ -160,14 +160,20 @@ public:
 
     /** \returns true if a X error occurred since the last time this method was called on this ScopedXErrorHandler object,
      *           or since the creation of this ScopedXErrorHandler object if this method was never called on it.
      *
      * \param ev this optional parameter, if set, will be filled with the XErrorEvent object. If multiple errors occurred,
      *           the first one will be returned.
      */
     bool SyncAndGetError(Display *dpy, XErrorEvent *ev = nsnull);
+
+    /** Like SyncAndGetError, but does not sync. Faster, but only reliably catches errors in synchronous calls.
+     *
+     * \param ev this optional parameter, if set, will be filled with the XErrorEvent object. If multiple errors occurred,
+     *           the first one will be returned.
+     */
+    bool GetError(XErrorEvent *ev = nsnull);
 };
 
-
 } // namespace mozilla
 
 #endif  // mozilla_X11Util_h
--- a/gfx/thebes/GLContextProviderGLX.cpp
+++ b/gfx/thebes/GLContextProviderGLX.cpp
@@ -159,30 +159,52 @@ GLXLibrary::EnsureInitialized()
 
     if (!LibrarySymbolLoader::LoadSymbols(mOGLLibrary, &symbols[0])) {
         NS_WARNING("Couldn't find required entry point in OpenGL shared library");
         return PR_FALSE;
     }
 
     Display *display = DefaultXDisplay();
     int screen = DefaultScreen(display);
-    if (!xQueryVersion(display, &gGLXMajorVersion, &gGLXMinorVersion)) {
-        gGLXMajorVersion = 0;
-        gGLXMinorVersion = 0;
-        return PR_FALSE;
-    }
+    const char *vendor;
+    const char *serverVersionStr;
+    const char *extensionsStr;
+
+    // this scope is covered by a ScopedXErrorHandler to catch X errors in GLX calls,
+    // see bug 632867 comment 3: Mesa versions up to 7.10 cause a BadLength error during the first GLX call
+    // when the server GLX version < 1.3.
+    {
+        ScopedXErrorHandler xErrorHandler;
+
+        if (!xQueryVersion(display, &gGLXMajorVersion, &gGLXMinorVersion)) {
+            gGLXMajorVersion = 0;
+            gGLXMinorVersion = 0;
+            return PR_FALSE;
+        }
 
-    const char *vendor = xQueryServerString(display, screen, GLX_VENDOR);
-    const char *serverVersionStr = xQueryServerString(display, screen, GLX_VERSION);
+        vendor = xQueryServerString(display, screen, GLX_VENDOR);
+        serverVersionStr = xQueryServerString(display, screen, GLX_VERSION);
 
-    if (!GLXVersionCheck(1, 1))
-        // Not possible to query for extensions.
-        return PR_FALSE;
+        if (strcmp(vendor, "NVIDIA Corporation") &&
+            !PR_GetEnv("MOZ_GLX_IGNORE_BLACKLIST"))
+        {
+          printf("[GLX] your GL driver is currently blocked. If you would like to bypass this, "
+                  "define the MOZ_GLX_IGNORE_BLACKLIST environment variable.\n");
+          return nsnull;
+        }
 
-    const char *extensionsStr = xQueryExtensionsString(display, screen);
+        if (!GLXVersionCheck(1, 1))
+            // Not possible to query for extensions.
+            return PR_FALSE;
+
+        extensionsStr = xQueryExtensionsString(display, screen);
+
+        if (xErrorHandler.GetError())
+          return PR_FALSE;
+    }
 
     LibrarySymbolLoader::SymLoadStruct *sym13;
     if (!GLXVersionCheck(1, 3)) {
         // Even if we don't have 1.3, we might have equivalent extensions
         // (as on the Intel X server).
         if (!HasExtension(extensionsStr, "GLX_SGIX_fbconfig")) {
             return PR_FALSE;
         }
@@ -229,25 +251,16 @@ public:
                     Display *display,
                     GLXDrawable drawable,
                     GLXFBConfig cfg,
                     XVisualInfo *vinfo,
                     GLContextGLX *shareContext,
                     PRBool deleteDrawable,
                     gfxXlibSurface *pixmap = nsnull)
     {
-        const char *glxVendorString = sGLXLibrary.xQueryServerString(display, DefaultScreen(display), GLX_VENDOR);
-        if (strcmp(glxVendorString, "NVIDIA Corporation") &&
-            !PR_GetEnv("MOZ_GLX_IGNORE_BLACKLIST"))
-        {
-          printf("[GLX] your GL driver is currently blocked. If you would like to bypass this, "
-                 "define the MOZ_GLX_IGNORE_BLACKLIST environment variable.\n");
-          return nsnull;
-        }
-
         int db = 0, err;
         err = sGLXLibrary.xGetFBConfigAttrib(display, cfg,
                                              GLX_DOUBLEBUFFER, &db);
         if (GLX_BAD_ATTRIBUTE != err) {
 #ifdef DEBUG
             printf("[GLX] FBConfig is %sdouble-buffered\n", db ? "" : "not ");
 #endif
         }