From f6feed92b7d73ae1c42e8a9f94a708f01379d830 Mon Sep 17 00:00:00 2001 From: eyim Date: Thu, 11 Aug 2016 18:20:21 -0400 Subject: [PATCH] Bug 1286653 - Re-run blacklist on DXGI adapter used for device creation r=BenWa,dvander MozReview-Commit-ID: 9QV8QFu5WYR --HG-- extra : rebase_source : d0da9409b2818a1ebce1469daecc3ca436bfa33e --- gfx/thebes/DeviceManagerD3D11.cpp | 29 +++ widget/GfxInfoBase.cpp | 7 + widget/GfxInfoBase.h | 2 + widget/nsIGfxInfo.idl | 6 + widget/windows/GfxInfo.cpp | 284 +++++++++++++++++++----------- widget/windows/GfxInfo.h | 4 + 6 files changed, 228 insertions(+), 104 deletions(-) diff --git a/gfx/thebes/DeviceManagerD3D11.cpp b/gfx/thebes/DeviceManagerD3D11.cpp index 3258c8afb959..50df220d2979 100644 --- a/gfx/thebes/DeviceManagerD3D11.cpp +++ b/gfx/thebes/DeviceManagerD3D11.cpp @@ -92,6 +92,35 @@ DeviceManagerD3D11::CreateDevices() } if (XRE_IsParentProcess()) { + // reset the primary adapter information, given the adapter from device creation + RefPtr 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 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) { diff --git a/widget/GfxInfoBase.cpp b/widget/GfxInfoBase.cpp index 09993b2c9848..e1a967afaa80 100644 --- a/widget/GfxInfoBase.cpp +++ b/widget/GfxInfoBase.cpp @@ -575,6 +575,13 @@ GfxInfoBase::Init() 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) { diff --git a/widget/GfxInfoBase.h b/widget/GfxInfoBase.h index 2cf4514d1238..21b6f88b80d6 100644 --- a/widget/GfxInfoBase.h +++ b/widget/GfxInfoBase.h @@ -59,6 +59,8 @@ public: NS_IMETHOD GetFeatureLog(JSContext*, JS::MutableHandle) override; NS_IMETHOD GetActiveCrashGuards(JSContext*, JS::MutableHandle) 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 diff --git a/widget/nsIGfxInfo.idl b/widget/nsIGfxInfo.idl index bb93eb8e1738..56020fd239db 100644 --- a/widget/nsIGfxInfo.idl +++ b/widget/nsIGfxInfo.idl @@ -156,6 +156,12 @@ interface nsIGfxInfo : nsISupports // 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(); diff --git a/widget/windows/GfxInfo.cpp b/widget/windows/GfxInfo.cpp index 4dc2f5b2b981..fa9f311edc9a 100644 --- a/widget/windows/GfxInfo.cpp +++ b/widget/windows/GfxInfo.cpp @@ -299,114 +299,17 @@ GfxInfo::Init() deviceIndex++; } - // make sure the string is nullptr terminated - if (wcsnlen(displayDevice.DeviceKey, ArrayLength(displayDevice.DeviceKey)) - == ArrayLength(displayDevice.DeviceKey)) { - // we did not find a nullptr + rv = UpdatePrimaryDeviceInfo(displayDevice); + if (rv != NS_OK) { 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); - } - 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}", @@ -518,6 +421,183 @@ GfxInfo::Init() } } + 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 @@ -574,10 +654,6 @@ GfxInfo::Init() if (spoofedDevice) { mAdapterDeviceID.AssignASCII(spoofedDevice); } - - AddCrashReportAnnotations(); - - return rv; } NS_IMETHODIMP diff --git a/widget/windows/GfxInfo.h b/widget/windows/GfxInfo.h index c7aa859a6e83..2324d8a07e03 100644 --- a/widget/windows/GfxInfo.h +++ b/widget/windows/GfxInfo.h @@ -46,6 +46,8 @@ public: 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; } @@ -72,6 +74,8 @@ protected: private: void AddCrashReportAnnotations(); + nsresult UpdatePrimaryDeviceInfo(DISPLAY_DEVICEW &displayDevice); + void CheckAndUpdateDriverInfo(); nsString mDeviceString; nsString mDeviceID;