Bug 671259 - Disable OpenGL layers on linux when we don't have texture_from_pixmap. r=bjacob
authorMatt Woodrow <mwoodrow@mozilla.com>
Fri, 05 Aug 2011 13:13:25 +1200
changeset 74270 83fe19966844facbc1efbf441a86402b334214c8
parent 74269 c0adebd5c58d4ea18de1c9031345a56271ebef23
child 74271 1edc576938dccbe441132bddf8afca8981fe86a6
push idunknown
push userunknown
push dateunknown
reviewersbjacob
bugs671259
milestone8.0a1
Bug 671259 - Disable OpenGL layers on linux when we don't have texture_from_pixmap. r=bjacob
toolkit/xre/glxtest.cpp
widget/src/xpwidgets/GfxInfoX11.cpp
widget/src/xpwidgets/GfxInfoX11.h
--- a/toolkit/xre/glxtest.cpp
+++ b/toolkit/xre/glxtest.cpp
@@ -133,25 +133,29 @@ static void glxtest()
   PFNGLXDESTROYPIXMAP glXDestroyPixmap = cast<PFNGLXDESTROYPIXMAP>(dlsym(libgl, "glXDestroyPixmap"));
 
   typedef void (* PFNGLXDESTROYCONTEXT) (Display*, GLXContext);
   PFNGLXDESTROYCONTEXT glXDestroyContext = cast<PFNGLXDESTROYCONTEXT>(dlsym(libgl, "glXDestroyContext"));
 
   typedef GLubyte* (* PFNGLGETSTRING) (GLenum);
   PFNGLGETSTRING glGetString = cast<PFNGLGETSTRING>(dlsym(libgl, "glGetString"));
 
+  typedef void* (* PFNGLXGETPROCADDRESS) (const char *);
+  PFNGLXGETPROCADDRESS glXGetProcAddress = cast<PFNGLXGETPROCADDRESS>(dlsym(libgl, "glXGetProcAddress"));
+
   if (!glXQueryExtension ||
       !glXChooseFBConfig ||
       !glXGetVisualFromFBConfig ||
       !glXCreatePixmap ||
       !glXCreateNewContext ||
       !glXMakeCurrent ||
       !glXDestroyPixmap ||
       !glXDestroyContext ||
-      !glGetString)
+      !glGetString ||
+      !glXGetProcAddress)
   {
     fatal_error("Unable to find required symbols in libGL.so.1");
   }
   ///// Open a connection to the X server /////
   Display *dpy = XOpenDisplay(NULL);
   if (!dpy)
     fatal_error("Unable to open a connection to the X server");
   
@@ -178,31 +182,35 @@ static void glxtest()
   ///// Get a Pixmap and a GLXPixmap /////
   Pixmap pixmap = XCreatePixmap(dpy, RootWindow(dpy, vInfo->screen), 4, 4, 32);
   GLXPixmap glxpixmap = glXCreatePixmap(dpy, fbConfigs[0], pixmap, NULL);
 
   ///// Get a GL context and make it current //////
   GLXContext context = glXCreateNewContext(dpy, fbConfigs[0], GLX_RGBA_TYPE, NULL, True);
   glXMakeCurrent(dpy, glxpixmap, context);
 
+  ///// Look for this symbol to determine texture_from_pixmap support /////
+  void* glXBindTexImageEXT = glXGetProcAddress("glXBindTexImageEXT"); 
+
   ///// Get GL vendor/renderer/versions strings /////
   enum { bufsize = 1024 };
   char buf[bufsize];
   const GLubyte *vendorString = glGetString(GL_VENDOR);
   const GLubyte *rendererString = glGetString(GL_RENDERER);
   const GLubyte *versionString = glGetString(GL_VERSION);
   
   if (!vendorString || !rendererString || !versionString)
     fatal_error("glGetString returned null");
 
   int length = snprintf(buf, bufsize,
-                        "VENDOR\n%s\nRENDERER\n%s\nVERSION\n%s\n",
+                        "VENDOR\n%s\nRENDERER\n%s\nVERSION\n%s\nTFP\n%s\n",
                         vendorString,
                         rendererString,
-                        versionString);
+                        versionString,
+                        glXBindTexImageEXT ? "TRUE" : "FALSE");
   if (length >= bufsize)
     fatal_error("GL strings length too large for buffer size");
 
   ///// Check that no X error happened /////
   // In case of X errors, our X error handler will exit() now.
   // We really want to make sure that the system is able to create a GL context without generating X errors,
   // as these would crash the application.
   XSync(dpy, False);
