Bug 668004 - generalized GPU blocklist to all platforms - r=bjacob
authorDoug Sherk <dsherk@mozilla.com>
Thu, 03 Nov 2011 10:50:40 -0400
changeset 80324 1f1d6394148c1c8b839dac78bdd429f48354af18
parent 80323 ef9b57cf2a7c444d4f49d075d52edf5a65639cdb
child 80325 b7a96e8bec7e489f407233ea71af2390bbf790e8
push idunknown
push userunknown
push dateunknown
reviewersbjacob
bugs668004
milestone10.0a1
Bug 668004 - generalized GPU blocklist to all platforms - r=bjacob Refactored Windows-specific code for blocklisting GPUs to GfxInfoBase so that it could be re-used by every platform. Also enabled all downloaded blocklist code on X11 (Linux) and Cocoa (Mac) but not yet on Android.
gfx/thebes/gfxPlatformMac.h
widget/src/android/GfxInfo.cpp
widget/src/android/GfxInfo.h
widget/src/cocoa/GfxInfo.h
widget/src/cocoa/GfxInfo.mm
widget/src/windows/GfxInfo.cpp
widget/src/windows/GfxInfo.h
widget/src/xpwidgets/GfxDriverInfo.cpp
widget/src/xpwidgets/GfxDriverInfo.h
widget/src/xpwidgets/GfxInfoBase.cpp
widget/src/xpwidgets/GfxInfoBase.h
widget/src/xpwidgets/GfxInfoX11.cpp
widget/src/xpwidgets/GfxInfoX11.h
--- a/gfx/thebes/gfxPlatformMac.h
+++ b/gfx/thebes/gfxPlatformMac.h
@@ -40,16 +40,17 @@
 #define GFX_PLATFORM_MAC_H
 
 #include "nsTArray.h"
 #include "gfxPlatform.h"
 
 #define MAC_OS_X_VERSION_10_4_HEX 0x00001040
 #define MAC_OS_X_VERSION_10_5_HEX 0x00001050
 #define MAC_OS_X_VERSION_10_6_HEX 0x00001060
+#define MAC_OS_X_VERSION_10_7_HEX 0x00001070
 
 #define MAC_OS_X_MAJOR_VERSION_MASK 0xFFFFFFF0U
 
 class gfxTextRun;
 
 class THEBES_API gfxPlatformMac : public gfxPlatform {
 public:
     gfxPlatformMac();
--- a/widget/src/android/GfxInfo.cpp
+++ b/widget/src/android/GfxInfo.cpp
@@ -34,16 +34,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "GfxInfo.h"
 #include "nsUnicharUtils.h"
 #include "mozilla/FunctionTimer.h"
 #include "prenv.h"
 #include "prprf.h"
 #include "EGLUtils.h"
+#include "nsHashKeys.h"
 
 #include "AndroidBridge.h"
 
 #if defined(MOZ_CRASHREPORTER)
 #include "nsExceptionHandler.h"
 #include "nsICrashReporter.h"
 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
 #endif
@@ -182,31 +183,43 @@ GfxInfo::GetAdapterDriverDate2(nsAString
 {
   return NS_ERROR_FAILURE;
 }
 
 /* readonly attribute unsigned long adapterVendorID; */
 NS_IMETHODIMP
 GfxInfo::GetAdapterVendorID(PRUint32 *aAdapterVendorID)
 {
+  nsAutoString str;
+  if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "HARDWARE", str)) {
+    *aAdapterVendorID = HashString(str);
+    return NS_OK;
+  }
+
   *aAdapterVendorID = 0;
   return NS_OK;
 }
 
 /* readonly attribute unsigned long adapterVendorID2; */
 NS_IMETHODIMP
 GfxInfo::GetAdapterVendorID2(PRUint32 *aAdapterVendorID)
 {
   return NS_ERROR_FAILURE;
 }
 
 /* readonly attribute unsigned long adapterDeviceID; */
 NS_IMETHODIMP
 GfxInfo::GetAdapterDeviceID(PRUint32 *aAdapterDeviceID)
 {
+  nsAutoString str;
+  if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "MODEL", str)) {
+    *aAdapterDeviceID = HashString(str);
+    return NS_OK;
+  }
+
   *aAdapterDeviceID = 0;
   return NS_OK;
 }
 
 /* readonly attribute unsigned long adapterDeviceID2; */
 NS_IMETHODIMP
 GfxInfo::GetAdapterDeviceID2(PRUint32 *aAdapterDeviceID)
 {
@@ -249,30 +262,45 @@ GfxInfo::AddOpenGLCrashReportAnnotations
   note.Append("\n");
   note.AppendPrintf("AdapterDescription: '%s'.", NS_ConvertUTF16toUTF8(adapterDescriptionString).get());
   note.Append("\n");
 
   CrashReporter::AppendAppNotesToCrashReport(note);
 #endif
 }
 
+static GfxDriverInfo gDriverInfo[] = {
+  GfxDriverInfo()
+};
+
+const GfxDriverInfo*
+GfxInfo::GetGfxDriverInfo()
+{
+  return &gDriverInfo[0];
+}
+
 nsresult
-GfxInfo::GetFeatureStatusImpl(PRInt32 aFeature, PRInt32 *aStatus, nsAString & aSuggestedDriverVersion,
-                              GfxDriverInfo* aDriverInfo /* = nsnull */)
+GfxInfo::GetFeatureStatusImpl(PRInt32 aFeature, 
+                              PRInt32 *aStatus, 
+                              nsAString & aSuggestedDriverVersion,
+                              GfxDriverInfo* aDriverInfo /* = nsnull */, 
+                              OperatingSystem* aOS /* = nsnull */)
 {
   PRInt32 status = nsIGfxInfo::FEATURE_NO_INFO;
 
   aSuggestedDriverVersion.SetIsVoid(true);
 
   // For now, we don't implement the downloaded blacklist.
   if (aDriverInfo) {
     *aStatus = status;
     return NS_OK;
   }
 
+  OperatingSystem os = DRIVER_OS_ANDROID;
+
   if (aFeature == FEATURE_OPENGL_LAYERS) {
     if (!mSetCrashReportAnnotations) {
       AddOpenGLCrashReportAnnotations();
       mSetCrashReportAnnotations = true;
     }
 
     /* XXX: Use this code when we're ready to whitelist devices. */
     // nsAutoString str;
@@ -282,10 +310,13 @@ GfxInfo::GetFeatureStatusImpl(PRInt32 aF
     //     status = FEATURE_BLOCKED_DEVICE;
     //   }
     // }
 
     status = FEATURE_BLOCKED_DEVICE;
   }
 
   *aStatus = status;
-  return NS_OK;
+  if (aOS)
+    *aOS = os;
+
+  return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, &os);
 }
--- a/widget/src/android/GfxInfo.h
+++ b/widget/src/android/GfxInfo.h
@@ -75,17 +75,22 @@ public:
   using GfxInfoBase::GetFeatureStatus;
   using GfxInfoBase::GetFeatureSuggestedDriverVersion;
   using GfxInfoBase::GetWebGLParameter;
 
   virtual nsresult Init();
 
 protected:
 
-  virtual nsresult GetFeatureStatusImpl(PRInt32 aFeature, PRInt32 *aStatus, nsAString & aSuggestedDriverVersion, GfxDriverInfo* aDriverInfo = nsnull);
+  virtual nsresult GetFeatureStatusImpl(PRInt32 aFeature, 
+                                        PRInt32 *aStatus, 
+                                        nsAString & aSuggestedDriverVersion, 
+                                        GfxDriverInfo* aDriverInfo = nsnull,
+                                        OperatingSystem* aOS = nsnull);
+  virtual const GfxDriverInfo* GetGfxDriverInfo();
 
 private:
 
   void     AddOpenGLCrashReportAnnotations();
   bool     mSetCrashReportAnnotations;
   nsString mRendererIDsString;
   nsString mAdapterRAMString;
 
