Bug 699482: refactored GfxDriverInfo init to happen after global init r=bjacob
authorDoug Sherk <dsherk@mozilla.com>
Wed, 14 Dec 2011 21:02:59 -0800
changeset 84255 f9203039a956038bb6341042398c21c8426d570e
parent 84254 ae42e4497ff2129bd73a33d4316637a0b55961a0
child 84256 8c075fee9be499590b5ee1d4deac3d50c8deada0
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbjacob
bugs699482
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 699482: refactored GfxDriverInfo init to happen after global init r=bjacob This patch moves all static initialization of GfxDriverInfo and DeviceFamily classes to the point that they're actually used. It also converts all static GfxDriverInfo arrays into nsTArray<GfxDriverInfo> so that they can be used interchangeably with the downloadable blocklist. This patch also introduces a new phase of blocklist checking called BEING_PROCESSED, which is the status set when a blocklist check is currently being processed. NO_INFO now only means that we have confirmed that a device is not blocked.
browser/app/blocklist.xml
widget/public/nsIGfxInfo.idl
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/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -220,9 +220,9 @@
             <feature>DIRECT3D_9_LAYERS</feature>
       <featureStatus>BLOCKED_DRIVER_VERSION</featureStatus>
       <driverVersion>7.0.0.0</driverVersion>
       <driverVersionComparator>GREATER_THAN_OR_EQUAL</driverVersionComparator>
     </gfxBlacklistEntry>
     </gfxItems>
 
 
-</blocklist>
\ No newline at end of file
+</blocklist>
--- a/widget/public/nsIGfxInfo.idl
+++ b/widget/public/nsIGfxInfo.idl
@@ -109,29 +109,32 @@ interface nsIGfxInfo : nsISupports
   /* Whether WebGL is supported via ANGLE (D3D9 -- does not check for the presence of ANGLE libs). */
   const long FEATURE_WEBGL_ANGLE = 7;
   /* Whether WebGL antialiasing is supported. */
   const long FEATURE_WEBGL_MSAA = 8;
 
   /*
    * A set of return values from GetFeatureStatus
    */
+
   /* We don't explicitly block or discourage the feature. Which means we'll try getting it from the
    * hardware, and see what happens. */
   const long FEATURE_NO_INFO = 1;
+  /* We don't know the status of the feature yet. The analysis probably hasn't finished yet. */
+  const long FEATURE_STATUS_UNKNOWN = 2;
   /* This feature is blocked on this driver version. Updating driver will typically unblock it. */
-  const long FEATURE_BLOCKED_DRIVER_VERSION = 2;
+  const long FEATURE_BLOCKED_DRIVER_VERSION = 3;
   /* This feature is blocked on this device, regardless of driver version.
    * Typically means we hit too many driver crashes without a good reason to hope for them to
    * get fixed soon. */
-  const long FEATURE_BLOCKED_DEVICE = 3;
+  const long FEATURE_BLOCKED_DEVICE = 4;
   /* This feature is available and can be used, but is not suggested (e.g. shouldn't be used by default */
-  const long FEATURE_DISCOURAGED = 4;
+  const long FEATURE_DISCOURAGED = 5;
   /* This feature is blocked on this OS version. */
