Bug 1286653 - Re-run blacklist on DXGI adapter used for device creation
MozReview-Commit-ID: 9QV8QFu5WYR
--- 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;