--- a/widget/src/cocoa/GfxInfo.h
+++ b/widget/src/cocoa/GfxInfo.h
@@ -77,17 +77,22 @@ public:
   using GfxInfoBase::GetFeatureStatus;
   using GfxInfoBase::GetFeatureSuggestedDriverVersion;
   using GfxInfoBase::GetWebGLParameter;
 
   virtual nsresult Init();
 
 protected:
 
-  virtual nsresult GetFeatureStatusImpl(PRInt32 aFeature, PRInt32 *aStatus, nsAString & aSuggestedDriverVersion, GfxDriverInfo* aDriverInfo = nsnull);
+  virtual nsresult GetFeatureStatusImpl(PRInt32 aFeature, 
+                                        PRInt32 *aStatus, 
+                                        nsAString & aSuggestedDriverVersion, 
+                                        GfxDriverInfo* aDriverInfo = nsnull, 
+                                        OperatingSystem* aOS = nsnull);
+  virtual const GfxDriverInfo* GetGfxDriverInfo();
 
 private:
 
   void GetDeviceInfo();
   void AddCrashReportAnnotations();
   nsString mRendererIDsString;
   nsString mAdapterRAMString;
 
@@ -95,14 +100,16 @@ private:
   nsString mDriverVersion;
   nsString mDriverDate;
   nsString mDeviceKey;
 
   PRUint32 mAdapterVendorID;
   PRUint32 mAdapterDeviceID;
 
   PRUint32 mRendererIDs[16];
+
+  PRUint32 mOSXVersion;
 };
 
 } // namespace widget
 } // namespace mozilla
 
 #endif /* __mozilla_widget_GfxInfo_h__ */
--- a/widget/src/cocoa/GfxInfo.mm
+++ b/widget/src/cocoa/GfxInfo.mm
@@ -44,23 +44,31 @@
 #include "GfxInfo.h"
 #include "nsUnicharUtils.h"
 #include "mozilla/FunctionTimer.h"
 #include "nsToolkit.h"
 #include "mozilla/Preferences.h"
 
 #import <Foundation/Foundation.h>
 #import <IOKit/IOKitLib.h>
+#import <Cocoa/Cocoa.h>
 
 #if defined(MOZ_CRASHREPORTER)
 #include "nsExceptionHandler.h"
 #include "nsICrashReporter.h"
 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
 #endif
 
+#define MAC_OS_X_VERSION_MASK       0x0000FFFF
+#define MAC_OS_X_VERSION_MAJOR_MASK 0x0000FFF0
+#define MAC_OS_X_VERSION_10_4_HEX   0x00001040 // Not supported
+#define MAC_OS_X_VERSION_10_5_HEX   0x00001050
+#define MAC_OS_X_VERSION_10_6_HEX   0x00001060
+#define MAC_OS_X_VERSION_10_7_HEX   0x00001070
+
 using namespace mozilla;
 using namespace mozilla::widget;
 
 GfxInfo::GfxInfo()
   : mAdapterVendorID(0),
     mAdapterDeviceID(0)
 {
 }
@@ -334,32 +342,65 @@ GfxInfo::AddCrashReportAnnotations()
   /* AppendPrintf only supports 32 character strings, mrghh. */
   note.AppendLiteral("Renderers: ");
   note.Append(NS_LossyConvertUTF16toASCII(mRendererIDsString));
 
   CrashReporter::AppendAppNotesToCrashReport(note);
 #endif
 }
 
+static GfxDriverInfo gDriverInfo[] = {
+  // We don't support checking driver versions on Mac.
+  #define IMPLEMENT_MAC_DRIVER_BLOCKLIST(os, vendor, device, features, blockOn) \
+    GfxDriverInfo(os, vendor, device, features, blockOn,                        \
+                  DRIVER_UNKNOWN_COMPARISON, V(0,0,0,0), ""),
+
+  // Example use of macro.
+  //IMPLEMENT_MAC_DRIVER_BLOCKLIST(DRIVER_OS_OS_X_10_7,
+  //  GfxDriverInfo::vendorATI, GfxDriverInfo::allDevices,
+  //  GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION)
+
+  GfxDriverInfo()
+};
+
+const GfxDriverInfo*
+GfxInfo::GetGfxDriverInfo()
+{
+  return &gDriverInfo[0];
+}
+
+static OperatingSystem
+OSXVersionToOperatingSystem(PRUint32 aOSXVersion)
+{
+  switch (aOSXVersion & MAC_OS_X_VERSION_MAJOR_MASK) {
+    case MAC_OS_X_VERSION_10_5_HEX:
+      return DRIVER_OS_OS_X_10_5;
+    case MAC_OS_X_VERSION_10_6_HEX:
+      return DRIVER_OS_OS_X_10_6;
+    case MAC_OS_X_VERSION_10_7_HEX:
+      return DRIVER_OS_OS_X_10_7;
+  }
+
+  return DRIVER_OS_UNKNOWN;
+}
+
 nsresult
-GfxInfo::GetFeatureStatusImpl(PRInt32 aFeature, PRInt32* aStatus,
+GfxInfo::GetFeatureStatusImpl(PRInt32 aFeature, 
+                              PRInt32* aStatus,
                               nsAString& aSuggestedDriverVersion,
-                              GfxDriverInfo* aDriverInfo /* = nsnull */)
+                              GfxDriverInfo* aDriverInfo /* = nsnull */,
+                              OperatingSystem* aOS /* = nsnull */)
 {
   NS_ENSURE_ARG_POINTER(aStatus);
 
   aSuggestedDriverVersion.SetIsVoid(true);
 
   PRInt32 status = nsIGfxInfo::FEATURE_NO_INFO;
 
-  // For now, we don't implement the downloaded blacklist.
-  if (aDriverInfo) {
-    *aStatus = status;
-    return NS_OK;
-  }
+  OperatingSystem os = OSXVersionToOperatingSystem(nsToolkit::OSXVersion());
 
   // Many WebGL issues on 10.5, especially:
   //   * bug 631258: WebGL shader paints using textures belonging to other processes on Mac OS 10.5
   //   * bug 618848: Post process shaders and texture mapping crash OS X 10.5
   if (aFeature == nsIGfxInfo::FEATURE_WEBGL_OPENGL &&
       !nsToolkit::OnSnowLeopardOrLater())
   {
     status = nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION;
@@ -420,11 +461,14 @@ GfxInfo::GetFeatureStatusImpl(PRInt32 aF
     if (mAdapterVendorID == 0x10de && mAdapterDeviceID == 0x0393) {
       foundGoodDevice = false;
     }
 
     if (!foundGoodDevice)
       status = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
   }
 
+  if (aOS)
+    *aOS = os;
   *aStatus = status;
-  return NS_OK;
+
+  return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, &os);
 }
--- a/widget/src/windows/GfxInfo.cpp
+++ b/widget/src/windows/GfxInfo.cpp
@@ -59,24 +59,16 @@
 using namespace mozilla;
 using namespace mozilla::widget;
 
 #ifdef DEBUG
 NS_IMPL_ISUPPORTS_INHERITED1(GfxInfo, GfxInfoBase, nsIGfxInfoDebug)
 #endif
 
 static const PRUint32 allWindowsVersions = 0xffffffff;