-  const long FEATURE_BLOCKED_OS_VERSION = 5;
+  const long FEATURE_BLOCKED_OS_VERSION = 6;
 
   /**
    * Ask about a feature, and return the status of that feature
    */
   long getFeatureStatus(in long aFeature);
 
   /*
    * Ask about a feature, return the minimum driver version required for it if its status is
--- a/widget/src/android/GfxInfo.cpp
+++ b/widget/src/android/GfxInfo.cpp
@@ -269,40 +269,40 @@ 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*
+const nsTArray<GfxDriverInfo>&
 GfxInfo::GetGfxDriverInfo()
 {
-  return &gDriverInfo[0];
+  // Nothing here yet.
+  //if (!mDriverInfo->Length()) {
+  //
+  //}
+  return *mDriverInfo;
 }
 
 nsresult
 GfxInfo::GetFeatureStatusImpl(PRInt32 aFeature, 
                               PRInt32 *aStatus, 
                               nsAString & aSuggestedDriverVersion,
-                              GfxDriverInfo* aDriverInfo /* = nsnull */, 
+                              const nsTArray<GfxDriverInfo>& aDriverInfo, 
                               OperatingSystem* aOS /* = nsnull */)
 {
-  PRInt32 status = nsIGfxInfo::FEATURE_NO_INFO;
+  PRInt32 status = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
 
   aSuggestedDriverVersion.SetIsVoid(true);
 
   // For now, we don't implement the downloaded blacklist.
-  if (aDriverInfo) {
-    *aStatus = status;
+  if (aDriverInfo.Length()) {
+    *aStatus = nsIGfxInfo::FEATURE_NO_INFO;
     return NS_OK;
   }
 
   OperatingSystem os = DRIVER_OS_ANDROID;
 
   if (aFeature == FEATURE_OPENGL_LAYERS) {
     if (!mSetCrashReportAnnotations) {
       AddOpenGLCrashReportAnnotations();
@@ -321,11 +321,17 @@ GfxInfo::GetFeatureStatusImpl(PRInt32 aF
     status = FEATURE_BLOCKED_DEVICE;
   }
 
   *aStatus = status;
   if (aOS)
     *aOS = os;
 
   // XXX disabled for now as this calls GetAdapterVendorID and friends, which currently crash on Android, see bug 700124
-  // return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, &os);
+  // FIXME: if this gets fixed, the line setting *aStatus must be removed
+#if 0
+  return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, &os);
+#else
+  if (status == nsIGfxInfo::FEATURE_STATUS_UNKNOWN)
+    *aStatus = nsIGfxInfo::FEATURE_NO_INFO;
+#endif
   return NS_OK;
 }
--- a/widget/src/android/GfxInfo.h
+++ b/widget/src/android/GfxInfo.h
@@ -78,19 +78,19 @@ public:
 
   virtual nsresult Init();
 
 protected:
 
   virtual nsresult GetFeatureStatusImpl(PRInt32 aFeature, 
                                         PRInt32 *aStatus, 
                                         nsAString & aSuggestedDriverVersion, 
-                                        GfxDriverInfo* aDriverInfo = nsnull,
+                                        const nsTArray<GfxDriverInfo>& aDriverInfo,
                                         OperatingSystem* aOS = nsnull);
-  virtual const GfxDriverInfo* GetGfxDriverInfo();
+  virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo();
 
 private:
 
   void     AddOpenGLCrashReportAnnotations();
   bool     mSetCrashReportAnnotations;
   nsString mRendererIDsString;
   nsString mAdapterRAMString;
 
--- a/widget/src/cocoa/GfxInfo.h
+++ b/widget/src/cocoa/GfxInfo.h
@@ -80,19 +80,19 @@ public:
 
   virtual nsresult Init();
 
 protected:
 
   virtual nsresult GetFeatureStatusImpl(PRInt32 aFeature, 
                                         PRInt32 *aStatus, 
                                         nsAString & aSuggestedDriverVersion, 
-                                        GfxDriverInfo* aDriverInfo = nsnull, 
+                                        const nsTArray<GfxDriverInfo>& aDriverInfo,
                                         OperatingSystem* aOS = nsnull);
-  virtual const GfxDriverInfo* GetGfxDriverInfo();
+  virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo();
 
 private:
 
   void GetDeviceInfo();
   void AddCrashReportAnnotations();
   nsString mRendererIDsString;
   nsString mAdapterRAMString;
 
--- a/widget/src/cocoa/GfxInfo.mm
+++ b/widget/src/cocoa/GfxInfo.mm
@@ -351,40 +351,31 @@ GfxInfo::AddCrashReportAnnotations()
   nsCAutoString note;
   /* AppendPrintf only supports 32 character strings, mrghh. */
   note.AppendPrintf("AdapterVendorID: %04x, ", vendorID);
   note.AppendPrintf("AdapterDeviceID: %04x", deviceID);
   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)
+// We don't support checking driver versions on Mac.
+#define IMPLEMENT_MAC_DRIVER_BLOCKLIST(os, vendor, device, features, blockOn) \
+  APPEND_TO_DRIVER_BLOCKLIST(os, vendor, device, features, blockOn,           \
+                             DRIVER_UNKNOWN_COMPARISON, V(0,0,0,0), "")
 
-  // Block all ATI cards from using MSAA, except for two devices that have
-  // special exceptions in the GetFeatureStatusImpl() function.
-  IMPLEMENT_MAC_DRIVER_BLOCKLIST(DRIVER_OS_ALL,
-    GfxDriverInfo::vendorATI, GfxDriverInfo::allDevices,
-    nsIGfxInfo::FEATURE_WEBGL_MSAA, nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION)
 
-  GfxDriverInfo()
-};
-
-const GfxDriverInfo*
+const nsTArray<GfxDriverInfo>&
 GfxInfo::GetGfxDriverInfo()
 {
-  return &gDriverInfo[0];
+  if (!mDriverInfo->Length()) {
+    IMPLEMENT_MAC_DRIVER_BLOCKLIST(DRIVER_OS_ALL,
+      GfxDriverInfo::vendorATI, GfxDriverInfo::allDevices,
+      nsIGfxInfo::FEATURE_WEBGL_MSAA, nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION);
+  }
+  return *mDriverInfo;
 }
 
 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;
@@ -396,24 +387,24 @@ OSXVersionToOperatingSystem(PRUint32 aOS
 
   return DRIVER_OS_UNKNOWN;
 }
 
 nsresult
 GfxInfo::GetFeatureStatusImpl(PRInt32 aFeature, 
                               PRInt32* aStatus,
                               nsAString& aSuggestedDriverVersion,
-                              GfxDriverInfo* aDriverInfo /* = nsnull */,
+                              const nsTArray<GfxDriverInfo>& aDriverInfo,
                               OperatingSystem* aOS /* = nsnull */)
 {
   NS_ENSURE_ARG_POINTER(aStatus);
 
   aSuggestedDriverVersion.SetIsVoid(true);
 
-  PRInt32 status = nsIGfxInfo::FEATURE_NO_INFO;
+  PRInt32 status = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
 
   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())
--- a/widget/src/windows/GfxInfo.cpp
+++ b/widget/src/windows/GfxInfo.cpp
@@ -789,128 +789,16 @@ GfxInfo::AddCrashReportAnnotations()
     note.AppendPrintf("AdapterDriverVersion2: ");
     note.Append(NS_LossyConvertUTF16toASCII(adapterDriverVersionString2));
   }
   CrashReporter::AppendAppNotesToCrashReport(note);
 
 #endif
 }
 
