Bug 1286653 - Re-run blacklist on DXGI adapter used for device creation r=BenWa,dvander
☠☠ backed out by e129019c9d4e ☠ ☠
authoreyim <eyim@mozilla.com>
Thu, 11 Aug 2016 18:20:21 -0400
changeset 309408 9ba0dd5271fed0e9ec56cbb5ec4528cdb7885651
parent 309407 e225f606ad70067ab50cff51879b59be4e98659e
child 309409 aeadc64780e1967536a789d260b76d4cffd1375b
push id80592
push userkwierso@gmail.com
push dateMon, 15 Aug 2016 21:54:03 +0000
treeherdermozilla-inbound@16b35e0c7644 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBenWa, dvander
bugs1286653
milestone51.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 1286653 - Re-run blacklist on DXGI adapter used for device creation r=BenWa,dvander MozReview-Commit-ID: 9QV8QFu5WYR
gfx/thebes/DeviceManagerD3D11.cpp
widget/GfxInfoBase.cpp
widget/GfxInfoBase.h
widget/nsIGfxInfo.idl
widget/windows/GfxInfo.cpp
widget/windows/GfxInfo.h
--- a/gfx/thebes/DeviceManagerD3D11.cpp
+++ b/gfx/thebes/DeviceManagerD3D11.cpp
@@ -87,16 +87,45 @@ DeviceManagerD3D11::CreateDevices()
   // Check if a failure was injected for testing.
   if (gfxPrefs::DeviceFailForTesting()) {
     d3d11.SetFailed(FeatureStatus::Failed, "Direct3D11 device failure simulated by preference",
                     NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_SIM"));
     return;
   }
 
   if (XRE_IsParentProcess()) {
+    // reset the primary adapter information, given the adapter from device creation
+    RefPtr<IDXGIAdapter1> adapter = GetDXGIAdapter();
+    DXGI_ADAPTER_DESC adapterDesc;
+    nsString vendorID;
+    nsString deviceID;
+
+    if (!adapter) { // no dxgiadapter
+      d3d11.SetFailed(FeatureStatus::Failed, "No DXGI adapter found",
+                      NS_LITERAL_CSTRING("FEATURE_FAILURE_D3D11_DXGIADAPTER"));
+      return;
+    }
+
+    adapter->GetDesc(&adapterDesc);
+
+    vendorID.AppendPrintf("0x%04x", adapterDesc.VendorId);
+    deviceID.AppendPrintf("0x%04x", adapterDesc.DeviceId);
+
+    if (nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo()) {
+      gfxInfo->Reset(vendorID, deviceID);
+
+      // check device to see if blacklisted after device creation successful
+      nsCString message;
+      nsCString failureId;
+      if (!gfxPlatform::IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, &message, failureId)) {
+        d3d11.Disable(FeatureStatus::Blacklisted, message.get(), failureId);
+        return;
+      }
+    }
+
     if (!gfxConfig::UseFallback(Fallback::USE_D3D11_WARP_COMPOSITOR)) {
       AttemptD3D11DeviceCreation(d3d11);
       if (d3d11.GetValue() == FeatureStatus::CrashedInHandler) {
         return;
       }
 
       // If we failed to get a device, but WARP is allowed and might work,
       // re-enable D3D11 and switch to WARP.
--- a/widget/GfxInfoBase.cpp
+++ b/widget/GfxInfoBase.cpp
@@ -571,16 +571,23 @@ GfxInfoBase::Init()
   if (os) {
     os->AddObserver(this, "blocklist-data-gfxItems", true);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+GfxInfoBase::Reset(const nsAString& aVendorID, const nsAString& aDeviceID)
+{
+  NS_ABORT();
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 GfxInfoBase::GetFeatureStatus(int32_t aFeature, nsACString& aFailureId, int32_t* aStatus)
 {
   int32_t blocklistAll = gfxPrefs::BlocklistAll();
   if (blocklistAll > 0) {
     gfxCriticalErrorOnce(gfxCriticalError::DefaultOptions(false)) << "Forcing blocklisting all features";
     *aStatus = FEATURE_BLOCKED_DEVICE;
     aFailureId = "FEATURE_FAILURE_BLOCK_ALL";
     return NS_OK;
--- a/widget/GfxInfoBase.h
+++ b/widget/GfxInfoBase.h
@@ -54,16 +54,18 @@ public:
   NS_IMETHOD GetMonitors(JSContext* cx, JS::MutableHandleValue _retval) override;
   NS_IMETHOD GetFailures(uint32_t *failureCount, int32_t** indices, char ***failures) override;
   NS_IMETHOD_(void) LogFailure(const nsACString &failure) override;
   NS_IMETHOD GetInfo(JSContext*, JS::MutableHandle<JS::Value>) override;
   NS_IMETHOD GetFeatures(JSContext*, JS::MutableHandle<JS::Value>) override;
   NS_IMETHOD GetFeatureLog(JSContext*, JS::MutableHandle<JS::Value>) override;
   NS_IMETHOD GetActiveCrashGuards(JSContext*, JS::MutableHandle<JS::Value>) override;
 
+  NS_IMETHOD Reset(const nsAString& aVendorID, const nsAString& aDeviceID) override;
+
   // Initialization function. If you override this, you must call this class's
   // 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();
--- a/widget/nsIGfxInfo.idl
+++ b/widget/nsIGfxInfo.idl
@@ -151,16 +151,22 @@ interface nsIGfxInfo : nsISupports
    * "shading_language_version", "extensions".  These return info from
    * underlying GL impl that's used to implement WebGL.
    */
   DOMString getWebGLParameter(in DOMString aParam);
 
   // only useful on X11
   [noscript, notxpcom] void GetData();
 
+  /**
+   * At startup we sometimes have to make a guess what device we're going to be
+   * using. We can reset this once we've gotten an exact device.
+   */
+  [noscript] void Reset (in AString aVendorID, in AString aDeviceID);
+
   [implicit_jscontext]
   jsval getInfo();
 
   // Return an object describing all features that have been configured:
   //
   //   "features": [
   //     // For each feature:
   //     {
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -294,124 +294,27 @@ GfxInfo::Init()
   while (EnumDisplayDevicesW(nullptr, deviceIndex, &displayDevice, 0)) {
     if (displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
       mDeviceKeyDebug = NS_LITERAL_STRING("NullSearch");
       break;
     }
     deviceIndex++;
   }
 
-  // make sure the string is nullptr terminated
-  if (wcsnlen(displayDevice.DeviceKey, ArrayLength(displayDevice.DeviceKey))
-      == ArrayLength(displayDevice.DeviceKey)) {
-    // we did not find a nullptr
-    return rv;
-  }
-
-  mDeviceKeyDebug = displayDevice.DeviceKey;
-
-  /* DeviceKey is "reserved" according to MSDN so we'll be careful with it */
-  /* check that DeviceKey begins with DEVICE_KEY_PREFIX */
-  /* some systems have a DeviceKey starting with \REGISTRY\Machine\ so we need to compare case insenstively */
-  if (_wcsnicmp(displayDevice.DeviceKey, DEVICE_KEY_PREFIX, ArrayLength(DEVICE_KEY_PREFIX)-1) != 0)
+  rv = UpdatePrimaryDeviceInfo(displayDevice);
+  if (rv != NS_OK) {
     return rv;
-
-  // chop off DEVICE_KEY_PREFIX
-  mDeviceKey = displayDevice.DeviceKey + ArrayLength(DEVICE_KEY_PREFIX)-1;
-
-  mDeviceID = displayDevice.DeviceID;
-  mDeviceString = displayDevice.DeviceString;
-
-  // On Windows 8 and Server 2012 hosts, we want to not block RDP
-  // sessions from attempting hardware acceleration.  RemoteFX
-  // provides features and functionaltiy that can give a good D3D10 +
-  // D2D + DirectWrite experience emulated via a software GPU.
-  //
-  // Unfortunately, the Device ID is nullptr, and we can't enumerate
-  // it using the setup infrastructure (SetupDiGetClassDevsW below
-  // will return INVALID_HANDLE_VALUE).
-  if (mWindowsVersion == kWindows8 &&
-      mDeviceID.Length() == 0 &&
-      mDeviceString.EqualsLiteral("RDPUDD Chained DD"))
-  {
-    WCHAR sysdir[255];
-    UINT len = GetSystemDirectory(sysdir, sizeof(sysdir));
-    if (len < sizeof(sysdir)) {
-      nsString rdpudd(sysdir);
-      rdpudd.AppendLiteral("\\rdpudd.dll");
-      gfxWindowsPlatform::GetDLLVersion(rdpudd.BeginReading(), mDriverVersion);
-      mDriverDate.AssignLiteral("01-01-1970");
-
-      // 0x1414 is Microsoft; 0xfefe is an invented (and unused) code
-      mDeviceID.AssignLiteral("PCI\\VEN_1414&DEV_FEFE&SUBSYS_00000000");
-    }
-  }
-
-  /* create a device information set composed of the current display device */
-  HDEVINFO devinfo = SetupDiGetClassDevsW(nullptr, mDeviceID.get(), nullptr,
-                                          DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
-
-  if (devinfo != INVALID_HANDLE_VALUE) {
-    HKEY key;
-    LONG result;
-    WCHAR value[255];
-    DWORD dwcbData;
-    SP_DEVINFO_DATA devinfoData;
-    DWORD memberIndex = 0;
-
-    devinfoData.cbSize = sizeof(devinfoData);
-    NS_NAMED_LITERAL_STRING(driverKeyPre, "System\\CurrentControlSet\\Control\\Class\\");
-    /* enumerate device information elements in the device information set */
-    while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) {
-      /* get a string that identifies the device's driver key */
-      if (SetupDiGetDeviceRegistryPropertyW(devinfo,
-                                            &devinfoData,
-                                            SPDRP_DRIVER,
-                                            nullptr,
-                                            (PBYTE)value,
-                                            sizeof(value),
-                                            nullptr)) {
-        nsAutoString driverKey(driverKeyPre);
-        driverKey += value;
-        result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey.get(), 0, KEY_QUERY_VALUE, &key);
-        if (result == ERROR_SUCCESS) {
-          /* we've found the driver we're looking for */
-          dwcbData = sizeof(value);
-          result = RegQueryValueExW(key, L"DriverVersion", nullptr, nullptr,
-                                    (LPBYTE)value, &dwcbData);
-          if (result == ERROR_SUCCESS) {
-            mDriverVersion = value;
-          } else {
-            // If the entry wasn't found, assume the worst (0.0.0.0).
-            mDriverVersion.AssignLiteral("0.0.0.0");
-          }
-          dwcbData = sizeof(value);
-          result = RegQueryValueExW(key, L"DriverDate", nullptr, nullptr,
-                                    (LPBYTE)value, &dwcbData);
-          if (result == ERROR_SUCCESS) {
-            mDriverDate = value;
-          } else {
-            // Again, assume the worst
-            mDriverDate.AssignLiteral("01-01-1970");
-          }
-          RegCloseKey(key);
-          break;
-        }
-      }
-    }
-
-    SetupDiDestroyDeviceInfoList(devinfo);
   }
 
   mAdapterVendorID.AppendPrintf("0x%04x", ParseIDFromDeviceID(mDeviceID, "VEN_", 4));
   mAdapterDeviceID.AppendPrintf("0x%04x", ParseIDFromDeviceID(mDeviceID, "&DEV_", 4));
   mAdapterSubsysID.AppendPrintf("%08x", ParseIDFromDeviceID(mDeviceID,  "&SUBSYS_", 8));
 
   // We now check for second display adapter.
-
+  HDEVINFO devinfo;
   // Device interface class for display adapters.
   CLSID GUID_DISPLAY_DEVICE_ARRIVAL;
   HRESULT hresult = CLSIDFromString(L"{1CA05180-A699-450A-9A0C-DE4FBE3DDD89}",
                                &GUID_DISPLAY_DEVICE_ARRIVAL);
   if (hresult == NOERROR) {
     devinfo = SetupDiGetClassDevsW(&GUID_DISPLAY_DEVICE_ARRIVAL,
                                    nullptr, nullptr,
                                    DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
@@ -513,16 +416,193 @@ GfxInfo::Init()
           }
         }
       }
 
       SetupDiDestroyDeviceInfoList(devinfo);
     }
   }
 
+  CheckAndUpdateDriverInfo();
+
+  AddCrashReportAnnotations();
+
+  return rv;
+}
+
+nsresult
+GfxInfo::Reset(const nsAString& aVendorID, const nsAString& aDeviceID)
+{
+  nsresult rv = NS_OK;
+  if (aVendorID.IsEmpty() || aDeviceID.IsEmpty()) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+
+  DISPLAY_DEVICEW displayDevice;
+  displayDevice.cb = sizeof(displayDevice);
+  int deviceIndex = 0;
+
+  nsString tempDeviceID;
+  nsString tempAdapterVendorID;
+  nsString tempAdapterDeviceID;
+  nsString tempAdapterSubsysID;
+
+  while (EnumDisplayDevicesW(nullptr, deviceIndex, &displayDevice, 0)) {
+    // reset these strings due to append later
+    tempAdapterVendorID = NS_LITERAL_STRING("");
+    tempAdapterDeviceID = NS_LITERAL_STRING("");
+    tempAdapterSubsysID = NS_LITERAL_STRING("");
+
+    tempDeviceID = displayDevice.DeviceID;
+    tempAdapterVendorID.AppendPrintf("0x%04x", ParseIDFromDeviceID(tempDeviceID, "VEN_", 4));
+    tempAdapterDeviceID.AppendPrintf("0x%04x", ParseIDFromDeviceID(tempDeviceID, "&DEV_", 4));
+    tempAdapterSubsysID.AppendPrintf("%08x", ParseIDFromDeviceID(tempDeviceID,  "&SUBSYS_", 8));
+
+    // look for device that has the same vendor and device id as given
+    if (mAdapterVendorID.Equals(aVendorID) && mAdapterDeviceID.Equals(aDeviceID)){
+      break;
+    }
+
+    deviceIndex++;
+  }
+
+  if (tempAdapterVendorID.Equals(aVendorID) && tempAdapterDeviceID.Equals(aDeviceID)) {
+    mDeviceID = tempDeviceID;
+    mAdapterVendorID = tempAdapterVendorID;
+    mAdapterDeviceID = tempAdapterDeviceID;
+    mAdapterSubsysID = tempAdapterSubsysID;
+  } else { // vendorid and deviceid given cannot be found
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  rv = UpdatePrimaryDeviceInfo(displayDevice);
+  if (rv != NS_OK) {
+    return rv;
+  }
+
+  CheckAndUpdateDriverInfo();
+
+  AddCrashReportAnnotations();
+
+  return rv;
+}
+
+nsresult
+GfxInfo::UpdatePrimaryDeviceInfo(DISPLAY_DEVICEW &displayDevice)
+{
+  nsresult rv = NS_ERROR_FAILURE;
+  // make sure the string is nullptr terminated
+  if (wcsnlen(displayDevice.DeviceKey, ArrayLength(displayDevice.DeviceKey))
+      == ArrayLength(displayDevice.DeviceKey)) {
+    // we did not find a nullptr
+    return rv;
+  }
+
+  mDeviceKeyDebug = displayDevice.DeviceKey;
+
+  /* DeviceKey is "reserved" according to MSDN so we'll be careful with it */
+  /* check that DeviceKey begins with DEVICE_KEY_PREFIX */
+  /* some systems have a DeviceKey starting with \REGISTRY\Machine\ so we need to compare case insenstively */
+  if (_wcsnicmp(displayDevice.DeviceKey, DEVICE_KEY_PREFIX, ArrayLength(DEVICE_KEY_PREFIX)-1) != 0)
+    return rv;
+
+  // chop off DEVICE_KEY_PREFIX
+  mDeviceKey = displayDevice.DeviceKey + ArrayLength(DEVICE_KEY_PREFIX)-1;
+
+  mDeviceID = displayDevice.DeviceID;
+  mDeviceString = displayDevice.DeviceString;
+
+  // On Windows 8 and Server 2012 hosts, we want to not block RDP
+  // sessions from attempting hardware acceleration.  RemoteFX
+  // provides features and functionaltiy that can give a good D3D10 +
+  // D2D + DirectWrite experience emulated via a software GPU.
+  //
+  // Unfortunately, the Device ID is nullptr, and we can't enumerate
+  // it using the setup infrastructure (SetupDiGetClassDevsW below
+  // will return INVALID_HANDLE_VALUE).
+  if (mWindowsVersion == kWindows8 &&
+      mDeviceID.Length() == 0 &&
+      mDeviceString.EqualsLiteral("RDPUDD Chained DD"))
+  {
+    WCHAR sysdir[255];
+    UINT len = GetSystemDirectory(sysdir, sizeof(sysdir));
+    if (len < sizeof(sysdir)) {
+      nsString rdpudd(sysdir);
+      rdpudd.AppendLiteral("\\rdpudd.dll");
+      gfxWindowsPlatform::GetDLLVersion(rdpudd.BeginReading(), mDriverVersion);
+      mDriverDate.AssignLiteral("01-01-1970");
+
+      // 0x1414 is Microsoft; 0xfefe is an invented (and unused) code
+      mDeviceID.AssignLiteral("PCI\\VEN_1414&DEV_FEFE&SUBSYS_00000000");
+    }
+  }
+
+  /* create a device information set composed of the current display device */
+  HDEVINFO devinfo = SetupDiGetClassDevsW(nullptr, mDeviceID.get(), nullptr,
+                                          DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
+
+  if (devinfo != INVALID_HANDLE_VALUE) {
+    HKEY key;
+    LONG result;
+    WCHAR value[255];
+    DWORD dwcbData;
+    SP_DEVINFO_DATA devinfoData;
+    DWORD memberIndex = 0;
+
+    devinfoData.cbSize = sizeof(devinfoData);
+    NS_NAMED_LITERAL_STRING(driverKeyPre, "System\\CurrentControlSet\\Control\\Class\\");
+    /* enumerate device information elements in the device information set */
+    while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) {
+      /* get a string that identifies the device's driver key */
+      if (SetupDiGetDeviceRegistryPropertyW(devinfo,
+                                            &devinfoData,
+                                            SPDRP_DRIVER,
+                                            nullptr,
+                                            (PBYTE)value,
+                                            sizeof(value),
+                                            nullptr)) {
+        nsAutoString driverKey(driverKeyPre);
+        driverKey += value;
+        result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey.get(), 0, KEY_QUERY_VALUE, &key);
+        if (result == ERROR_SUCCESS) {
+          /* we've found the driver we're looking for */
+          dwcbData = sizeof(value);
+          result = RegQueryValueExW(key, L"DriverVersion", nullptr, nullptr,
+                                    (LPBYTE)value, &dwcbData);
+          if (result == ERROR_SUCCESS) {
+            mDriverVersion = value;
+          } else {
+            // If the entry wasn't found, assume the worst (0.0.0.0).
+            mDriverVersion.AssignLiteral("0.0.0.0");
+          }
+          dwcbData = sizeof(value);
+          result = RegQueryValueExW(key, L"DriverDate", nullptr, nullptr,
+                                    (LPBYTE)value, &dwcbData);
+          if (result == ERROR_SUCCESS) {
+            mDriverDate = value;
+          } else {
+            // Again, assume the worst
+            mDriverDate.AssignLiteral("01-01-1970");
+          }
+          RegCloseKey(key);
+          break;
+        }
+      }
+    }
+
+    SetupDiDestroyDeviceInfoList(devinfo);
+  }
+  return NS_OK;
+}
+
+
+void
+GfxInfo::CheckAndUpdateDriverInfo()
+{
+
   mHasDriverVersionMismatch = false;
   if (mAdapterVendorID == GfxDriverInfo::GetDeviceVendor(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 char16_t *dllFileName = is64bitApp
                                  ? u"igd10umd64.dll"
@@ -569,20 +649,16 @@ GfxInfo::Init()
   if (spoofedVendor) {
     mAdapterVendorID.AssignASCII(spoofedVendor);
   }
 
   const char *spoofedDevice = PR_GetEnv("MOZ_GFX_SPOOF_DEVICE_ID");
   if (spoofedDevice) {
     mAdapterDeviceID.AssignASCII(spoofedDevice);
   }
-
-  AddCrashReportAnnotations();
-
-  return rv;
 }
 
 NS_IMETHODIMP
 GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription)
 {
   aAdapterDescription = mDeviceString;
   return NS_OK;
 }
--- a/widget/windows/GfxInfo.h
+++ b/widget/windows/GfxInfo.h
@@ -41,16 +41,18 @@ public:
   NS_IMETHOD GetAdapterRAM2(nsAString & aAdapterRAM) override;
   NS_IMETHOD GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion) override;
   NS_IMETHOD GetAdapterDriverDate2(nsAString & aAdapterDriverDate) override;
   NS_IMETHOD GetIsGPU2Active(bool *aIsGPU2Active) override;
   using GfxInfoBase::GetFeatureStatus;
   using GfxInfoBase::GetFeatureSuggestedDriverVersion;
   using GfxInfoBase::GetWebGLParameter;
 
+  NS_IMETHOD Reset(const nsAString& aVendorID, const nsAString& aDeviceID) override;
+
   virtual nsresult Init() override;
 
   virtual uint32_t OperatingSystemVersion() override { return mWindowsVersion; }
 
   nsresult FindMonitors(JSContext* cx, JS::HandleObject array) override;
 
 #ifdef DEBUG
   NS_DECL_ISUPPORTS_INHERITED
@@ -67,16 +69,18 @@ protected:
                                         OperatingSystem* aOS = nullptr) override;
   virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() override;
 
   void DescribeFeatures(JSContext* cx, JS::Handle<JSObject*> aOut) override;
 
 private:
 
   void AddCrashReportAnnotations();
+  nsresult UpdatePrimaryDeviceInfo(DISPLAY_DEVICEW &displayDevice);
+  void CheckAndUpdateDriverInfo();
 
   nsString mDeviceString;
   nsString mDeviceID;
   nsString mDriverVersion;
   nsString mDriverDate;
   nsString mDeviceKey;
   nsString mDeviceKeyDebug;
   nsString mAdapterVendorID;