-static const PRUint64 allDriverVersions = 0xffffffffffffffffULL;
-
-static const PRUint32 vendorIntel = 0x8086;
-
-static const PRUint32 vendorNVIDIA = 0x10de;
-
-static const PRUint32 vendorAMD = 0x1022;
-static const PRUint32 vendorATI = 0x1002;
 
 #define V(a,b,c,d) GFX_DRIVER_VERSION(a,b,c,d)
 
 
 GfxInfo::GfxInfo()
   : mAdapterVendorID(0),
     mAdapterDeviceID(0),
     mAdapterVendorID2(0),
@@ -486,17 +478,17 @@ GfxInfo::Init()
   }
 
   const char *spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_VENDOR_ID");
   if (spoofedVendor) {
      PR_sscanf(spoofedVendor, "%x", &mAdapterVendorID);
   }
 
   mHasDriverVersionMismatch = false;
-  if (mAdapterVendorID == vendorIntel) {
+  if (mAdapterVendorID == GfxDriverInfo::vendorIntel) {
     // we've had big crashers (bugs 590373 and 595364) apparently correlated
     // with bad Intel driver installations where the DriverVersion reported
     // by the registry was not the version of the DLL.
     bool is64bitApp = sizeof(void*) == 8;
     const PRUnichar *dllFileName = is64bitApp
                                  ? L"igd10umd64.dll"
                                  : L"igd10umd32.dll";
     nsString dllVersion;
@@ -726,230 +718,124 @@ GfxInfo::AddCrashReportAnnotations()
     note.AppendPrintf("AdapterDriverVersion2: ");
     note.Append(NS_LossyConvertUTF16toASCII(adapterDriverVersionString2));
   }
   CrashReporter::AppendAppNotesToCrashReport(note);
 
 #endif
 }
 
-#define V(a,b,c,d) GFX_DRIVER_VERSION(a,b,c,d)
-
-static const PRUint32 deviceFamilyIntelGMA500[] = {
-    0x8108, /* IntelGMA500_1 */
-    0x8109, /* IntelGMA500_2 */
-    0
-};
-
-static const PRUint32 deviceFamilyIntelGMA900[] = {
-    0x2582, /* IntelGMA900_1 */
-    0x2782, /* IntelGMA900_2 */
-    0x2592, /* IntelGMA900_3 */
-    0x2792, /* IntelGMA900_4 */
-    0
-};
-
-static const PRUint32 deviceFamilyIntelGMA950[] = {
-    0x2772, /* Intel945G_1 */
-    0x2776, /* Intel945G_2 */
-    0x27A2, /* Intel945_1 */
-    0x27A6, /* Intel945_2 */
-    0x27AE, /* Intel945_3 */
-    0
-};
-
-static const PRUint32 deviceFamilyIntelGMA3150[] = {
-    0xA001, /* IntelGMA3150_Nettop_1 */
-    0xA002, /* IntelGMA3150_Nettop_2 */
-    0xA011, /* IntelGMA3150_Netbook_1 */
-    0xA012, /* IntelGMA3150_Netbook_2 */
-    0
-};
-
-static const PRUint32 deviceFamilyIntelGMAX3000[] = {
-    0x2972, /* Intel946GZ_1 */
-    0x2973, /* Intel946GZ_2 */
-    0x2982, /* IntelG35_1 */
-    0x2983, /* IntelG35_2 */
-    0x2992, /* IntelQ965_1 */
-    0x2993, /* IntelQ965_2 */
-    0x29A2, /* IntelG965_1 */
-    0x29A3, /* IntelG965_2 */
-    0x29B2, /* IntelQ35_1 */
-    0x29B3, /* IntelQ35_2 */
-    0x29C2, /* IntelG33_1 */
-    0x29C3, /* IntelG33_2 */
-    0x29D2, /* IntelQ33_1 */
-    0x29D3, /* IntelQ33_2 */
-    0x2A02, /* IntelGL960_1 */
-    0x2A03, /* IntelGL960_2 */
-    0x2A12, /* IntelGM965_1 */
-    0x2A13, /* IntelGM965_2 */
-    0
-};
-
-static const PRUint32 deviceFamilyIntelGMAX4500HD[] = {
-    0x2A42, /* IntelGMA4500MHD_1 */
-    0x2A43, /* IntelGMA4500MHD_2 */
-    0x2E42, /* IntelB43_1 */
-    0x2E43, /* IntelB43_2 */
-    0x2E92, /* IntelB43_3 */
-    0x2E93, /* IntelB43_4 */
-    0x2E32, /* IntelG41_1 */
-    0x2E33, /* IntelG41_2 */
-    0x2E22, /* IntelG45_1 */
-    0x2E23, /* IntelG45_2 */
-    0x2E12, /* IntelQ45_1 */
-    0x2E13, /* IntelQ45_2 */
-    0x0042, /* IntelHDGraphics */
-    0x0046, /* IntelMobileHDGraphics */
-    0x0102, /* IntelSandyBridge_1 */
-    0x0106, /* IntelSandyBridge_2 */
-    0x0112, /* IntelSandyBridge_3 */
-    0x0116, /* IntelSandyBridge_4 */
-    0x0122, /* IntelSandyBridge_5 */
-    0x0126, /* IntelSandyBridge_6 */
-    0x010A, /* IntelSandyBridge_7 */
-    0x0080, /* IntelIvyBridge */
-    0
-};
-
-// Glitches whilst scrolling (see bugs 612007, 644787, 645872)
-static const PRUint32 deviceFamilyNvidiaBlockD3D9Layers[] = {
-    0x00f3, /* NV43 [GeForce 6200 (TM)] */
-    0x0146, /* NV43 [Geforce Go 6600TE/6200TE (TM)] */
-    0x014f, /* NV43 [GeForce 6200 (TM)] */
-    0x0161, /* NV44 [GeForce 6200 TurboCache (TM)] */
-    0x0162, /* NV44 [GeForce 6200SE TurboCache (TM)] */
-    0x0163, /* NV44 [GeForce 6200 LE (TM)] */
-    0x0164, /* NV44 [GeForce Go 6200 (TM)] */
-    0x0167, /* NV43 [GeForce Go 6200/6400 (TM)] */
-    0x0168, /* NV43 [GeForce Go 6200/6400 (TM)] */
-    0x0169, /* NV44 [GeForce 6250 (TM)] */
-    0x0222, /* NV44 [GeForce 6200 A-LE (TM)] */
-    0x0240, /* C51PV [GeForce 6150 (TM)] */
-    0x0241, /* C51 [GeForce 6150 LE (TM)] */
-    0x0244, /* C51 [Geforce Go 6150 (TM)] */
-    0x0245, /* C51 [Quadro NVS 210S/GeForce 6150LE (TM)] */
-    0x0247, /* C51 [GeForce Go 6100 (TM)] */
-    0x03d0, /* C61 [GeForce 6150SE nForce 430 (TM)] */
-    0x03d1, /* C61 [GeForce 6100 nForce 405 (TM)] */
-    0x03d2, /* C61 [GeForce 6100 nForce 400 (TM)] */
-    0x03d5, /* C61 [GeForce 6100 nForce 420 (TM)] */
-    0
-};
-
 static const GfxDriverInfo gDriverInfo[] = {
   /*
    * Notice that the first match defines the result. So always implement special cases firsts and general case last.
    */
 
   /*
    * NVIDIA entries
    */
   GfxDriverInfo( DRIVER_OS_WINDOWS_XP,
-    vendorNVIDIA, GfxDriverInfo::allDevices,
+    GfxDriverInfo::vendorNVIDIA, GfxDriverInfo::allDevices,
     GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
     DRIVER_LESS_THAN, V(6,14,12,5721), "257.21" ),
   GfxDriverInfo( DRIVER_OS_WINDOWS_VISTA,
-    vendorNVIDIA, GfxDriverInfo::allDevices,
+    GfxDriverInfo::vendorNVIDIA, GfxDriverInfo::allDevices,
     GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
     DRIVER_LESS_THAN, V(8,17,12,5721), "257.21" ),
   GfxDriverInfo( DRIVER_OS_WINDOWS_7,
-    vendorNVIDIA, GfxDriverInfo::allDevices,
+    GfxDriverInfo::vendorNVIDIA, GfxDriverInfo::allDevices,
     GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
     DRIVER_LESS_THAN, V(8,17,12,5721), "257.21" ),
 
   /* Disable D3D9 layers on NVIDIA 6100/6150/6200 series due to glitches
    * whilst scrolling. See bugs: 612007, 644787 & 645872.
    */
   GfxDriverInfo( DRIVER_OS_ALL,
-    vendorNVIDIA, (GfxDeviceFamily) deviceFamilyNvidiaBlockD3D9Layers,
+    GfxDriverInfo::vendorNVIDIA, (GfxDeviceFamily) deviceFamilyNvidiaBlockD3D9Layers,
     nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
-    DRIVER_LESS_THAN, allDriverVersions ),
+    DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ),
 
   /*
    * AMD/ATI entries
    */
   GfxDriverInfo( DRIVER_OS_ALL,
-    vendorATI, GfxDriverInfo::allDevices,
+    GfxDriverInfo::vendorATI, GfxDriverInfo::allDevices,
     GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
     DRIVER_LESS_THAN, V(8,741,0,0), "10.6" ),
   GfxDriverInfo( DRIVER_OS_ALL,
-    vendorAMD, GfxDriverInfo::allDevices,
+    GfxDriverInfo::vendorAMD, GfxDriverInfo::allDevices,
     GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
     DRIVER_LESS_THAN, V(8,741,0,0), "10.6" ),
 
   /* OpenGL on any ATI/AMD hardware is discouraged
    * See:
    *  bug 619773 - WebGL: Crash with blue screen : "NMI: Parity Check / Memory Parity Error"
    *  bugs 584403, 584404, 620924 - crashes in atioglxx
    *  + many complaints about incorrect rendering
    */
   GfxDriverInfo( DRIVER_OS_ALL,
-    vendorATI, GfxDriverInfo::allDevices,
+    GfxDriverInfo::vendorATI, GfxDriverInfo::allDevices,
     nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
-    DRIVER_LESS_THAN, allDriverVersions ),
+    DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ),
   GfxDriverInfo( DRIVER_OS_ALL,
-    vendorATI, GfxDriverInfo::allDevices,
+    GfxDriverInfo::vendorATI, GfxDriverInfo::allDevices,
     nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
-    DRIVER_LESS_THAN, allDriverVersions ),
+    DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ),
   GfxDriverInfo( DRIVER_OS_ALL,
-    vendorAMD, GfxDriverInfo::allDevices,
+    GfxDriverInfo::vendorAMD, GfxDriverInfo::allDevices,
     nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
-    DRIVER_LESS_THAN, allDriverVersions ),
+    DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ),
   GfxDriverInfo( DRIVER_OS_ALL,
-    vendorAMD, GfxDriverInfo::allDevices,
+    GfxDriverInfo::vendorAMD, GfxDriverInfo::allDevices,
     nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
-    DRIVER_LESS_THAN, allDriverVersions ),
+    DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ),
 
   /*
    * Intel entries
    */
 
   /* implement the blocklist from bug 594877
    * Block all features on any drivers before this, as there's a crash when a MS Hotfix is installed.
    * The crash itself is Direct2D-related, but for safety we block all features.
    */