--- a/widget/src/xpwidgets/GfxInfoX11.cpp
+++ b/widget/src/xpwidgets/GfxInfoX11.cpp
@@ -62,16 +62,17 @@ nsresult
 GfxInfo::Init()
 {
     mMajorVersion = 0;
     mMinorVersion = 0;
     mRevisionVersion = 0;
     mIsMesa = false;
     mIsNVIDIA = false;
     mIsFGLRX = false;
+    mHasTextureFromPixmap = false;
     return GfxInfoBase::Init();
 }
 
 void
 GfxInfo::GetData()
 {
     // to understand this function, see bug 639842. We retrieve the OpenGL driver information in a
     // separate process to protect against bad drivers.
@@ -114,16 +115,17 @@ GfxInfo::GetData()
     bool exited_with_error_code = !waiting_for_glxtest_process_failed &&
                                   WIFEXITED(glxtest_status) && 
                                   WEXITSTATUS(glxtest_status) != EXIT_SUCCESS;
     bool received_signal = !waiting_for_glxtest_process_failed &&
                            WIFSIGNALED(glxtest_status);
 
     bool error = waiting_for_glxtest_process_failed || exited_with_error_code || received_signal;
 
+    nsCString textureFromPixmap; 
     nsCString *stringToFill = nsnull;
     char *bufptr = buf;
     if (!error) {
         while(true) {
             char *line = NS_strtok("\n", &bufptr);
             if (!line)
                 break;
             if (stringToFill) {
@@ -131,19 +133,24 @@ GfxInfo::GetData()
                 stringToFill = nsnull;
             }
             else if(!strcmp(line, "VENDOR"))
                 stringToFill = &mVendor;
             else if(!strcmp(line, "RENDERER"))
                 stringToFill = &mRenderer;
             else if(!strcmp(line, "VERSION"))
                 stringToFill = &mVersion;
+            else if(!strcmp(line, "TFP"))
+                stringToFill = &textureFromPixmap;
         }
     }
 
+    if (!strcmp(textureFromPixmap.get(), "TRUE"))
+        mHasTextureFromPixmap = true;
+
     const char *spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_GL_VENDOR");
     if (spoofedVendor)
         mVendor.Assign(spoofedVendor);
     const char *spoofedRenderer = PR_GetEnv("MOZ_GFX_SPOOF_GL_RENDERER");
     if (spoofedRenderer)
         mRenderer.Assign(spoofedRenderer);
     const char *spoofedVersion = PR_GetEnv("MOZ_GFX_SPOOF_GL_VERSION");
     if (spoofedVersion)
@@ -176,16 +183,18 @@ GfxInfo::GetData()
     mAdapterDescription.AppendLiteral(" -- ");
     mAdapterDescription.Append(mRenderer);
 
     nsCAutoString note;
     note.Append("OpenGL: ");
     note.Append(mAdapterDescription);
     note.Append(" -- ");
     note.Append(mVersion);
+    if (mHasTextureFromPixmap)
+        note.Append(" -- texture_from_pixmap");
     note.Append("\n");
 #ifdef MOZ_CRASHREPORTER
     CrashReporter::AppendAppNotesToCrashReport(note);
 #endif
 
     // determine driver type (vendor) and where in the version string
     // the actual driver version numbers should be expected to be found (whereToReadVersionNumbers)
     const char *whereToReadVersionNumbers = nsnull;
@@ -244,16 +253,23 @@ GfxInfo::GetFeatureStatusImpl(PRInt32 aF
     *aStatus = nsIGfxInfo::FEATURE_NO_INFO;
     aSuggestedDriverVersion.SetIsVoid(PR_TRUE);
 
 #ifdef MOZ_PLATFORM_MAEMO
     // on Maemo, the glxtest probe doesn't build, and we don't really need GfxInfo anyway
     return NS_OK;
 #endif
 
+    // Disable OpenGL layers when we don't have texture_from_pixmap because it regresses performance. 
+    if (aFeature == nsIGfxInfo::FEATURE_OPENGL_LAYERS && !mHasTextureFromPixmap) {
+        *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
+        aSuggestedDriverVersion.AssignLiteral("<Anything with EXT_texture_from_pixmap support>");
+        return NS_OK;
+    }
+
     // whitelist the linux test slaves' current configuration.
     // this is necessary as they're still using the slightly outdated 190.42 driver.
     // this isn't a huge risk, as at least this is the exact setting in which we do continuous testing,
     // and this only affects GeForce 9400 cards on linux on this precise driver version, which is very few users.
     // We do the same thing on Windows XP, see in widget/src/windows/GfxInfo.cpp
     if (mIsNVIDIA &&
         !strcmp(mRenderer.get(), "GeForce 9400/PCI/SSE2") &&
         !strcmp(mVersion.get(), "3.2.0 NVIDIA 190.42"))
--- a/widget/src/xpwidgets/GfxInfoX11.h
+++ b/widget/src/xpwidgets/GfxInfoX11.h
@@ -74,16 +74,17 @@ protected:
   virtual nsresult GetFeatureStatusImpl(PRInt32 aFeature, PRInt32 *aStatus, nsAString & aSuggestedDriverVersion, GfxDriverInfo* aDriverInfo = nsnull);
 
 private:
   nsCString mVendor;
   nsCString mRenderer;
   nsCString mVersion;
   nsCString mAdapterDescription;
   bool mIsMesa, mIsNVIDIA, mIsFGLRX;
+  bool mHasTextureFromPixmap;
   int mMajorVersion, mMinorVersion, mRevisionVersion;
 
   void AddCrashReportAnnotations();
   void GetData();
 };
 
 } // namespace widget
 } // namespace mozilla