-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,
-    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,
-    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,
-    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,
-    GfxDriverInfo::vendorNVIDIA, (GfxDeviceFamily) deviceFamilyNvidiaBlockD3D9Layers,
-    nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
-    DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ),
-
-  /*
-   * AMD/ATI entries
-   */
-  GfxDriverInfo( DRIVER_OS_ALL,
-    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,
-    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,
-    GfxDriverInfo::vendorATI, GfxDriverInfo::allDevices,
-    nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
-    DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ),
-  GfxDriverInfo( DRIVER_OS_ALL,
-    GfxDriverInfo::vendorATI, GfxDriverInfo::allDevices,
-    nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
-    DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ),
-  GfxDriverInfo( DRIVER_OS_ALL,
-    GfxDriverInfo::vendorAMD, GfxDriverInfo::allDevices,
-    nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
-    DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ),
-  GfxDriverInfo( DRIVER_OS_ALL,
-    GfxDriverInfo::vendorAMD, GfxDriverInfo::allDevices,
-    nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
-    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,                                               \
-      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,   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,   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 */
-  GfxDriverInfo( DRIVER_OS_ALL,
-    GfxDriverInfo::vendorIntel, GfxDriverInfo::allDevices,
-    nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
-    DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ),
-  GfxDriverInfo( DRIVER_OS_ALL,
-    GfxDriverInfo::vendorIntel, GfxDriverInfo::allDevices,
-    nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
-    DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ),
-
-  GfxDriverInfo()
-};
-
 static OperatingSystem
 WindowsVersionToOperatingSystem(PRInt32 aWindowsVersion)
 {
   switch(aWindowsVersion) {
     case gfxWindowsPlatform::kWindows2000:
       return DRIVER_OS_WINDOWS_2000;
     case gfxWindowsPlatform::kWindowsXP:
       return DRIVER_OS_WINDOWS_XP;
@@ -921,65 +809,181 @@ WindowsVersionToOperatingSystem(PRInt32 
     case gfxWindowsPlatform::kWindows7:
       return DRIVER_OS_WINDOWS_7;
     case gfxWindowsPlatform::kWindowsUnknown:
     default:
       return DRIVER_OS_UNKNOWN;
     };
 }
 
-const GfxDriverInfo*
+const nsTArray<GfxDriverInfo>&
 GfxInfo::GetGfxDriverInfo()
 {
-  return &gDriverInfo[0];
+  if (!mDriverInfo->Length()) {
+     /*
+     * NVIDIA entries
+     */
+    APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_XP,
+      GfxDriverInfo::vendorNVIDIA, GfxDriverInfo::allDevices,
+      GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
+      DRIVER_LESS_THAN, V(6,14,12,5721), "257.21" );
+    APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_VISTA,
+      GfxDriverInfo::vendorNVIDIA, GfxDriverInfo::allDevices,
+      GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
+      DRIVER_LESS_THAN, V(8,17,12,5721), "257.21" );
+    APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_7,
+      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.
+     */
+    APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
+      GfxDriverInfo::vendorNVIDIA, (GfxDeviceFamily) GfxDriverInfo::GetDeviceFamily(DeviceFamily::NvidiaBlockD3D9Layers),
+      nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
+      DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
+
+    /*
+     * AMD/ATI entries
+     */
+    APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL,
+      GfxDriverInfo::vendorATI, GfxDriverInfo::allDevices,
+      GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
+      DRIVER_LESS_THAN, V(8,741,0,0), "10.6" );
+    APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL,
+      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
+     */
+    APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
+      GfxDriverInfo::vendorATI, GfxDriverInfo::allDevices,
+      nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
+      DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
+    APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
+      GfxDriverInfo::vendorATI, GfxDriverInfo::allDevices,
+      nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
+      DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
+    APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
+      GfxDriverInfo::vendorAMD, GfxDriverInfo::allDevices,
+      nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
+      DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
+    APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
+      GfxDriverInfo::vendorAMD, GfxDriverInfo::allDevices,
+      nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
+      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) \
+      APPEND_TO_DRIVER_BLOCKLIST2( winVer,                                               \
+        GfxDriverInfo::vendorIntel, (GfxDeviceFamily) GfxDriverInfo::GetDeviceFamily(devFamily),    \
+        GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,                     \
+        DRIVER_LESS_THAN, driverVer )
+
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, DeviceFamily::IntelGMA500,   V(6,14,11,1018));
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, DeviceFamily::IntelGMA900,   V(6,14,10,4764));
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, DeviceFamily::IntelGMA950,   V(6,14,10,4926));
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, DeviceFamily::IntelGMA3150,  V(6,14,10,5260));
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, DeviceFamily::IntelGMAX3000, V(6,14,10,5218));
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, DeviceFamily::IntelGMAX4500HD, V(6,14,10,5284));
+
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, DeviceFamily::IntelGMA500,   V(7,14,10,1006));
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, DeviceFamily::IntelGMA900,   GfxDriverInfo::allDriverVersions);
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, DeviceFamily::IntelGMA950,   V(7,14,10,1504));
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, DeviceFamily::IntelGMA3150,  V(7,14,10,2124));
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, DeviceFamily::IntelGMAX3000, V(7,15,10,1666));
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, DeviceFamily::IntelGMAX4500HD, V(8,15,10,2202));
+
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, DeviceFamily::IntelGMA500,   V(5,0,0,2026));
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, DeviceFamily::IntelGMA900,   GfxDriverInfo::allDriverVersions);
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, DeviceFamily::IntelGMA950,   V(8,15,10,1930));
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, DeviceFamily::IntelGMA3150,  V(8,14,10,2117));
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, DeviceFamily::IntelGMAX3000, V(8,15,10,1930));
+    IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, DeviceFamily::IntelGMAX4500HD, V(8,15,10,2202));
+
+     /* OpenGL on any Intel hardware is discouraged */
+    APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
+      GfxDriverInfo::vendorIntel, GfxDriverInfo::allDevices,
+      nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
+      DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
+    APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
+      GfxDriverInfo::vendorIntel, GfxDriverInfo::allDevices,
+      nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
+      DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
+  }
+  return *mDriverInfo;
 }
 
 nsresult
 GfxInfo::GetFeatureStatusImpl(PRInt32 aFeature, 
                               PRInt32 *aStatus, 
                               nsAString & aSuggestedDriverVersion, 
-                              GfxDriverInfo* aDriverInfo /* = nsnull */, 
+                              const nsTArray<GfxDriverInfo>& aDriverInfo,
                               OperatingSystem* aOS /* = nsnull */)
 {
-  *aStatus = nsIGfxInfo::FEATURE_NO_INFO;
   aSuggestedDriverVersion.SetIsVoid(true);
 
-  PRInt32 status = nsIGfxInfo::FEATURE_NO_INFO;
+  PRInt32 status = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
 
-  PRUint32 adapterVendor = 0;
+  PRUint32 adapterVendorID = 0;
   PRUint32 adapterDeviceID = 0;
   nsAutoString adapterDriverVersionString;
-  if (NS_FAILED(GetAdapterVendorID(&adapterVendor)) ||
+  if (NS_FAILED(GetAdapterVendorID(&adapterVendorID)) ||
       NS_FAILED(GetAdapterDeviceID(&adapterDeviceID)) ||
       NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString)))
   {
     return NS_ERROR_FAILURE;
   }
 