-#define IMPLEMENT_INTEL_DRIVER_BLOCKLIST(winVer, devFamily, driverVer) \
-  GfxDriverInfo( winVer,                                               \
-    vendorIntel, (GfxDeviceFamily) devFamily,                          \
-    GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,           \
-    DRIVER_LESS_THAN, driverVer ),
+  #define IMPLEMENT_INTEL_DRIVER_BLOCKLIST(winVer, devFamily, driverVer) \
+    GfxDriverInfo( winVer,                                               \
+      GfxDriverInfo::vendorIntel, (GfxDeviceFamily) devFamily,                          \
+      GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,           \
+      DRIVER_LESS_THAN, driverVer ),
 
   IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, deviceFamilyIntelGMA500,   V(6,14,11,1018))
   IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, deviceFamilyIntelGMA900,   V(6,14,10,4764))
   IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, deviceFamilyIntelGMA950,   V(6,14,10,4926))
   IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, deviceFamilyIntelGMA3150,  V(6,14,10,5260))
   IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, deviceFamilyIntelGMAX3000, V(6,14,10,5218))
   IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, deviceFamilyIntelGMAX4500HD, V(6,14,10,5284))
 
   IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, deviceFamilyIntelGMA500,   V(7,14,10,1006))
-  IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, deviceFamilyIntelGMA900,   allDriverVersions)
+  IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, deviceFamilyIntelGMA900,   GfxDriverInfo::allDriverVersions)
   IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, deviceFamilyIntelGMA950,   V(7,14,10,1504))
   IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, deviceFamilyIntelGMA3150,  V(7,14,10,2124))
   IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, deviceFamilyIntelGMAX3000, V(7,15,10,1666))
   IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, deviceFamilyIntelGMAX4500HD, V(8,15,10,2202))
 
   IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, deviceFamilyIntelGMA500,   V(5,0,0,2026))
-  IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, deviceFamilyIntelGMA900,   allDriverVersions)
+  IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, deviceFamilyIntelGMA900,   GfxDriverInfo::allDriverVersions)
   IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, deviceFamilyIntelGMA950,   V(8,15,10,1930))
   IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, deviceFamilyIntelGMA3150,  V(8,14,10,2117))
   IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, deviceFamilyIntelGMAX3000, V(8,15,10,1930))
   IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, deviceFamilyIntelGMAX4500HD, V(8,15,10,2202))
 
-  /* OpenGL on any Intel hardware is discouraged */
+   /* OpenGL on any Intel hardware is discouraged */
   GfxDriverInfo( DRIVER_OS_ALL,
-    vendorIntel, GfxDriverInfo::allDevices,
+    GfxDriverInfo::vendorIntel, GfxDriverInfo::allDevices,
     nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
-    DRIVER_LESS_THAN, allDriverVersions ),
+    DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ),
   GfxDriverInfo( DRIVER_OS_ALL,
-    vendorIntel, GfxDriverInfo::allDevices,
+    GfxDriverInfo::vendorIntel, GfxDriverInfo::allDevices,
     nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
-    DRIVER_LESS_THAN, allDriverVersions ),
+    DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ),
 
   GfxDriverInfo()
 };
 
 static OperatingSystem
 WindowsVersionToOperatingSystem(PRInt32 aWindowsVersion)
 {
   switch(aWindowsVersion) {
@@ -964,38 +850,48 @@ WindowsVersionToOperatingSystem(PRInt32 
     case gfxWindowsPlatform::kWindows7:
       return DRIVER_OS_WINDOWS_7;
     case gfxWindowsPlatform::kWindowsUnknown:
     default:
       return DRIVER_OS_UNKNOWN;
     };
 }
 
+const GfxDriverInfo*
+GfxInfo::GetGfxDriverInfo()
+{
+  return &gDriverInfo[0];
+}
+
 nsresult
-GfxInfo::GetFeatureStatusImpl(PRInt32 aFeature, PRInt32 *aStatus, nsAString & aSuggestedDriverVersion, GfxDriverInfo* aDriverInfo /* = nsnull */)
+GfxInfo::GetFeatureStatusImpl(PRInt32 aFeature, 
+                              PRInt32 *aStatus, 
+                              nsAString & aSuggestedDriverVersion, 
+                              GfxDriverInfo* aDriverInfo /* = nsnull */, 
+                              OperatingSystem* aOS /* = nsnull */)
 {
   *aStatus = nsIGfxInfo::FEATURE_NO_INFO;
   aSuggestedDriverVersion.SetIsVoid(true);
 
   PRInt32 status = nsIGfxInfo::FEATURE_NO_INFO;
 
   PRUint32 adapterVendor = 0;
   PRUint32 adapterDeviceID = 0;
   nsAutoString adapterDriverVersionString;
   if (NS_FAILED(GetAdapterVendorID(&adapterVendor)) ||
       NS_FAILED(GetAdapterDeviceID(&adapterDeviceID)) ||
       NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString)))
   {
     return NS_ERROR_FAILURE;
   }
 
