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 id18738
push userbjacob@mozilla.com
push dateSat, 12 Feb 2011 20:41:12 +0000
treeherdermozilla-central@0275087f8fb9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt, hardblocker
bugs632867
milestone2.0b12pre
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 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
         }