-  if (adapterVendor != GfxDriverInfo::vendorIntel &&
-      adapterVendor != GfxDriverInfo::vendorNVIDIA &&
-      adapterVendor != GfxDriverInfo::vendorAMD &&
-      adapterVendor != GfxDriverInfo::vendorATI &&
+  if (adapterVendorID != GfxDriverInfo::vendorIntel &&
+      adapterVendorID != GfxDriverInfo::vendorNVIDIA &&
+      adapterVendorID != GfxDriverInfo::vendorAMD &&
+      adapterVendorID != 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)
+      adapterVendorID != 0xabcd &&
+      adapterVendorID != 0xdcba &&
+      adapterVendorID != 0xabab &&
+      adapterVendorID != 0xdcdc)
   {
     *aStatus = FEATURE_BLOCKED_DEVICE;
     return NS_OK;
   }
 
   PRUint64 driverVersion;
   if (!ParseDriverVersion(adapterDriverVersionString, &driverVersion)) {
     return NS_ERROR_FAILURE;
   }
-  
+
+  // 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 (mWindowsVersion == gfxWindowsPlatform::kWindowsXP &&
+      adapterVendorID == GfxDriverInfo::vendorNVIDIA &&
+      adapterDeviceID == 0x0861 && // GeForce 9400
+      driverVersion == V(6,14,11,7756))
+  {
+    *aStatus = FEATURE_NO_INFO;
+    return NS_OK;
+  }
+
   if (aFeature == FEATURE_DIRECT3D_9_LAYERS &&
       mWindowsVersion < gfxWindowsPlatform::kWindowsXP)
   {
     *aStatus = FEATURE_BLOCKED_OS_VERSION;
     return NS_OK;
   }
 
   // ANGLE currently uses D3D10 <-> D3D9 interop, which crashes on Optimus