-  if (adapterVendor != vendorIntel &&
-      adapterVendor != vendorNVIDIA &&
-      adapterVendor != vendorAMD &&
-      adapterVendor != vendorATI &&
+  if (adapterVendor != GfxDriverInfo::vendorIntel &&
+      adapterVendor != GfxDriverInfo::vendorNVIDIA &&
+      adapterVendor != GfxDriverInfo::vendorAMD &&
+      adapterVendor != GfxDriverInfo::vendorATI &&
       // FIXME - these special hex values are currently used in xpcshell tests introduced by
       // bug 625160 patch 8/8. Maybe these tests need to be adjusted now that we're only whitelisting
       // intel/ati/nvidia.
       adapterVendor != 0xabcd &&
       adapterVendor != 0xdcba &&
       adapterVendor != 0xabab &&
       adapterVendor != 0xdcdc)
   {
@@ -1042,121 +938,21 @@ GfxInfo::GetFeatureStatusImpl(PRInt32 aF
         aFeature == nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS ||
         aFeature == nsIGfxInfo::FEATURE_DIRECT2D)
     {
       *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
       return NS_OK;
     }
   }
 
-  // special-case the WinXP test slaves: they have out-of-date drivers, but we still want to
-  // whitelist them, actually we do know that this combination of device and driver version
-  // works well.
-  if (os == DRIVER_OS_WINDOWS_XP &&
-      adapterVendor == vendorNVIDIA &&
-      adapterDeviceID == 0x0861 && // GeForce 9400
-      driverVersion == V(6,14,11,7756))
-  {
-    return NS_OK;
-  }
-
-  while (info->mOperatingSystem) {
-
-    if (info->mOperatingSystem != DRIVER_OS_ALL &&
-        info->mOperatingSystem != os)
-    {
-      info++;
-      continue;
-    }
-
-    if (info->mAdapterVendor != GfxDriverInfo::allAdapterVendors &&
-        info->mAdapterVendor != adapterVendor) {
-      info++;
-      continue;
-    }
-
-    if (info->mDevices != GfxDriverInfo::allDevices) {
-        bool deviceMatches = false;
-        for (const PRUint32 *devices = info->mDevices; *devices; ++devices) {
-            if (*devices == adapterDeviceID) {
-                deviceMatches = true;
-                break;
-            }
-        }
-
-        if (!deviceMatches) {
-            info++;
-            continue;
-        }
-    }
-
-    bool match = false;
+  *aStatus = status;
+  if (aOS)
+    *aOS = os;
 
-    switch (info->mComparisonOp) {
-    case DRIVER_LESS_THAN:
-      match = driverVersion < info->mDriverVersion;
-      break;
-    case DRIVER_LESS_THAN_OR_EQUAL:
-      match = driverVersion <= info->mDriverVersion;
-      break;
-    case DRIVER_GREATER_THAN:
-      match = driverVersion > info->mDriverVersion;
-      break;
-    case DRIVER_GREATER_THAN_OR_EQUAL:
-      match = driverVersion >= info->mDriverVersion;
-      break;
-    case DRIVER_EQUAL:
-      match = driverVersion == info->mDriverVersion;
-      break;
-    case DRIVER_NOT_EQUAL:
-      match = driverVersion != info->mDriverVersion;
-      break;
-    case DRIVER_BETWEEN_EXCLUSIVE:
-      match = driverVersion > info->mDriverVersion && driverVersion < info->mDriverVersionMax;
-      break;
-    case DRIVER_BETWEEN_INCLUSIVE:
-      match = driverVersion >= info->mDriverVersion && driverVersion <= info->mDriverVersionMax;
-      break;
-    case DRIVER_BETWEEN_INCLUSIVE_START:
-      match = driverVersion >= info->mDriverVersion && driverVersion < info->mDriverVersionMax;
-      break;
-    default:
-      NS_WARNING("Bogus op in GfxDriverInfo");
-      break;
-    }
-
-    if (match) {
-      if (info->mFeature == GfxDriverInfo::allFeatures ||
-          info->mFeature == aFeature)
-      {
-        status = info->mFeatureStatus;
-        break;
-      }
-    }
-
-    info++;
-  }
-
-  *aStatus = status;
-
-  if (status == FEATURE_BLOCKED_DRIVER_VERSION) {
-      if (info->mSuggestedVersion) {
-          aSuggestedDriverVersion.AppendPrintf("%s", info->mSuggestedVersion);
-      } else if (info->mComparisonOp == DRIVER_LESS_THAN &&
-                 info->mDriverVersion != allDriverVersions)
-      {
-          aSuggestedDriverVersion.AppendPrintf("%lld.%lld.%lld.%lld",
-                                               (info->mDriverVersion & 0xffff000000000000) >> 48,
-                                               (info->mDriverVersion & 0x0000ffff00000000) >> 32,
-                                               (info->mDriverVersion & 0x00000000ffff0000) >> 16,
-                                               (info->mDriverVersion & 0x000000000000ffff));
-      }
-  }
-  
-  return NS_OK;
+  return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, &os);
 }
 
 #ifdef DEBUG
 
 // Implement nsIGfxInfoDebug
 
 /* void spoofVendorID (in unsigned long aVendorID); */
 NS_IMETHODIMP GfxInfo::SpoofVendorID(PRUint32 aVendorID)
--- a/widget/src/windows/GfxInfo.h
+++ b/widget/src/windows/GfxInfo.h
@@ -84,17 +84,22 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIGFXINFODEBUG
 #endif
 
   virtual nsresult Init();
 
 protected:
 
-  virtual nsresult GetFeatureStatusImpl(PRInt32 aFeature, PRInt32 *aStatus, nsAString & aSuggestedDriverVersion, GfxDriverInfo* aDriverInfo = nsnull);
+  virtual nsresult GetFeatureStatusImpl(PRInt32 aFeature, 
+                                        PRInt32 *aStatus, 
+                                        nsAString & aSuggestedDriverVersion, 
+                                        GfxDriverInfo* aDriverInfo = nsnull, 
+                                        OperatingSystem* aOS = nsnull);
+  virtual const GfxDriverInfo* GetGfxDriverInfo();
 
 private:
 
   void AddCrashReportAnnotations();
   nsString mDeviceString;
   nsString mDeviceID;
   nsString mDriverVersion;
   nsString mDriverDate;
--- a/widget/src/xpwidgets/GfxDriverInfo.cpp
+++ b/widget/src/xpwidgets/GfxDriverInfo.cpp
@@ -37,16 +37,23 @@
 
 #include "GfxDriverInfo.h"
 #include "nsIGfxInfo.h"
 
 using namespace mozilla::widget;
 
 PRUint32 GfxDriverInfo::allAdapterVendors = 0;
 PRInt32 GfxDriverInfo::allFeatures = 0;
+PRUint64 GfxDriverInfo::allDriverVersions = ~(PRUint64(0));
+
+PRUint32 GfxDriverInfo::vendorIntel = 0x8086;
+PRUint32 GfxDriverInfo::vendorNVIDIA = 0x10de;
+PRUint32 GfxDriverInfo::vendorAMD = 0x1022;
+PRUint32 GfxDriverInfo::vendorATI = 0x1002;
+
 GfxDeviceFamily GfxDriverInfo::allDevices = nsnull;
 
 GfxDriverInfo::GfxDriverInfo()
   : mOperatingSystem(DRIVER_OS_UNKNOWN),
     mAdapterVendor(allAdapterVendors),
     mDevices(allDevices),
     mDeleteDevices(false),
     mFeature(allFeatures),
--- a/widget/src/xpwidgets/GfxDriverInfo.h
+++ b/widget/src/xpwidgets/GfxDriverInfo.h
@@ -36,45 +36,153 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "prtypes.h"
 #include "nsString.h"
 
 #ifndef __mozilla_widget_GfxDriverInfo_h__
 #define __mozilla_widget_GfxDriverInfo_h__
 
+#define V(a,b,c,d) GFX_DRIVER_VERSION(a,b,c,d)
+
 namespace mozilla {
 namespace widget {
 
 enum OperatingSystem {
   DRIVER_OS_UNKNOWN = 0,
   DRIVER_OS_WINDOWS_2000,
   DRIVER_OS_WINDOWS_XP,
   DRIVER_OS_WINDOWS_SERVER_2003,
   DRIVER_OS_WINDOWS_VISTA,
   DRIVER_OS_WINDOWS_7,
   DRIVER_OS_LINUX,
   DRIVER_OS_OS_X_10_5,
   DRIVER_OS_OS_X_10_6,
+  DRIVER_OS_OS_X_10_7,
+  DRIVER_OS_ANDROID,
   DRIVER_OS_ALL
 };
 
 enum VersionComparisonOp {
   DRIVER_LESS_THAN,             // driver <  version
   DRIVER_LESS_THAN_OR_EQUAL,    // driver <= version
   DRIVER_GREATER_THAN,          // driver >  version
   DRIVER_GREATER_THAN_OR_EQUAL, // driver >= version
   DRIVER_EQUAL,                 // driver == version
   DRIVER_NOT_EQUAL,             // driver != version
   DRIVER_BETWEEN_EXCLUSIVE,     // driver > version && driver < versionMax
   DRIVER_BETWEEN_INCLUSIVE,     // driver >= version && driver <= versionMax
   DRIVER_BETWEEN_INCLUSIVE_START, // driver >= version && driver < versionMax
   DRIVER_UNKNOWN_COMPARISON
 };
 
+static const PRUint32 deviceFamilyIntelGMA500[] = {
+    0x8108, /* IntelGMA500_1 */
+    0x8109, /* IntelGMA500_2 */
+    0
+};
+
+static const PRUint32 deviceFamilyIntelGMA900[] = {
+    0x2582, /* IntelGMA900_1 */
+    0x2782, /* IntelGMA900_2 */
+    0x2592, /* IntelGMA900_3 */
+    0x2792, /* IntelGMA900_4 */
+    0
+};
+
+static const PRUint32 deviceFamilyIntelGMA950[] = {
+    0x2772, /* Intel945G_1 */
+    0x2776, /* Intel945G_2 */
+    0x27A2, /* Intel945_1 */
+    0x27A6, /* Intel945_2 */
+    0x27AE, /* Intel945_3 */
+    0
+};
+
+static const PRUint32 deviceFamilyIntelGMA3150[] = {
+    0xA001, /* IntelGMA3150_Nettop_1 */
+    0xA002, /* IntelGMA3150_Nettop_2 */
+    0xA011, /* IntelGMA3150_Netbook_1 */
+    0xA012, /* IntelGMA3150_Netbook_2 */
+    0
+};
+
+static const PRUint32 deviceFamilyIntelGMAX3000[] = {
+    0x2972, /* Intel946GZ_1 */
+    0x2973, /* Intel946GZ_2 */
+    0x2982, /* IntelG35_1 */
+    0x2983, /* IntelG35_2 */
+    0x2992, /* IntelQ965_1 */
+    0x2993, /* IntelQ965_2 */
+    0x29A2, /* IntelG965_1 */
+    0x29A3, /* IntelG965_2 */
+    0x29B2, /* IntelQ35_1 */
+    0x29B3, /* IntelQ35_2 */
+    0x29C2, /* IntelG33_1 */
+    0x29C3, /* IntelG33_2 */
+    0x29D2, /* IntelQ33_1 */
+    0x29D3, /* IntelQ33_2 */
+    0x2A02, /* IntelGL960_1 */
+    0x2A03, /* IntelGL960_2 */
+    0x2A12, /* IntelGM965_1 */
+    0x2A13, /* IntelGM965_2 */
+    0
+};
+
+static const PRUint32 deviceFamilyIntelGMAX4500HD[] = {
+    0x2A42, /* IntelGMA4500MHD_1 */
+    0x2A43, /* IntelGMA4500MHD_2 */
+    0x2E42, /* IntelB43_1 */
+    0x2E43, /* IntelB43_2 */
+    0x2E92, /* IntelB43_3 */
+    0x2E93, /* IntelB43_4 */
+    0x2E32, /* IntelG41_1 */
+    0x2E33, /* IntelG41_2 */
+    0x2E22, /* IntelG45_1 */
+    0x2E23, /* IntelG45_2 */
+    0x2E12, /* IntelQ45_1 */
+    0x2E13, /* IntelQ45_2 */
+    0x0042, /* IntelHDGraphics */
+    0x0046, /* IntelMobileHDGraphics */
+    0x0102, /* IntelSandyBridge_1 */
+    0x0106, /* IntelSandyBridge_2 */
+    0x0112, /* IntelSandyBridge_3 */
+    0x0116, /* IntelSandyBridge_4 */
+    0x0122, /* IntelSandyBridge_5 */
+    0x0126, /* IntelSandyBridge_6 */
+    0x010A, /* IntelSandyBridge_7 */
+    0x0080, /* IntelIvyBridge */
+    0
+};
+
+// Glitches whilst scrolling (see bugs 612007, 644787, 645872)
+static const PRUint32 deviceFamilyNvidiaBlockD3D9Layers[] = {
+    0x00f3, /* NV43 [GeForce 6200 (TM)] */
+    0x0146, /* NV43 [Geforce Go 6600TE/6200TE (TM)] */
+    0x014f, /* NV43 [GeForce 6200 (TM)] */
+    0x0161, /* NV44 [GeForce 6200 TurboCache (TM)] */
+    0x0162, /* NV44 [GeForce 6200SE TurboCache (TM)] */
+    0x0163, /* NV44 [GeForce 6200 LE (TM)] */
+    0x0164, /* NV44 [GeForce Go 6200 (TM)] */
+    0x0167, /* NV43 [GeForce Go 6200/6400 (TM)] */
+    0x0168, /* NV43 [GeForce Go 6200/6400 (TM)] */
+    0x0169, /* NV44 [GeForce 6250 (TM)] */
+    0x0222, /* NV44 [GeForce 6200 A-LE (TM)] */
+    0x0240, /* C51PV [GeForce 6150 (TM)] */
+    0x0241, /* C51 [GeForce 6150 LE (TM)] */
+    0x0244, /* C51 [Geforce Go 6150 (TM)] */
+    0x0245, /* C51 [Quadro NVS 210S/GeForce 6150LE (TM)] */
+    0x0247, /* C51 [GeForce Go 6100 (TM)] */
+    0x03d0, /* C61 [GeForce 6150SE nForce 430 (TM)] */
+    0x03d1, /* C61 [GeForce 6100 nForce 405 (TM)] */
+    0x03d2, /* C61 [GeForce 6100 nForce 400 (TM)] */
+    0x03d5, /* C61 [GeForce 6100 nForce 420 (TM)] */
+    0
+};
+
 /* A zero-terminated array of devices to match, or all devices */
 typedef PRUint32 *GfxDeviceFamily;
 
 struct GfxDriverInfo
 {
   // If |ownDevices| is true, you are transferring ownership of the devices
   // array, and it will be deleted when this GfxDriverInfo is destroyed.
   GfxDriverInfo(OperatingSystem os, PRUint32 vendor, GfxDeviceFamily devices,
@@ -105,16 +213,22 @@ struct GfxDriverInfo
   /* A feature status from nsIGfxInfo */
   PRInt32 mFeatureStatus;
 
   VersionComparisonOp mComparisonOp;
 
   /* versions are assumed to be A.B.C.D packed as 0xAAAABBBBCCCCDDDD */
   PRUint64 mDriverVersion;
   PRUint64 mDriverVersionMax;
+  static PRUint64 allDriverVersions;
+
+  static PRUint32 vendorIntel;
+  static PRUint32 vendorNVIDIA;
+  static PRUint32 vendorAMD;
+  static PRUint32 vendorATI;
 
   const char *mSuggestedVersion;
 };
 
 #define GFX_DRIVER_VERSION(a,b,c,d) \
   ((PRUint64(a)<<48) | (PRUint64(b)<<32) | (PRUint64(c)<<16) | PRUint64(d))
 
 inline bool
--- a/widget/src/xpwidgets/GfxInfoBase.cpp
+++ b/widget/src/xpwidgets/GfxInfoBase.cpp
@@ -244,16 +244,20 @@ BlacklistOSToOperatingSystem(const nsASt
   else if (os == NS_LITERAL_STRING("WINNT 6.1"))
     return DRIVER_OS_WINDOWS_7;
   else if (os == NS_LITERAL_STRING("Linux"))
     return DRIVER_OS_LINUX;
   else if (os == NS_LITERAL_STRING("Darwin 9"))
     return DRIVER_OS_OS_X_10_5;
   else if (os == NS_LITERAL_STRING("Darwin 10"))
     return DRIVER_OS_OS_X_10_6;
+  else if (os == NS_LITERAL_STRING("Darwin 11"))
+    return DRIVER_OS_OS_X_10_7;
+  else if (os == NS_LITERAL_STRING("Android"))
+    return DRIVER_OS_ANDROID;
   else if (os == NS_LITERAL_STRING("All"))
     return DRIVER_OS_ALL;
 
   return DRIVER_OS_UNKNOWN;
 }
 
 static PRUint32
 BlacklistHexToInt(const nsAString& aHex)
@@ -544,26 +548,201 @@ GfxInfoBase::Init()
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (os) {
     os->AddObserver(this, "blocklist-data-gfxItems", true);
   }
 
   return NS_OK;
 }
 
+static const GfxDriverInfo gDriverInfo[] = {
+  // No combinations that cause a crash on every OS.
+  GfxDriverInfo()
+};
+
+
 NS_IMETHODIMP
 GfxInfoBase::GetFeatureStatus(PRInt32 aFeature, PRInt32* aStatus NS_OUTPARAM)
 {
   if (GetPrefValueForFeature(aFeature, *aStatus))
     return NS_OK;
 
   nsString version;
   return GetFeatureStatusImpl(aFeature, aStatus, version);
 }
 
+nsresult
+GfxInfoBase::GetFeatureStatusImpl(PRInt32 aFeature,
+                                  PRInt32* aStatus,
+                                  nsAString& aVersion,
+                                  GfxDriverInfo* aDriverInfo /* = nsnull */,
+                                  OperatingSystem* aOS /* = nsnull */)
+{
+  if (*aStatus != nsIGfxInfo::FEATURE_NO_INFO) {
+    // Terminate now with the status determined by the derived type (OS-specific
+    // code).
+    return NS_OK;
+  }
+
+  OperatingSystem os = DRIVER_OS_UNKNOWN;
+  if (aOS)
+    os = *aOS;
+
+  PRUint32 adapterVendorID = 0;
+  PRUint32 adapterDeviceID = 0;
+  nsAutoString adapterDriverVersionString;
+  if (NS_FAILED(GetAdapterVendorID(&adapterVendorID)) ||
+      NS_FAILED(GetAdapterDeviceID(&adapterDeviceID)) ||
+      NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString)))
+  {
+    return NS_ERROR_FAILURE;
+  }
+
+  PRUint64 driverVersion;
+  if (!ParseDriverVersion(adapterDriverVersionString, &driverVersion)) {
+#if !defined(XP_MACOSX)
+    return NS_ERROR_FAILURE;
+#endif
+  }
+
+  // special-case the WinXP test slaves: they have out-of-date drivers, but we still want to
+  // whitelist them, actually we do know that this combination of device and driver version
+  // works well.
+  if (os == DRIVER_OS_WINDOWS_XP &&
+      adapterVendorID == GfxDriverInfo::vendorNVIDIA &&
+      adapterDeviceID == 0x0861 && // GeForce 9400
+      driverVersion == V(6,14,11,7756))
+  {
+    return NS_OK;
+  }
+
+  PRInt32 status = *aStatus;
+  const GfxDriverInfo* info = aDriverInfo ? aDriverInfo : &gDriverInfo[0];
+  // This code will operate in two modes:
+  // It first loops over the driver tuples stored locally in gDriverInfo,
+  // then loops over it a second time for the OS's specific list to check for
+  // all combinations that can lead to disabling a feature.
+  bool loopingOverOS = false;
+  while (true) {
+    if (!info->mOperatingSystem) {
+      if (loopingOverOS)
+        break;
+      else
+      {
+        // Mark us as looping over the OS driver tuples.
+        loopingOverOS = true;
+        // Get the GfxDriverInfo table from the OS subclass.
+       info = GetGfxDriverInfo();
+      }
+    }
+
+    if (info->mOperatingSystem != DRIVER_OS_ALL &&
+        info->mOperatingSystem != os)
+    {
+      info++;
+      continue;
+    }
+
+    if (info->mAdapterVendor != GfxDriverInfo::allAdapterVendors &&
+        info->mAdapterVendor != adapterVendorID) {
+      info++;
+      continue;
+    }
+
+    if (info->mDevices != GfxDriverInfo::allDevices) {
+        bool deviceMatches = false;
+        for (const PRUint32 *devices = info->mDevices; *devices; ++devices) {
+            if (*devices == adapterDeviceID) {
+                deviceMatches = true;
+                break;
+            }
+        }
+
+        if (!deviceMatches) {
+            info++;
+            continue;
+        }
+    }
+
+    bool match = false;
+
+#if !defined(XP_MACOSX)
+    switch (info->mComparisonOp) {
+    case DRIVER_LESS_THAN:
+      match = driverVersion < info->mDriverVersion;
+      break;
+    case DRIVER_LESS_THAN_OR_EQUAL:
+      match = driverVersion <= info->mDriverVersion;
+      break;
+    case DRIVER_GREATER_THAN:
+      match = driverVersion > info->mDriverVersion;
+      break;
+    case DRIVER_GREATER_THAN_OR_EQUAL:
+      match = driverVersion >= info->mDriverVersion;
+      break;
+    case DRIVER_EQUAL:
+      match = driverVersion == info->mDriverVersion;
+      break;
+    case DRIVER_NOT_EQUAL:
+      match = driverVersion != info->mDriverVersion;
+      break;
+    case DRIVER_BETWEEN_EXCLUSIVE:
+      match = driverVersion > info->mDriverVersion && driverVersion < info->mDriverVersionMax;
+      break;
+    case DRIVER_BETWEEN_INCLUSIVE:
+      match = driverVersion >= info->mDriverVersion && driverVersion <= info->mDriverVersionMax;
+      break;
+    case DRIVER_BETWEEN_INCLUSIVE_START:
+      match = driverVersion >= info->mDriverVersion && driverVersion < info->mDriverVersionMax;
+      break;
+    default:
+      NS_WARNING("Bogus op in GfxDriverInfo");
+      break;
+    }
+#else
+    // We don't care what driver version it was. We only check OS version and if
+    // the device matches.
+    match = true;
+#endif
+
+    if (match) {
+      if (info->mFeature == GfxDriverInfo::allFeatures ||
+          info->mFeature == aFeature)
+      {
+        status = info->mFeatureStatus;
+        break;
+      }
+    }
+
+    info++;
+  }
+ 
+  *aStatus = status;
+
+  // Depends on Windows driver versioning. We don't pass a GfxDriverInfo object
+  // back to the Windows handler, so we must handle this here.
+#if defined(XP_WIN)
+  if (status == FEATURE_BLOCKED_DRIVER_VERSION) {
+    if (info->mSuggestedVersion) {
+        aVersion.AppendPrintf("%s", info->mSuggestedVersion);
+    } else if (info->mComparisonOp == DRIVER_LESS_THAN &&
+               info->mDriverVersion != GfxDriverInfo::allDriverVersions)
+    {
+        aVersion.AppendPrintf("%lld.%lld.%lld.%lld",
+                             (info->mDriverVersion & 0xffff000000000000) >> 48,
+                             (info->mDriverVersion & 0x0000ffff00000000) >> 32,
+                             (info->mDriverVersion & 0x00000000ffff0000) >> 16,
+                             (info->mDriverVersion & 0x000000000000ffff));
+    }
+  }
+#endif
+
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 GfxInfoBase::GetFeatureSuggestedDriverVersion(PRInt32 aFeature,
                                               nsAString& aVersion NS_OUTPARAM)
 {
   nsCString version;
   if (GetPrefValueForDriverVersion(version)) {
     aVersion = NS_ConvertASCIItoUTF16(version);
     return NS_OK;
--- a/widget/src/xpwidgets/GfxInfoBase.h
+++ b/widget/src/xpwidgets/GfxInfoBase.h
@@ -80,24 +80,29 @@ public:
   // version of Init first.
   // We need Init to be called separately from the constructor so we can
   // register as an observer after all derived classes have been constructed
   // and we know we have a non-zero refcount.
   // Ideally, Init() would be void-return, but the rules of
   // NS_GENERIC_FACTORY_CONSTRUCTOR_INIT require it be nsresult return.
   virtual nsresult Init();
   
+  // Gets the driver info table. Used by GfxInfoBase to check for general cases
+  // (while subclasses check for more specific ones).
+  virtual const GfxDriverInfo* GetGfxDriverInfo() = 0;
+
   // only useful on X11
   NS_IMETHOD_(void) GetData() { }
 
 protected:
 
   virtual nsresult GetFeatureStatusImpl(PRInt32 aFeature, PRInt32* aStatus,
                                         nsAString& aSuggestedDriverVersion,
-                                        GfxDriverInfo* aDriverInfo = nsnull) = 0;
+                                        GfxDriverInfo* aDriverInfo = nsnull,
+                                        OperatingSystem* aOS = nsnull);
 
 private:
 
   void EvaluateDownloadedBlacklist(nsTArray<GfxDriverInfo>& aDriverInfo);
 
   nsCString mFailures[9]; // The choice of 9 is Ehsan's
   PRUint32 mFailureCount;
 
--- a/widget/src/xpwidgets/GfxInfoX11.cpp
+++ b/widget/src/xpwidgets/GfxInfoX11.cpp
@@ -241,34 +241,45 @@ GfxInfo::GetData()
     }
 }
 
 static inline PRUint64 version(PRUint32 major, PRUint32 minor, PRUint32 revision = 0)
 {
     return (PRUint64(major) << 32) + (PRUint64(minor) << 16) + PRUint64(revision);
 }
 