@@ -993,22 +997,16 @@ GfxInfo::GetFeatureStatusImpl(PRInt32 aF
 
   OperatingSystem os = WindowsVersionToOperatingSystem(mWindowsVersion);
 
   // Windows Server 2003 should be just like Windows XP for present purpose, but still has a different version number.
   // OTOH Windows Server 2008 R1 and R2 already have the same version numbers as Vista and Seven respectively
   if (os == DRIVER_OS_WINDOWS_SERVER_2003)
     os = DRIVER_OS_WINDOWS_XP;
 
-  const GfxDriverInfo *info;
-  if (aDriverInfo)
-    info = aDriverInfo;
-  else
-    info = &gDriverInfo[0];
-
   if (mHasDriverVersionMismatch) {
     if (aFeature == nsIGfxInfo::FEATURE_DIRECT3D_10_LAYERS ||
         aFeature == nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS ||
         aFeature == nsIGfxInfo::FEATURE_DIRECT2D)
     {
       *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
       return NS_OK;
     }
--- a/widget/src/windows/GfxInfo.h
+++ b/widget/src/windows/GfxInfo.h
@@ -87,19 +87,19 @@ public:
 
   virtual nsresult Init();
 
 protected:
 
   virtual nsresult GetFeatureStatusImpl(PRInt32 aFeature, 
                                         PRInt32 *aStatus, 
                                         nsAString & aSuggestedDriverVersion, 
-                                        GfxDriverInfo* aDriverInfo = nsnull, 
+                                        const nsTArray<GfxDriverInfo>& aDriverInfo, 
                                         OperatingSystem* aOS = nsnull);
-  virtual const GfxDriverInfo* GetGfxDriverInfo();
+  virtual const nsTArray<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
@@ -112,8 +112,136 @@ GfxDriverInfo::GfxDriverInfo(const GfxDr
   mDeleteDevices = aOrig.mDeleteDevices;
 }
 
 GfxDriverInfo::~GfxDriverInfo()
 {
   if (mDeleteDevices)
     delete[] mDevices;
 }
+
+const GfxDeviceFamily GfxDriverInfo::GetDeviceFamily(DeviceFamily id)
+{
+  switch (id) {
+    case IntelGMA500: {
+      static const PRUint32 intelGMA500[] = {
+        0x8108, /* IntelGMA500_1 */
+        0x8109, /* IntelGMA500_2 */
+        0
+      };
+      return (const GfxDeviceFamily) &intelGMA500[0];
+    }
+    case IntelGMA900: {
+      static const PRUint32 intelGMA900[] = {
+        0x2582, /* IntelGMA900_1 */
+        0x2782, /* IntelGMA900_2 */
+        0x2592, /* IntelGMA900_3 */
+        0x2792, /* IntelGMA900_4 */
+        0
+      };
+      return (const GfxDeviceFamily) &intelGMA900[0];
+    }
+    case IntelGMA950: {
+      static const PRUint32 intelGMA950[] = {
+        0x2772, /* Intel945G_1 */
+        0x2776, /* Intel945G_2 */
+        0x27A2, /* Intel945_1 */
+        0x27A6, /* Intel945_2 */
+        0x27AE, /* Intel945_3 */
+        0
+      };
+      return (const GfxDeviceFamily) &intelGMA950[0];
+    }
+    case IntelGMA3150: {
+      static const PRUint32 intelGMA3150[] = {
+        0xA001, /* IntelGMA3150_Nettop_1 */
+        0xA002, /* IntelGMA3150_Nettop_2 */
+        0xA011, /* IntelGMA3150_Netbook_1 */
+        0xA012, /* IntelGMA3150_Netbook_2 */
+        0
+      };
+      return (const GfxDeviceFamily) &intelGMA3150[0];
+    }
+    case IntelGMAX3000: {
+      static const PRUint32 intelGMAX3000[] = {
+        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
+      };
+      return (const GfxDeviceFamily) &intelGMAX3000[0];
+    }
+    case IntelGMAX4500HD: {
+      static const PRUint32 intelGMAX4500HD[] = {
+        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
+      };
+      return (const GfxDeviceFamily) &intelGMAX4500HD[0];
+    }
+    case NvidiaBlockD3D9Layers: {
+      // Glitches whilst scrolling (see bugs 612007, 644787, 645872)
+      static const PRUint32 nvidiaBlockD3D9Layers[] = {
+        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
+      };
+      return (const GfxDeviceFamily) &nvidiaBlockD3D9Layers[0];
+    }
+    default:
+      NS_WARNING("Invalid device family");
+  }
+
+  return nsnull;
+}
--- a/widget/src/xpwidgets/GfxDriverInfo.h
+++ b/widget/src/xpwidgets/GfxDriverInfo.h
@@ -38,16 +38,21 @@
 #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)
 
+#define APPEND_TO_DRIVER_BLOCKLIST(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, suggestedVersion) \
+    mDriverInfo->AppendElement(GfxDriverInfo(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion, suggestedVersion))
+#define APPEND_TO_DRIVER_BLOCKLIST2(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion) \
+    mDriverInfo->AppendElement(GfxDriverInfo(os, vendor, devices, feature, featureStatus, driverComparator, driverVersion))
+
 namespace mozilla {
 namespace widget {
 
 enum OperatingSystem {
   DRIVER_OS_UNKNOWN = 0,
   DRIVER_OS_WINDOWS_2000,
   DRIVER_OS_WINDOWS_XP,
   DRIVER_OS_WINDOWS_SERVER_2003,
@@ -69,122 +74,28 @@ enum VersionComparisonOp {
   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
+enum DeviceFamily {
+  IntelGMA500,
+  IntelGMA900,
+  IntelGMA950,
+  IntelGMA3150,
+  IntelGMAX3000,
+  IntelGMAX4500HD,
+  NvidiaBlockD3D9Layers
 };
 
 /* A zero-terminated array of devices to match, or all devices */
-typedef PRUint32 *GfxDeviceFamily;
+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,
                 PRInt32 feature, PRInt32 featureStatus, VersionComparisonOp op,
                 PRUint64 driverVersion, const char *suggestedVersion = nsnull,
@@ -221,16 +132,18 @@ struct GfxDriverInfo
   static PRUint64 allDriverVersions;
 
   static PRUint32 vendorIntel;
   static PRUint32 vendorNVIDIA;
   static PRUint32 vendorAMD;
   static PRUint32 vendorATI;
 
   const char *mSuggestedVersion;
+
+  static const GfxDeviceFamily GetDeviceFamily(DeviceFamily id);
 };
 
 #define GFX_DRIVER_VERSION(a,b,c,d) \
   ((PRUint64(a)<<48) | (PRUint64(b)<<32) | (PRUint64(c)<<16) | PRUint64(d))
 
 inline bool
 ParseDriverVersion(nsAString& aVersion, PRUint64 *aNumericVersion)
 {
--- a/widget/src/xpwidgets/GfxInfoBase.cpp
+++ b/widget/src/xpwidgets/GfxInfoBase.cpp
@@ -43,30 +43,75 @@
 
 #include "GfxInfoWebGL.h"
 #include "GfxDriverInfo.h"
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 #include "nsAutoPtr.h"
 #include "nsString.h"
 #include "mozilla/Services.h"
+#include "mozilla/Observer.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
 #include "nsTArray.h"
 #include "mozilla/Preferences.h"
 
 #if defined(MOZ_CRASHREPORTER)
 #include "nsExceptionHandler.h"
 #endif
 
+using namespace mozilla::widget;
 using namespace mozilla;
 
+nsTArray<GfxDriverInfo>* GfxInfoBase::mDriverInfo;
+bool GfxInfoBase::mDriverInfoObserverInitialized;
+
+// Observes for shutdown so that the child GfxDriverInfo list is freed.
+class ShutdownObserver : public nsIObserver
+{
+public:
+  ShutdownObserver() {}
+  virtual ~ShutdownObserver() {}
+
+  NS_DECL_ISUPPORTS
+
+  NS_IMETHOD Observe(nsISupports *subject, const char *aTopic,
+                     const PRUnichar *aData)
+  {
+    MOZ_ASSERT(strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0);
+    if (GfxInfoBase::mDriverInfo) {
+      delete GfxInfoBase::mDriverInfo;
+      GfxInfoBase::mDriverInfo = nsnull;
+    }
+    return NS_OK;
+  }
+};
+
+NS_IMPL_ISUPPORTS1(ShutdownObserver, nsIObserver);
+
+void InitGfxDriverInfoShutdownObserver()
+{
+  if (GfxInfoBase::mDriverInfoObserverInitialized)
+    return;
+
+  GfxInfoBase::mDriverInfoObserverInitialized = true;
+
+  nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
+  if (!observerService) {
+    NS_WARNING("Could not get observer service!");
+    return;
+  }
+
+  ShutdownObserver *obs = new ShutdownObserver();
+  observerService->AddObserver(obs, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
+}
+
 extern "C" {
   void StoreSpline(int ax, int ay, int bx, int by, int cx, int cy, int dx, int dy);
   void CrashSpline(double tolerance, int ax, int ay, int bx, int by, int cx, int cy, int dx, int dy);
 }
 
 static int crash_ax;
 static int crash_ay;
 static int crash_bx;
@@ -333,16 +378,18 @@ BlacklistFeatureStatusToGfxFeatureStatus
     return nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
   else if (aStatus == NS_LITERAL_STRING("BLOCKED_DEVICE"))
     return nsIGfxInfo::FEATURE_BLOCKED_DEVICE;
   else if (aStatus == NS_LITERAL_STRING("DISCOURAGED"))
     return nsIGfxInfo::FEATURE_DISCOURAGED;
   else if (aStatus == NS_LITERAL_STRING("BLOCKED_OS_VERSION"))
     return nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION;
 
+  // Do not allow it to set STATUS_UNKNOWN.
+
   return nsIGfxInfo::FEATURE_NO_INFO;
 }
 
 static VersionComparisonOp
 BlacklistComparatorToComparisonOp(const nsAString& op)
 {
   if (op == NS_LITERAL_STRING("LESS_THAN"))
     return DRIVER_LESS_THAN;
@@ -553,45 +600,162 @@ 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);
+  nsTArray<GfxDriverInfo> driverInfo;
+  return GetFeatureStatusImpl(aFeature, aStatus, version, driverInfo);
+}
+
+PRInt32
+GfxInfoBase::FindBlocklistedDeviceInList(const nsTArray<GfxDriverInfo>& info,
+                                         nsAString& aSuggestedVersion,
+                                         PRInt32 aFeature,
+                                         OperatingSystem os)
+{
+  PRInt32 status = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
+
+  PRUint32 adapterVendorID = 0;
+  PRUint32 adapterDeviceID = 0;
+  nsAutoString adapterDriverVersionString;
+  if (NS_FAILED(GetAdapterVendorID(&adapterVendorID)) ||
+      NS_FAILED(GetAdapterDeviceID(&adapterDeviceID)) ||
+      NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString)))
+  {
+    return NS_OK;
+  }
+
+  PRUint64 driverVersion;
+  ParseDriverVersion(adapterDriverVersionString, &driverVersion);
+
+  PRUint32 i = 0;
+  for (; i < info.Length(); i++) {
+    if (info[i].mOperatingSystem != DRIVER_OS_ALL &&
+        info[i].mOperatingSystem != os)
+    {
+      continue;
+    }
+
+    if (info[i].mAdapterVendor != GfxDriverInfo::allAdapterVendors &&
+        info[i].mAdapterVendor != adapterVendorID) {
+      continue;
+    }
+
+    if (info[i].mDevices != GfxDriverInfo::allDevices) {
+        bool deviceMatches = false;
+        for (const PRUint32 *devices = info[i].mDevices; *devices; ++devices) {
+            if (*devices == adapterDeviceID) {
+                deviceMatches = true;
+                break;
+            }
+        }
+
+        if (!deviceMatches) {
+            continue;
+        }
+    }
+
+    bool match = false;
+
+#if !defined(XP_MACOSX)
+    switch (info[i].mComparisonOp) {
+    case DRIVER_LESS_THAN:
+      match = driverVersion < info[i].mDriverVersion;
+      break;
+    case DRIVER_LESS_THAN_OR_EQUAL:
+      match = driverVersion <= info[i].mDriverVersion;
+      break;
+    case DRIVER_GREATER_THAN:
+      match = driverVersion > info[i].mDriverVersion;
+      break;
+    case DRIVER_GREATER_THAN_OR_EQUAL:
+      match = driverVersion >= info[i].mDriverVersion;
+      break;
+    case DRIVER_EQUAL:
+      match = driverVersion == info[i].mDriverVersion;
+      break;
+    case DRIVER_NOT_EQUAL:
+      match = driverVersion != info[i].mDriverVersion;
+      break;
+    case DRIVER_BETWEEN_EXCLUSIVE:
+      match = driverVersion > info[i].mDriverVersion && driverVersion < info[i].mDriverVersionMax;
+      break;
+    case DRIVER_BETWEEN_INCLUSIVE:
+      match = driverVersion >= info[i].mDriverVersion && driverVersion <= info[i].mDriverVersionMax;
+      break;
+    case DRIVER_BETWEEN_INCLUSIVE_START:
+      match = driverVersion >= info[i].mDriverVersion && driverVersion < info[i].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[i].mFeature == GfxDriverInfo::allFeatures ||
+          info[i].mFeature == aFeature)
+      {
+        status = info[i].mFeatureStatus;
+        break;
+      }
+    }
+  }
+
+  // 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[i].mSuggestedVersion) {
+        aSuggestedVersion.AppendPrintf("%s", info[i].mSuggestedVersion);
+    } else if (info[i].mComparisonOp == DRIVER_LESS_THAN &&
+               info[i].mDriverVersion != GfxDriverInfo::allDriverVersions)
+    {
+        aSuggestedVersion.AppendPrintf("%lld.%lld.%lld.%lld",
+                                      (info[i].mDriverVersion & 0xffff000000000000) >> 48,
+                                      (info[i].mDriverVersion & 0x0000ffff00000000) >> 32,
+                                      (info[i].mDriverVersion & 0x00000000ffff0000) >> 16,
+                                      (info[i].mDriverVersion & 0x000000000000ffff));
+    }
+  }
+#endif
+
+  return status;
 }
 
 nsresult
 GfxInfoBase::GetFeatureStatusImpl(PRInt32 aFeature,
                                   PRInt32* aStatus,
-                                  nsAString& aVersion,
-                                  GfxDriverInfo* aDriverInfo /* = nsnull */,
+                                  nsAString& aSuggestedVersion,
+                                  const nsTArray<GfxDriverInfo>& aDriverInfo,
                                   OperatingSystem* aOS /* = nsnull */)
 {
-  if (*aStatus != nsIGfxInfo::FEATURE_NO_INFO) {
+  if (*aStatus != nsIGfxInfo::FEATURE_STATUS_UNKNOWN) {
     // Terminate now with the status determined by the derived type (OS-specific
     // code).
     return NS_OK;
   }
 
+  // If an operating system was provided by the derived GetFeatureStatusImpl,
+  // grab it here. Otherwise, the OS is unknown.
   OperatingSystem os = DRIVER_OS_UNKNOWN;
   if (aOS)
     os = *aOS;
 
   PRUint32 adapterVendorID = 0;
   PRUint32 adapterDeviceID = 0;
   nsAutoString adapterDriverVersionString;
   if (NS_FAILED(GetAdapterVendorID(&adapterVendorID)) ||
@@ -599,163 +763,51 @@ GfxInfoBase::GetFeatureStatusImpl(PRInt3
       NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString)))
   {
     return NS_OK;
   }
 
   PRUint64 driverVersion;
   ParseDriverVersion(adapterDriverVersionString, &driverVersion);
 
-  // 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;
+  // Check if the device is blocked from the downloaded blocklist. If not, check
+  // the static list after that. This order is used so that we can later escape
+  // out of static blocks (i.e. if we were wrong or something was patched, we
+  // can back out our static block without doing a release).
+  InitGfxDriverInfoShutdownObserver();
+  if (!mDriverInfo)
+    mDriverInfo = new nsTArray<GfxDriverInfo>();
+  PRInt32 status = FindBlocklistedDeviceInList(aDriverInfo, aSuggestedVersion, aFeature, os);
+  if (status == nsIGfxInfo::FEATURE_STATUS_UNKNOWN) {
+    status = FindBlocklistedDeviceInList(GetGfxDriverInfo(), aSuggestedVersion, aFeature, os);
   }
 
-  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++;
+  // It's now done being processed. It's safe to set the status to NO_INFO.
+  if (status == nsIGfxInfo::FEATURE_STATUS_UNKNOWN) {
+    *aStatus = nsIGfxInfo::FEATURE_NO_INFO;
+  } else {
+    *aStatus = status;
   }
- 
-  *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;
   }
 
   PRInt32 status;