+static GfxDriverInfo gDriverInfo[] = {
+  GfxDriverInfo()
+};
+
+const GfxDriverInfo*
+GfxInfo::GetGfxDriverInfo()
+{
+  return &gDriverInfo[0];
+}
+
 nsresult
-GfxInfo::GetFeatureStatusImpl(PRInt32 aFeature, PRInt32 *aStatus, nsAString & aSuggestedDriverVersion, GfxDriverInfo* aDriverInfo /* = nsnull */)
+GfxInfo::GetFeatureStatusImpl(PRInt32 aFeature, 
+                              PRInt32 *aStatus, 
+                              nsAString & aSuggestedDriverVersion, 
+                              GfxDriverInfo* aDriverInfo /* = nsnull */, 
+                              OperatingSystem* aOS /* = nsnull */)
+
 {
     GetData();
     *aStatus = nsIGfxInfo::FEATURE_NO_INFO;
     aSuggestedDriverVersion.SetIsVoid(true);
 
-    if (aDriverInfo) {
-      // We don't implement the downloaded blacklist yet. Don't evaluate
-      // anything.
-      return NS_OK;
-    }
-
 #ifdef MOZ_PLATFORM_MAEMO
     // on Maemo, the glxtest probe doesn't build, and we don't really need GfxInfo anyway
     return NS_OK;
 #endif
 
+    OperatingSystem os = DRIVER_OS_LINUX;
+
     // 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.
@@ -299,17 +310,21 @@ GfxInfo::GetFeatureStatusImpl(PRInt32 aF
         if (version(mMajorVersion, mMinorVersion, mRevisionVersion) < version(3, 0)) {
             *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
         }
     } else {
         // like on windows, let's block unknown vendors. Think of virtual machines.
         // Also, this case is hit whenever the GLXtest probe failed to get driver info or crashed.
         *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
     }
-  return NS_OK;
+
+  if (aOS)
+    *aOS = os;
+
+  return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, &os);
 }
 
 
 NS_IMETHODIMP
 GfxInfo::GetD2DEnabled(bool *aEnabled)
 {
   return NS_ERROR_FAILURE;
 }
--- a/widget/src/xpwidgets/GfxInfoX11.h
+++ b/widget/src/xpwidgets/GfxInfoX11.h
@@ -76,17 +76,22 @@ public:
   using GfxInfoBase::GetWebGLParameter;
 
   virtual nsresult Init();
   
   NS_IMETHOD_(void) GetData();
 
 protected:
 
-  virtual nsresult GetFeatureStatusImpl(PRInt32 aFeature, PRInt32 *aStatus, nsAString & aSuggestedDriverVersion, GfxDriverInfo* aDriverInfo = nsnull);
+  virtual nsresult GetFeatureStatusImpl(PRInt32 aFeature, 
+                                        PRInt32 *aStatus, 
+                                        nsAString & aSuggestedDriverVersion, 
+                                        GfxDriverInfo* aDriverInfo = nsnull, 
+                                        OperatingSystem* aOS = nsnull);
+  virtual const GfxDriverInfo* GetGfxDriverInfo();
 
 private:
   nsCString mVendor;
   nsCString mRenderer;
   nsCString mVersion;
   nsCString mAdapterDescription;
   bool mIsMesa, mIsNVIDIA, mIsFGLRX;
   bool mHasTextureFromPixmap;