-  return GetFeatureStatusImpl(aFeature, &status, aVersion);
+  nsTArray<GfxDriverInfo> driverInfo;
+  return GetFeatureStatusImpl(aFeature, &status, aVersion, driverInfo);
 }
 
 
 NS_IMETHODIMP
 GfxInfoBase::GetWebGLParameter(const nsAString& aParam,
                                nsAString& aResult NS_OUTPARAM)
 {
   return GfxInfoWebGL::GetWebGLParameter(aParam, aResult);
@@ -771,31 +823,27 @@ GfxInfoBase::EvaluateDownloadedBlacklist
     nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS,
     nsIGfxInfo::FEATURE_OPENGL_LAYERS,
     nsIGfxInfo::FEATURE_WEBGL_OPENGL,
     nsIGfxInfo::FEATURE_WEBGL_ANGLE,
     nsIGfxInfo::FEATURE_WEBGL_MSAA,
     0
   };
 
-  // GetFeatureStatusImpl wants a zero-GfxDriverInfo terminated array. So, we
-  // append that to our list.
-  aDriverInfo.AppendElement(GfxDriverInfo());
-
   // For every feature we know about, we evaluate whether this blacklist has a
   // non-NO_INFO status. If it does, we set the pref we evaluate in
   // GetFeatureStatus above, so we don't need to hold on to this blacklist
   // anywhere permanent.
   int i = 0;
   while (features[i]) {
     PRInt32 status;
     nsAutoString suggestedVersion;
     if (NS_SUCCEEDED(GetFeatureStatusImpl(features[i], &status,
                                           suggestedVersion,
-                                          aDriverInfo.Elements()))) {
+                                          aDriverInfo))) {
       switch (status) {
         default:
         case nsIGfxInfo::FEATURE_NO_INFO:
           RemovePrefForFeature(features[i]);
           break;
 
         case nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION:
           if (!suggestedVersion.IsEmpty()) {
--- a/widget/src/xpwidgets/GfxInfoBase.h
+++ b/widget/src/xpwidgets/GfxInfoBase.h
@@ -82,35 +82,41 @@ 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() { }
 
   static void AddCollector(GfxInfoCollectorBase* collector);
   static void RemoveCollector(GfxInfoCollectorBase* collector);
 
+  static nsTArray<GfxDriverInfo>* mDriverInfo;
+  static bool mDriverInfoObserverInitialized;
 
 protected:
 
   virtual nsresult GetFeatureStatusImpl(PRInt32 aFeature, PRInt32* aStatus,
                                         nsAString& aSuggestedDriverVersion,
-                                        GfxDriverInfo* aDriverInfo = nsnull,
+                                        const nsTArray<GfxDriverInfo>& aDriverInfo,
                                         OperatingSystem* aOS = nsnull);
 
+  // Gets the driver info table. Used by GfxInfoBase to check for general cases
+  // (while subclasses check for more specific ones).
+  virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() = 0;
+
 private:
+  virtual PRInt32 FindBlocklistedDeviceInList(const nsTArray<GfxDriverInfo>& aDriverInfo,
+                                              nsAString& aSuggestedVersion,
+                                              PRInt32 aFeature,
+                                              OperatingSystem os);
 
   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,39 +241,40 @@ 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*
+const nsTArray<GfxDriverInfo>&
 GfxInfo::GetGfxDriverInfo()
 {
-  return &gDriverInfo[0];
+  // Nothing here yet.
+  //if (!mDriverInfo->Length()) {
+  //
+  //}
+  return *mDriverInfo;
 }
 
 nsresult
 GfxInfo::GetFeatureStatusImpl(PRInt32 aFeature, 
                               PRInt32 *aStatus, 
                               nsAString & aSuggestedDriverVersion, 
-                              GfxDriverInfo* aDriverInfo /* = nsnull */, 
+                              const nsTArray<GfxDriverInfo>& aDriverInfo, 
                               OperatingSystem* aOS /* = nsnull */)
 
 {
     GetData();
-    *aStatus = nsIGfxInfo::FEATURE_NO_INFO;
+    *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
     aSuggestedDriverVersion.SetIsVoid(true);
 
 #ifdef MOZ_PLATFORM_MAEMO
+    *aStatus = nsIGfxInfo::FEATURE_NO_INFO;
     // 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) {
@@ -286,16 +287,17 @@ GfxInfo::GetFeatureStatusImpl(PRInt32 aF
     // 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"))
     {
+        *aStatus = nsIGfxInfo::FEATURE_NO_INFO;
         return NS_OK;
     }
 
     if (mIsMesa) {
         if (version(mMajorVersion, mMinorVersion, mRevisionVersion) < version(7,10,3)) {
             *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
             aSuggestedDriverVersion.AssignLiteral("Mesa 7.10.3");
         }
--- a/widget/src/xpwidgets/GfxInfoX11.h
+++ b/widget/src/xpwidgets/GfxInfoX11.h
@@ -79,19 +79,19 @@ public:
   
   NS_IMETHOD_(void) GetData();
 
 protected:
 
   virtual nsresult GetFeatureStatusImpl(PRInt32 aFeature, 
                                         PRInt32 *aStatus, 
                                         nsAString & aSuggestedDriverVersion, 
-                                        GfxDriverInfo* aDriverInfo = nsnull, 
+                                        const nsTArray<GfxDriverInfo>& aDriverInfo, 
                                         OperatingSystem* aOS = nsnull);
-  virtual const GfxDriverInfo* GetGfxDriverInfo();
+  virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo();
 
 private:
   nsCString mVendor;
   nsCString mRenderer;
   nsCString mVersion;
   nsCString mAdapterDescription;
   bool mIsMesa, mIsNVIDIA, mIsFGLRX;
   bool mHasTextureFromPixmap;