Bug 1692971 [wpt PR 27638] - WebKit export of https://bugs.webkit.org/show_bug.cgi...
[gecko.git] / widget / windows / GfxInfo.cpp
blob55f0f1d2d7ec54d8088bbd4e41838b0014fe4ec3
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/ArrayUtils.h"
8 #include <windows.h>
9 #include <devguid.h> // for GUID_DEVCLASS_BATTERY
10 #include <setupapi.h> // for SetupDi*
11 #include <winioctl.h> // for IOCTL_*
12 #include <batclass.h> // for BATTERY_*
13 #include "gfxConfig.h"
14 #include "gfxWindowsPlatform.h"
15 #include "GfxInfo.h"
16 #include "nsUnicharUtils.h"
17 #include "prenv.h"
18 #include "prprf.h"
19 #include "GfxDriverInfo.h"
20 #include "mozilla/Components.h"
21 #include "mozilla/Preferences.h"
22 #include "mozilla/gfx/DeviceManagerDx.h"
23 #include "mozilla/gfx/Logging.h"
24 #include "mozilla/SSE.h"
25 #include "nsExceptionHandler.h"
26 #include "nsPrintfCString.h"
27 #include "jsapi.h"
28 #include <intrin.h>
30 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
32 using namespace mozilla;
33 using namespace mozilla::gfx;
34 using namespace mozilla::widget;
36 #ifdef DEBUG
37 NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug)
38 #endif
40 GfxInfo::GfxInfo()
41 : mWindowsVersion(0),
42 mWindowsBuildNumber(0),
43 mActiveGPUIndex(0),
44 mHasDualGPU(false),
45 mHasBattery(false) {}
47 /* GetD2DEnabled and GetDwriteEnabled shouldn't be called until after
48 * gfxPlatform initialization has occurred because they depend on it for
49 * information. (See bug 591561) */
50 nsresult GfxInfo::GetD2DEnabled(bool* aEnabled) {
51 // Telemetry queries this during XPCOM initialization, and there's no
52 // gfxPlatform by then. Just bail out if gfxPlatform isn't initialized.
53 if (!gfxPlatform::Initialized()) {
54 *aEnabled = false;
55 return NS_OK;
58 // We check gfxConfig rather than the actual render mode, since the UI
59 // process does not use Direct2D if the GPU process is enabled. However,
60 // content processes can still use Direct2D.
61 *aEnabled = gfx::gfxConfig::IsEnabled(gfx::Feature::DIRECT2D);
62 return NS_OK;
65 nsresult GfxInfo::GetDWriteEnabled(bool* aEnabled) {
66 *aEnabled = gfxWindowsPlatform::GetPlatform()->DWriteEnabled();
67 return NS_OK;
70 NS_IMETHODIMP
71 GfxInfo::GetDWriteVersion(nsAString& aDwriteVersion) {
72 gfxWindowsPlatform::GetDLLVersion(L"dwrite.dll", aDwriteVersion);
73 return NS_OK;
76 NS_IMETHODIMP
77 GfxInfo::GetHasBattery(bool* aHasBattery) {
78 *aHasBattery = mHasBattery;
79 return NS_OK;
82 int32_t GfxInfo::GetMaxRefreshRate(bool* aMixed) {
83 int32_t maxRefreshRate = -1;
84 if (aMixed) {
85 *aMixed = false;
88 for (auto displayInfo : mDisplayInfo) {
89 int32_t refreshRate = int32_t(displayInfo.mRefreshRate);
90 if (aMixed && maxRefreshRate > 0 && maxRefreshRate != refreshRate) {
91 *aMixed = true;
93 maxRefreshRate = std::max(maxRefreshRate, refreshRate);
95 return maxRefreshRate;
98 NS_IMETHODIMP
99 GfxInfo::GetEmbeddedInFirefoxReality(bool* aEmbeddedInFirefoxReality) {
100 *aEmbeddedInFirefoxReality = gfxVars::FxREmbedded();
101 return NS_OK;
104 #define PIXEL_STRUCT_RGB 1
105 #define PIXEL_STRUCT_BGR 2
107 NS_IMETHODIMP
108 GfxInfo::GetCleartypeParameters(nsAString& aCleartypeParams) {
109 nsTArray<ClearTypeParameterInfo> clearTypeParams;
111 gfxWindowsPlatform::GetPlatform()->GetCleartypeParams(clearTypeParams);
112 uint32_t d, numDisplays = clearTypeParams.Length();
113 bool displayNames = (numDisplays > 1);
114 bool foundData = false;
115 nsString outStr;
117 for (d = 0; d < numDisplays; d++) {
118 ClearTypeParameterInfo& params = clearTypeParams[d];
120 if (displayNames) {
121 outStr.AppendPrintf("%S [ ", params.displayName.get());
124 if (params.gamma >= 0) {
125 foundData = true;
126 outStr.AppendPrintf("Gamma: %.4g ", params.gamma / 1000.0);
129 if (params.pixelStructure >= 0) {
130 foundData = true;
131 if (params.pixelStructure == PIXEL_STRUCT_RGB ||
132 params.pixelStructure == PIXEL_STRUCT_BGR) {
133 outStr.AppendPrintf(
134 "Pixel Structure: %S ",
135 (params.pixelStructure == PIXEL_STRUCT_RGB ? u"RGB" : u"BGR"));
136 } else {
137 outStr.AppendPrintf("Pixel Structure: %d ", params.pixelStructure);
141 if (params.clearTypeLevel >= 0) {
142 foundData = true;
143 outStr.AppendPrintf("ClearType Level: %d ", params.clearTypeLevel);
146 if (params.enhancedContrast >= 0) {
147 foundData = true;
148 outStr.AppendPrintf("Enhanced Contrast: %d ", params.enhancedContrast);
151 if (displayNames) {
152 outStr.Append(u"] ");
156 if (foundData) {
157 aCleartypeParams.Assign(outStr);
158 return NS_OK;
160 return NS_ERROR_FAILURE;
163 NS_IMETHODIMP
164 GfxInfo::GetWindowProtocol(nsAString& aWindowProtocol) {
165 return NS_ERROR_NOT_IMPLEMENTED;
168 NS_IMETHODIMP
169 GfxInfo::GetDesktopEnvironment(nsAString& aDesktopEnvironment) {
170 return NS_ERROR_NOT_IMPLEMENTED;
173 NS_IMETHODIMP
174 GfxInfo::GetTestType(nsAString& aTestType) { return NS_ERROR_NOT_IMPLEMENTED; }
176 static nsresult GetKeyValue(const WCHAR* keyLocation, const WCHAR* keyName,
177 uint32_t& destValue, int type) {
178 MOZ_ASSERT(type == REG_DWORD || type == REG_QWORD);
179 HKEY key;
180 DWORD dwcbData;
181 DWORD dValue;
182 DWORD resultType;
183 LONG result;
184 nsresult retval = NS_OK;
186 result =
187 RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyLocation, 0, KEY_QUERY_VALUE, &key);
188 if (result != ERROR_SUCCESS) {
189 return NS_ERROR_FAILURE;
192 switch (type) {
193 case REG_DWORD: {
194 // We only use this for vram size
195 dwcbData = sizeof(dValue);
196 result = RegQueryValueExW(key, keyName, nullptr, &resultType,
197 (LPBYTE)&dValue, &dwcbData);
198 if (result == ERROR_SUCCESS && resultType == REG_DWORD) {
199 destValue = (uint32_t)(dValue / 1024 / 1024);
200 } else {
201 retval = NS_ERROR_FAILURE;
203 break;
205 case REG_QWORD: {
206 // We only use this for vram size
207 LONGLONG qValue;
208 dwcbData = sizeof(qValue);
209 result = RegQueryValueExW(key, keyName, nullptr, &resultType,
210 (LPBYTE)&qValue, &dwcbData);
211 if (result == ERROR_SUCCESS && resultType == REG_QWORD) {
212 destValue = (uint32_t)(qValue / 1024 / 1024);
213 } else {
214 retval = NS_ERROR_FAILURE;
216 break;
219 RegCloseKey(key);
221 return retval;
224 static nsresult GetKeyValue(const WCHAR* keyLocation, const WCHAR* keyName,
225 nsAString& destString, int type) {
226 MOZ_ASSERT(type == REG_MULTI_SZ);
228 HKEY key;
229 DWORD dwcbData;
230 DWORD resultType;
231 LONG result;
232 nsresult retval = NS_OK;
234 result =
235 RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyLocation, 0, KEY_QUERY_VALUE, &key);
236 if (result != ERROR_SUCCESS) {
237 return NS_ERROR_FAILURE;
240 // A chain of null-separated strings; we convert the nulls to spaces
241 WCHAR wCharValue[1024];
242 dwcbData = sizeof(wCharValue);
244 result = RegQueryValueExW(key, keyName, nullptr, &resultType,
245 (LPBYTE)wCharValue, &dwcbData);
246 if (result == ERROR_SUCCESS && resultType == REG_MULTI_SZ) {
247 // This bit here could probably be cleaner.
248 bool isValid = false;
250 DWORD strLen = dwcbData / sizeof(wCharValue[0]);
251 for (DWORD i = 0; i < strLen; i++) {
252 if (wCharValue[i] == '\0') {
253 if (i < strLen - 1 && wCharValue[i + 1] == '\0') {
254 isValid = true;
255 break;
256 } else {
257 wCharValue[i] = ' ';
262 // ensure wCharValue is null terminated
263 wCharValue[strLen - 1] = '\0';
265 if (isValid) destString = wCharValue;
267 } else {
268 retval = NS_ERROR_FAILURE;
271 RegCloseKey(key);
273 return retval;
276 static nsresult GetKeyValues(const WCHAR* keyLocation, const WCHAR* keyName,
277 nsTArray<nsString>& destStrings) {
278 // First ask for the size of the value
279 DWORD size;
280 LONG rv = RegGetValueW(HKEY_LOCAL_MACHINE, keyLocation, keyName,
281 RRF_RT_REG_MULTI_SZ, nullptr, nullptr, &size);
282 if (rv != ERROR_SUCCESS) {
283 return NS_ERROR_FAILURE;
286 // Create a buffer with the proper size and retrieve the value
287 WCHAR* wCharValue = new WCHAR[size / sizeof(WCHAR)];
288 rv = RegGetValueW(HKEY_LOCAL_MACHINE, keyLocation, keyName,
289 RRF_RT_REG_MULTI_SZ, nullptr, (LPBYTE)wCharValue, &size);
290 if (rv != ERROR_SUCCESS) {
291 delete[] wCharValue;
292 return NS_ERROR_FAILURE;
295 // The value is a sequence of null-terminated strings, usually terminated by
296 // an empty string (\0). RegGetValue ensures that the value is properly
297 // terminated with a null character.
298 DWORD i = 0;
299 DWORD strLen = size / sizeof(WCHAR);
300 while (i < strLen) {
301 nsString value(wCharValue + i);
302 if (!value.IsEmpty()) {
303 destStrings.AppendElement(value);
305 i += value.Length() + 1;
307 delete[] wCharValue;
309 return NS_OK;
312 // The device ID is a string like PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD
313 // this function is used to extract the id's out of it
314 uint32_t ParseIDFromDeviceID(const nsAString& key, const char* prefix,
315 int length) {
316 nsAutoString id(key);
317 ToUpperCase(id);
318 int32_t start = id.Find(prefix);
319 if (start != -1) {
320 id.Cut(0, start + strlen(prefix));
321 id.Truncate(length);
323 if (id.Equals(L"QCOM", nsCaseInsensitiveStringComparator)) {
324 // String format assumptions are broken, so use a Qualcomm PCI Vendor ID
325 // for now. See also GfxDriverInfo::GetDeviceVendor.
326 return 0x5143;
328 nsresult err;
329 return id.ToInteger(&err, 16);
332 // OS version in 16.16 major/minor form
333 // based on http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
334 enum {
335 kWindowsUnknown = 0,
336 kWindows7 = 0x60001,
337 kWindows8 = 0x60002,
338 kWindows8_1 = 0x60003,
339 kWindows10 = 0xA0000
342 static bool HasBattery() {
343 // Helper classes to manage lifetimes of Windows structs.
344 class MOZ_STACK_CLASS HDevInfoHolder final {
345 public:
346 explicit HDevInfoHolder(HDEVINFO aHandle) : mHandle(aHandle) {}
348 ~HDevInfoHolder() { ::SetupDiDestroyDeviceInfoList(mHandle); }
350 private:
351 HDEVINFO mHandle;
354 class MOZ_STACK_CLASS HandleHolder final {
355 public:
356 explicit HandleHolder(HANDLE aHandle) : mHandle(aHandle) {}
358 ~HandleHolder() { ::CloseHandle(mHandle); }
360 private:
361 HANDLE mHandle;
364 HDEVINFO hdev =
365 ::SetupDiGetClassDevs(&GUID_DEVCLASS_BATTERY, nullptr, nullptr,
366 DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
367 if (hdev == INVALID_HANDLE_VALUE) {
368 return true;
371 HDevInfoHolder hdevHolder(hdev);
373 DWORD i = 0;
374 SP_DEVICE_INTERFACE_DATA did = {0};
375 did.cbSize = sizeof(did);
377 while (::SetupDiEnumDeviceInterfaces(hdev, nullptr, &GUID_DEVCLASS_BATTERY, i,
378 &did)) {
379 DWORD bufferSize = 0;
380 ::SetupDiGetDeviceInterfaceDetail(hdev, &did, nullptr, 0, &bufferSize,
381 nullptr);
382 if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
383 return true;
386 UniquePtr<uint8_t[]> buffer(new (std::nothrow) uint8_t[bufferSize]);
387 if (!buffer) {
388 return true;
391 PSP_DEVICE_INTERFACE_DETAIL_DATA pdidd =
392 reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(buffer.get());
393 pdidd->cbSize = sizeof(*pdidd);
394 if (!::SetupDiGetDeviceInterfaceDetail(hdev, &did, pdidd, bufferSize,
395 &bufferSize, nullptr)) {
396 return true;
399 HANDLE hbat = ::CreateFile(pdidd->DevicePath, GENERIC_READ | GENERIC_WRITE,
400 FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
401 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
402 if (hbat == INVALID_HANDLE_VALUE) {
403 return true;
406 HandleHolder hbatHolder(hbat);
408 BATTERY_QUERY_INFORMATION bqi = {0};
409 DWORD dwWait = 0;
410 DWORD dwOut;
412 // We need the tag to query the information below.
413 if (!::DeviceIoControl(hbat, IOCTL_BATTERY_QUERY_TAG, &dwWait,
414 sizeof(dwWait), &bqi.BatteryTag,
415 sizeof(bqi.BatteryTag), &dwOut, nullptr) ||
416 !bqi.BatteryTag) {
417 return true;
420 BATTERY_INFORMATION bi = {0};
421 bqi.InformationLevel = BatteryInformation;
423 if (!::DeviceIoControl(hbat, IOCTL_BATTERY_QUERY_INFORMATION, &bqi,
424 sizeof(bqi), &bi, sizeof(bi), &dwOut, nullptr)) {
425 return true;
428 // If a battery intended for general use (i.e. system use) is not a UPS
429 // (i.e. short term), then we know for certain we have a battery.
430 if ((bi.Capabilities & BATTERY_SYSTEM_BATTERY) &&
431 !(bi.Capabilities & BATTERY_IS_SHORT_TERM)) {
432 return true;
435 // Otherwise we check the next battery.
436 ++i;
439 // If we fail to enumerate because there are no more batteries to check, then
440 // we can safely say there are indeed no system batteries.
441 return ::GetLastError() != ERROR_NO_MORE_ITEMS;
444 /* Other interesting places for info:
445 * IDXGIAdapter::GetDesc()
446 * IDirectDraw7::GetAvailableVidMem()
447 * e->GetAvailableTextureMem()
448 * */
450 #define DEVICE_KEY_PREFIX L"\\Registry\\Machine\\"
451 nsresult GfxInfo::Init() {
452 nsresult rv = GfxInfoBase::Init();
453 mHasBattery = HasBattery();
455 DISPLAY_DEVICEW displayDevice;
456 displayDevice.cb = sizeof(displayDevice);
457 int deviceIndex = 0;
459 const char* spoofedWindowsVersion =
460 PR_GetEnv("MOZ_GFX_SPOOF_WINDOWS_VERSION");
461 if (spoofedWindowsVersion) {
462 PR_sscanf(spoofedWindowsVersion, "%x,%u", &mWindowsVersion,
463 &mWindowsBuildNumber);
464 } else {
465 OSVERSIONINFO vinfo;
466 vinfo.dwOSVersionInfoSize = sizeof(vinfo);
467 #ifdef _MSC_VER
468 # pragma warning(push)
469 # pragma warning(disable : 4996)
470 #endif
471 if (!GetVersionEx(&vinfo)) {
472 #ifdef _MSC_VER
473 # pragma warning(pop)
474 #endif
475 mWindowsVersion = kWindowsUnknown;
476 } else {
477 mWindowsVersion =
478 int32_t(vinfo.dwMajorVersion << 16) + vinfo.dwMinorVersion;
479 mWindowsBuildNumber = vinfo.dwBuildNumber;
483 mDeviceKeyDebug = u"PrimarySearch"_ns;
485 while (EnumDisplayDevicesW(nullptr, deviceIndex, &displayDevice, 0)) {
486 if (displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
487 mDeviceKeyDebug = u"NullSearch"_ns;
488 break;
490 deviceIndex++;
493 // make sure the string is nullptr terminated
494 if (wcsnlen(displayDevice.DeviceKey, ArrayLength(displayDevice.DeviceKey)) ==
495 ArrayLength(displayDevice.DeviceKey)) {
496 // we did not find a nullptr
497 return rv;
500 mDeviceKeyDebug = displayDevice.DeviceKey;
502 /* DeviceKey is "reserved" according to MSDN so we'll be careful with it */
503 /* check that DeviceKey begins with DEVICE_KEY_PREFIX */
504 /* some systems have a DeviceKey starting with \REGISTRY\Machine\ so we need
505 * to compare case insenstively */
506 /* If the device key is empty, we are most likely in a remote desktop
507 * environment. In this case we set the devicekey to an empty string so
508 * it can be handled later.
510 if (displayDevice.DeviceKey[0] != '\0') {
511 if (_wcsnicmp(displayDevice.DeviceKey, DEVICE_KEY_PREFIX,
512 ArrayLength(DEVICE_KEY_PREFIX) - 1) != 0) {
513 return rv;
516 // chop off DEVICE_KEY_PREFIX
517 mDeviceKey[0] =
518 displayDevice.DeviceKey + ArrayLength(DEVICE_KEY_PREFIX) - 1;
519 } else {
520 mDeviceKey[0].Truncate();
523 mDeviceID[0] = displayDevice.DeviceID;
524 mDeviceString[0] = displayDevice.DeviceString;
526 // On Windows 8 and Server 2012 hosts, we want to not block RDP
527 // sessions from attempting hardware acceleration. RemoteFX
528 // provides features and functionaltiy that can give a good D3D10 +
529 // D2D + DirectWrite experience emulated via a software GPU.
531 // Unfortunately, the Device ID is nullptr, and we can't enumerate
532 // it using the setup infrastructure (SetupDiGetClassDevsW below
533 // will return INVALID_HANDLE_VALUE).
534 UINT flags = DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES;
535 if (mWindowsVersion >= kWindows8 && mDeviceID[0].Length() == 0 &&
536 mDeviceString[0].EqualsLiteral("RDPUDD Chained DD")) {
537 WCHAR sysdir[255];
538 UINT len = GetSystemDirectory(sysdir, sizeof(sysdir));
539 if (len < sizeof(sysdir)) {
540 nsString rdpudd(sysdir);
541 rdpudd.AppendLiteral("\\rdpudd.dll");
542 gfxWindowsPlatform::GetDLLVersion(rdpudd.BeginReading(),
543 mDriverVersion[0]);
544 mDriverDate[0].AssignLiteral("01-01-1970");
546 // 0x1414 is Microsoft; 0xfefe is an invented (and unused) code
547 mDeviceID[0].AssignLiteral("PCI\\VEN_1414&DEV_FEFE&SUBSYS_00000000");
548 flags |= DIGCF_DEVICEINTERFACE;
552 /* create a device information set composed of the current display device */
553 HDEVINFO devinfo =
554 SetupDiGetClassDevsW(nullptr, mDeviceID[0].get(), nullptr, flags);
556 if (devinfo != INVALID_HANDLE_VALUE) {
557 HKEY key;
558 LONG result;
559 WCHAR value[255];
560 DWORD dwcbData;
561 SP_DEVINFO_DATA devinfoData;
562 DWORD memberIndex = 0;
564 devinfoData.cbSize = sizeof(devinfoData);
565 constexpr auto driverKeyPre =
566 u"System\\CurrentControlSet\\Control\\Class\\"_ns;
567 /* enumerate device information elements in the device information set */
568 while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) {
569 /* get a string that identifies the device's driver key */
570 if (SetupDiGetDeviceRegistryPropertyW(devinfo, &devinfoData, SPDRP_DRIVER,
571 nullptr, (PBYTE)value,
572 sizeof(value), nullptr)) {
573 nsAutoString driverKey(driverKeyPre);
574 driverKey += value;
575 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey.get(), 0,
576 KEY_QUERY_VALUE, &key);
577 if (result == ERROR_SUCCESS) {
578 /* we've found the driver we're looking for */
579 dwcbData = sizeof(value);
580 result = RegQueryValueExW(key, L"DriverVersion", nullptr, nullptr,
581 (LPBYTE)value, &dwcbData);
582 if (result == ERROR_SUCCESS) {
583 mDriverVersion[0] = value;
584 } else {
585 // If the entry wasn't found, assume the worst (0.0.0.0).
586 mDriverVersion[0].AssignLiteral("0.0.0.0");
588 dwcbData = sizeof(value);
589 result = RegQueryValueExW(key, L"DriverDate", nullptr, nullptr,
590 (LPBYTE)value, &dwcbData);
591 if (result == ERROR_SUCCESS) {
592 mDriverDate[0] = value;
593 } else {
594 // Again, assume the worst
595 mDriverDate[0].AssignLiteral("01-01-1970");
597 RegCloseKey(key);
598 break;
603 SetupDiDestroyDeviceInfoList(devinfo);
606 // It is convenient to have these as integers
607 uint32_t adapterVendorID[2] = {0, 0};
608 uint32_t adapterDeviceID[2] = {0, 0};
609 uint32_t adapterSubsysID[2] = {0, 0};
611 adapterVendorID[0] = ParseIDFromDeviceID(mDeviceID[0], "VEN_", 4);
612 adapterDeviceID[0] = ParseIDFromDeviceID(mDeviceID[0], "&DEV_", 4);
613 adapterSubsysID[0] = ParseIDFromDeviceID(mDeviceID[0], "&SUBSYS_", 8);
615 // Sometimes we don't get the valid device using this method. For now,
616 // allow zero vendor or device as valid, as long as the other value is
617 // non-zero.
618 bool foundValidDevice = (adapterVendorID[0] != 0 || adapterDeviceID[0] != 0);
620 // We now check for second display adapter. If we didn't find the valid
621 // device using the original approach, we will try the alternative.
623 // Device interface class for display adapters.
624 CLSID GUID_DISPLAY_DEVICE_ARRIVAL;
625 HRESULT hresult = CLSIDFromString(L"{1CA05180-A699-450A-9A0C-DE4FBE3DDD89}",
626 &GUID_DISPLAY_DEVICE_ARRIVAL);
627 if (hresult == NOERROR) {
628 devinfo =
629 SetupDiGetClassDevsW(&GUID_DISPLAY_DEVICE_ARRIVAL, nullptr, nullptr,
630 DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
632 if (devinfo != INVALID_HANDLE_VALUE) {
633 HKEY key;
634 LONG result;
635 WCHAR value[255];
636 DWORD dwcbData;
637 SP_DEVINFO_DATA devinfoData;
638 DWORD memberIndex = 0;
639 devinfoData.cbSize = sizeof(devinfoData);
641 nsAutoString adapterDriver2;
642 nsAutoString deviceID2;
643 nsAutoString driverVersion2;
644 nsAutoString driverDate2;
646 constexpr auto driverKeyPre =
647 u"System\\CurrentControlSet\\Control\\Class\\"_ns;
648 /* enumerate device information elements in the device information set */
649 while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) {
650 /* get a string that identifies the device's driver key */
651 if (SetupDiGetDeviceRegistryPropertyW(
652 devinfo, &devinfoData, SPDRP_DRIVER, nullptr, (PBYTE)value,
653 sizeof(value), nullptr)) {
654 nsAutoString driverKey2(driverKeyPre);
655 driverKey2 += value;
656 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey2.get(), 0,
657 KEY_QUERY_VALUE, &key);
658 if (result == ERROR_SUCCESS) {
659 dwcbData = sizeof(value);
660 result = RegQueryValueExW(key, L"MatchingDeviceId", nullptr,
661 nullptr, (LPBYTE)value, &dwcbData);
662 if (result != ERROR_SUCCESS) {
663 continue;
665 deviceID2 = value;
666 adapterVendorID[1] = ParseIDFromDeviceID(deviceID2, "VEN_", 4);
667 adapterDeviceID[1] = ParseIDFromDeviceID(deviceID2, "&DEV_", 4);
668 // Skip the devices we already considered, as well as any
669 // "zero" ones.
670 if ((adapterVendorID[0] == adapterVendorID[1] &&
671 adapterDeviceID[0] == adapterDeviceID[1]) ||
672 (adapterVendorID[1] == 0 && adapterDeviceID[1] == 0)) {
673 RegCloseKey(key);
674 continue;
677 // If this device is missing driver information, it is unlikely to
678 // be a real display adapter.
679 if (NS_FAILED(GetKeyValue(driverKey2.get(),
680 L"InstalledDisplayDrivers",
681 adapterDriver2, REG_MULTI_SZ))) {
682 RegCloseKey(key);
683 continue;
685 dwcbData = sizeof(value);
686 result = RegQueryValueExW(key, L"DriverVersion", nullptr, nullptr,
687 (LPBYTE)value, &dwcbData);
688 if (result != ERROR_SUCCESS) {
689 RegCloseKey(key);
690 continue;
692 driverVersion2 = value;
693 dwcbData = sizeof(value);
694 result = RegQueryValueExW(key, L"DriverDate", nullptr, nullptr,
695 (LPBYTE)value, &dwcbData);
696 if (result != ERROR_SUCCESS) {
697 RegCloseKey(key);
698 continue;
700 driverDate2 = value;
701 dwcbData = sizeof(value);
702 result = RegQueryValueExW(key, L"Device Description", nullptr,
703 nullptr, (LPBYTE)value, &dwcbData);
704 if (result != ERROR_SUCCESS) {
705 dwcbData = sizeof(value);
706 result = RegQueryValueExW(key, L"DriverDesc", nullptr, nullptr,
707 (LPBYTE)value, &dwcbData);
709 RegCloseKey(key);
710 if (result == ERROR_SUCCESS) {
711 // If we didn't find a valid device with the original method
712 // take this one, and continue looking for the second GPU.
713 if (!foundValidDevice) {
714 foundValidDevice = true;
715 adapterVendorID[0] = adapterVendorID[1];
716 adapterDeviceID[0] = adapterDeviceID[1];
717 mDeviceString[0] = value;
718 mDeviceID[0] = deviceID2;
719 mDeviceKey[0] = driverKey2;
720 mDriverVersion[0] = driverVersion2;
721 mDriverDate[0] = driverDate2;
722 adapterSubsysID[0] =
723 ParseIDFromDeviceID(mDeviceID[0], "&SUBSYS_", 8);
724 continue;
727 mHasDualGPU = true;
728 mDeviceString[1] = value;
729 mDeviceID[1] = deviceID2;
730 mDeviceKey[1] = driverKey2;
731 mDriverVersion[1] = driverVersion2;
732 mDriverDate[1] = driverDate2;
733 adapterSubsysID[1] =
734 ParseIDFromDeviceID(mDeviceID[1], "&SUBSYS_", 8);
735 mAdapterVendorID[1].AppendPrintf("0x%04x", adapterVendorID[1]);
736 mAdapterDeviceID[1].AppendPrintf("0x%04x", adapterDeviceID[1]);
737 mAdapterSubsysID[1].AppendPrintf("%08x", adapterSubsysID[1]);
738 break;
744 SetupDiDestroyDeviceInfoList(devinfo);
748 mAdapterVendorID[0].AppendPrintf("0x%04x", adapterVendorID[0]);
749 mAdapterDeviceID[0].AppendPrintf("0x%04x", adapterDeviceID[0]);
750 mAdapterSubsysID[0].AppendPrintf("%08x", adapterSubsysID[0]);
752 // Sometimes, the enumeration is not quite right and the two adapters
753 // end up being swapped. Actually enumerate the adapters that come
754 // back from the DXGI factory to check, and tag the second as active
755 // if found.
756 if (mHasDualGPU) {
757 nsModuleHandle dxgiModule(LoadLibrarySystem32(L"dxgi.dll"));
758 decltype(CreateDXGIFactory)* createDXGIFactory =
759 (decltype(CreateDXGIFactory)*)GetProcAddress(dxgiModule,
760 "CreateDXGIFactory");
762 if (createDXGIFactory) {
763 RefPtr<IDXGIFactory> factory = nullptr;
764 createDXGIFactory(__uuidof(IDXGIFactory), (void**)(&factory));
765 if (factory) {
766 RefPtr<IDXGIAdapter> adapter;
767 if (SUCCEEDED(factory->EnumAdapters(0, getter_AddRefs(adapter)))) {
768 DXGI_ADAPTER_DESC desc;
769 PodZero(&desc);
770 if (SUCCEEDED(adapter->GetDesc(&desc))) {
771 if (desc.VendorId != adapterVendorID[0] &&
772 desc.DeviceId != adapterDeviceID[0] &&
773 desc.VendorId == adapterVendorID[1] &&
774 desc.DeviceId == adapterDeviceID[1]) {
775 mActiveGPUIndex = 1;
783 mHasDriverVersionMismatch = false;
784 if (mAdapterVendorID[mActiveGPUIndex] ==
785 GfxDriverInfo::GetDeviceVendor(DeviceVendor::Intel)) {
786 // we've had big crashers (bugs 590373 and 595364) apparently correlated
787 // with bad Intel driver installations where the DriverVersion reported
788 // by the registry was not the version of the DLL.
790 // Note that these start without the .dll extension but eventually gain it.
791 bool is64bitApp = sizeof(void*) == 8;
792 nsAutoString dllFileName(is64bitApp ? u"igd10umd64" : u"igd10umd32");
793 nsAutoString dllFileName2(is64bitApp ? u"igd10iumd64" : u"igd10iumd32");
795 nsString dllVersion, dllVersion2;
796 uint64_t dllNumericVersion = 0, dllNumericVersion2 = 0,
797 driverNumericVersion = 0, knownSafeMismatchVersion = 0;
799 // Only parse the DLL version for those found in the driver list
800 nsAutoString eligibleDLLs;
801 if (NS_SUCCEEDED(GetAdapterDriver(eligibleDLLs))) {
802 if (FindInReadable(dllFileName, eligibleDLLs)) {
803 dllFileName += u".dll"_ns;
804 gfxWindowsPlatform::GetDLLVersion(dllFileName.get(), dllVersion);
805 ParseDriverVersion(dllVersion, &dllNumericVersion);
807 if (FindInReadable(dllFileName2, eligibleDLLs)) {
808 dllFileName2 += u".dll"_ns;
809 gfxWindowsPlatform::GetDLLVersion(dllFileName2.get(), dllVersion2);
810 ParseDriverVersion(dllVersion2, &dllNumericVersion2);
814 // Sometimes the DLL is not in the System32 nor SysWOW64 directories. But
815 // UserModeDriverName (or UserModeDriverNameWow, if available) might provide
816 // the full path to the DLL in some DriverStore FileRepository.
817 if (dllNumericVersion == 0 && dllNumericVersion2 == 0) {
818 nsTArray<nsString> eligibleDLLpaths;
819 const WCHAR* keyLocation = mDeviceKey[mActiveGPUIndex].get();
820 GetKeyValues(keyLocation, L"UserModeDriverName", eligibleDLLpaths);
821 GetKeyValues(keyLocation, L"UserModeDriverNameWow", eligibleDLLpaths);
822 size_t length = eligibleDLLpaths.Length();
823 for (size_t i = 0;
824 i < length && dllNumericVersion == 0 && dllNumericVersion2 == 0;
825 ++i) {
826 if (FindInReadable(dllFileName, eligibleDLLpaths[i])) {
827 gfxWindowsPlatform::GetDLLVersion(eligibleDLLpaths[i].get(),
828 dllVersion);
829 ParseDriverVersion(dllVersion, &dllNumericVersion);
830 } else if (FindInReadable(dllFileName2, eligibleDLLpaths[i])) {
831 gfxWindowsPlatform::GetDLLVersion(eligibleDLLpaths[i].get(),
832 dllVersion2);
833 ParseDriverVersion(dllVersion2, &dllNumericVersion2);
838 ParseDriverVersion(mDriverVersion[mActiveGPUIndex], &driverNumericVersion);
839 ParseDriverVersion(u"9.17.10.0"_ns, &knownSafeMismatchVersion);
841 // If there's a driver version mismatch, consider this harmful only when
842 // the driver version is less than knownSafeMismatchVersion. See the
843 // above comment about crashes with old mismatches. If the GetDllVersion
844 // call fails, we are not calling it a mismatch.
845 if ((dllNumericVersion != 0 && dllNumericVersion != driverNumericVersion) ||
846 (dllNumericVersion2 != 0 &&
847 dllNumericVersion2 != driverNumericVersion)) {
848 if (driverNumericVersion < knownSafeMismatchVersion ||
849 std::max(dllNumericVersion, dllNumericVersion2) <
850 knownSafeMismatchVersion) {
851 mHasDriverVersionMismatch = true;
852 gfxCriticalNoteOnce
853 << "Mismatched driver versions between the registry "
854 << NS_ConvertUTF16toUTF8(mDriverVersion[mActiveGPUIndex]).get()
855 << " and DLL(s) " << NS_ConvertUTF16toUTF8(dllVersion).get() << ", "
856 << NS_ConvertUTF16toUTF8(dllVersion2).get() << " reported.";
858 } else if (dllNumericVersion == 0 && dllNumericVersion2 == 0) {
859 // Leave it as an asserting error for now, to see if we can find
860 // a system that exhibits this kind of a problem internally.
861 gfxCriticalErrorOnce()
862 << "Potential driver version mismatch ignored due to missing DLLs "
863 << NS_ConvertUTF16toUTF8(dllFileName).get()
864 << " v=" << NS_ConvertUTF16toUTF8(dllVersion).get() << " and "
865 << NS_ConvertUTF16toUTF8(dllFileName2).get()
866 << " v=" << NS_ConvertUTF16toUTF8(dllVersion2).get();
870 // Get monitor information
871 RefreshMonitors();
873 const char* spoofedDriverVersionString =
874 PR_GetEnv("MOZ_GFX_SPOOF_DRIVER_VERSION");
875 if (spoofedDriverVersionString) {
876 mDriverVersion[mActiveGPUIndex].AssignASCII(spoofedDriverVersionString);
879 const char* spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_VENDOR_ID");
880 if (spoofedVendor) {
881 mAdapterVendorID[mActiveGPUIndex].AssignASCII(spoofedVendor);
884 const char* spoofedDevice = PR_GetEnv("MOZ_GFX_SPOOF_DEVICE_ID");
885 if (spoofedDevice) {
886 mAdapterDeviceID[mActiveGPUIndex].AssignASCII(spoofedDevice);
889 AddCrashReportAnnotations();
891 return rv;
894 NS_IMETHODIMP
895 GfxInfo::GetAdapterDescription(nsAString& aAdapterDescription) {
896 aAdapterDescription = mDeviceString[mActiveGPUIndex];
897 return NS_OK;
900 NS_IMETHODIMP
901 GfxInfo::GetAdapterDescription2(nsAString& aAdapterDescription) {
902 aAdapterDescription = mDeviceString[1 - mActiveGPUIndex];
903 return NS_OK;
906 NS_IMETHODIMP
907 GfxInfo::RefreshMonitors() {
908 mDisplayInfo.Clear();
910 for (int deviceIndex = 0;; deviceIndex++) {
911 DISPLAY_DEVICEW device;
912 device.cb = sizeof(device);
913 if (!::EnumDisplayDevicesW(nullptr, deviceIndex, &device, 0)) {
914 break;
917 if (!(device.StateFlags & DISPLAY_DEVICE_ACTIVE)) {
918 continue;
921 DEVMODEW mode;
922 mode.dmSize = sizeof(mode);
923 mode.dmDriverExtra = 0;
924 if (!::EnumDisplaySettingsW(device.DeviceName, ENUM_CURRENT_SETTINGS,
925 &mode)) {
926 continue;
929 DisplayInfo displayInfo;
931 displayInfo.mScreenWidth = mode.dmPelsWidth;
932 displayInfo.mScreenHeight = mode.dmPelsHeight;
933 displayInfo.mRefreshRate = mode.dmDisplayFrequency;
934 displayInfo.mIsPseudoDisplay =
935 !!(device.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER);
936 displayInfo.mDeviceString = device.DeviceString;
938 mDisplayInfo.AppendElement(displayInfo);
940 return NS_OK;
943 NS_IMETHODIMP
944 GfxInfo::GetAdapterRAM(uint32_t* aAdapterRAM) {
945 uint32_t result = 0;
946 if (NS_FAILED(GetKeyValue(mDeviceKey[mActiveGPUIndex].get(),
947 L"HardwareInformation.qwMemorySize", result,
948 REG_QWORD)) ||
949 result == 0) {
950 if (NS_FAILED(GetKeyValue(mDeviceKey[mActiveGPUIndex].get(),
951 L"HardwareInformation.MemorySize", result,
952 REG_DWORD))) {
953 result = 0;
956 *aAdapterRAM = result;
957 return NS_OK;
960 NS_IMETHODIMP
961 GfxInfo::GetAdapterRAM2(uint32_t* aAdapterRAM) {
962 uint32_t result = 0;
963 if (mHasDualGPU) {
964 if (NS_FAILED(GetKeyValue(mDeviceKey[1 - mActiveGPUIndex].get(),
965 L"HardwareInformation.qwMemorySize", result,
966 REG_QWORD)) ||
967 result == 0) {
968 if (NS_FAILED(GetKeyValue(mDeviceKey[1 - mActiveGPUIndex].get(),
969 L"HardwareInformation.MemorySize", result,
970 REG_DWORD))) {
971 result = 0;
975 *aAdapterRAM = result;
976 return NS_OK;
979 NS_IMETHODIMP
980 GfxInfo::GetAdapterDriver(nsAString& aAdapterDriver) {
981 if (NS_FAILED(GetKeyValue(mDeviceKey[mActiveGPUIndex].get(),
982 L"InstalledDisplayDrivers", aAdapterDriver,
983 REG_MULTI_SZ)))
984 aAdapterDriver = L"Unknown";
985 return NS_OK;
988 NS_IMETHODIMP
989 GfxInfo::GetAdapterDriver2(nsAString& aAdapterDriver) {
990 if (!mHasDualGPU) {
991 aAdapterDriver.Truncate();
992 } else if (NS_FAILED(GetKeyValue(mDeviceKey[1 - mActiveGPUIndex].get(),
993 L"InstalledDisplayDrivers", aAdapterDriver,
994 REG_MULTI_SZ))) {
995 aAdapterDriver = L"Unknown";
997 return NS_OK;
1000 NS_IMETHODIMP
1001 GfxInfo::GetAdapterDriverVendor(nsAString& aAdapterDriverVendor) {
1002 aAdapterDriverVendor.Truncate();
1003 return NS_OK;
1006 NS_IMETHODIMP
1007 GfxInfo::GetAdapterDriverVersion(nsAString& aAdapterDriverVersion) {
1008 aAdapterDriverVersion = mDriverVersion[mActiveGPUIndex];
1009 return NS_OK;
1012 NS_IMETHODIMP
1013 GfxInfo::GetAdapterDriverDate(nsAString& aAdapterDriverDate) {
1014 aAdapterDriverDate = mDriverDate[mActiveGPUIndex];
1015 return NS_OK;
1018 NS_IMETHODIMP
1019 GfxInfo::GetAdapterDriverVendor2(nsAString& aAdapterDriverVendor) {
1020 aAdapterDriverVendor.Truncate();
1021 return NS_OK;
1024 NS_IMETHODIMP
1025 GfxInfo::GetAdapterDriverVersion2(nsAString& aAdapterDriverVersion) {
1026 aAdapterDriverVersion = mDriverVersion[1 - mActiveGPUIndex];
1027 return NS_OK;
1030 NS_IMETHODIMP
1031 GfxInfo::GetAdapterDriverDate2(nsAString& aAdapterDriverDate) {
1032 aAdapterDriverDate = mDriverDate[1 - mActiveGPUIndex];
1033 return NS_OK;
1036 NS_IMETHODIMP
1037 GfxInfo::GetAdapterVendorID(nsAString& aAdapterVendorID) {
1038 aAdapterVendorID = mAdapterVendorID[mActiveGPUIndex];
1039 return NS_OK;
1042 NS_IMETHODIMP
1043 GfxInfo::GetAdapterVendorID2(nsAString& aAdapterVendorID) {
1044 aAdapterVendorID = mAdapterVendorID[1 - mActiveGPUIndex];
1045 return NS_OK;
1048 NS_IMETHODIMP
1049 GfxInfo::GetAdapterDeviceID(nsAString& aAdapterDeviceID) {
1050 aAdapterDeviceID = mAdapterDeviceID[mActiveGPUIndex];
1051 return NS_OK;
1054 NS_IMETHODIMP
1055 GfxInfo::GetAdapterDeviceID2(nsAString& aAdapterDeviceID) {
1056 aAdapterDeviceID = mAdapterDeviceID[1 - mActiveGPUIndex];
1057 return NS_OK;
1060 NS_IMETHODIMP
1061 GfxInfo::GetAdapterSubsysID(nsAString& aAdapterSubsysID) {
1062 aAdapterSubsysID = mAdapterSubsysID[mActiveGPUIndex];
1063 return NS_OK;
1066 NS_IMETHODIMP
1067 GfxInfo::GetAdapterSubsysID2(nsAString& aAdapterSubsysID) {
1068 aAdapterSubsysID = mAdapterSubsysID[1 - mActiveGPUIndex];
1069 return NS_OK;
1072 NS_IMETHODIMP
1073 GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active) {
1074 // This is never the case, as the active GPU ends up being
1075 // the first one. It should probably be removed.
1076 *aIsGPU2Active = false;
1077 return NS_OK;
1080 NS_IMETHODIMP
1081 GfxInfo::GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) {
1082 for (auto displayInfo : mDisplayInfo) {
1083 nsString value;
1084 value.AppendPrintf("%dx%d@%dHz %s %s", displayInfo.mScreenWidth,
1085 displayInfo.mScreenHeight, displayInfo.mRefreshRate,
1086 displayInfo.mIsPseudoDisplay ? "Pseudo Display :" : ":",
1087 NS_ConvertUTF16toUTF8(displayInfo.mDeviceString).get());
1089 aDisplayInfo.AppendElement(value);
1092 return NS_OK;
1095 NS_IMETHODIMP
1096 GfxInfo::GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) {
1097 for (auto displayInfo : mDisplayInfo) {
1098 aDisplayWidth.AppendElement((uint32_t)displayInfo.mScreenWidth);
1100 return NS_OK;
1103 NS_IMETHODIMP
1104 GfxInfo::GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) {
1105 for (auto displayInfo : mDisplayInfo) {
1106 aDisplayHeight.AppendElement((uint32_t)displayInfo.mScreenHeight);
1108 return NS_OK;
1111 NS_IMETHODIMP
1112 GfxInfo::GetDrmRenderDevice(nsACString& aDrmRenderDevice) {
1113 return NS_ERROR_NOT_IMPLEMENTED;
1116 /* Cisco's VPN software can cause corruption of the floating point state.
1117 * Make a note of this in our crash reports so that some weird crashes
1118 * make more sense */
1119 static void CheckForCiscoVPN() {
1120 LONG result;
1121 HKEY key;
1122 /* This will give false positives, but hopefully no false negatives */
1123 result =
1124 RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Cisco Systems\\VPN Client",
1125 0, KEY_QUERY_VALUE, &key);
1126 if (result == ERROR_SUCCESS) {
1127 RegCloseKey(key);
1128 CrashReporter::AppendAppNotesToCrashReport("Cisco VPN\n"_ns);
1132 void GfxInfo::AddCrashReportAnnotations() {
1133 CheckForCiscoVPN();
1135 if (mHasDriverVersionMismatch) {
1136 CrashReporter::AppendAppNotesToCrashReport("DriverVersionMismatch\n"_ns);
1139 nsString deviceID, vendorID, driverVersion, subsysID;
1140 nsCString narrowDeviceID, narrowVendorID, narrowDriverVersion, narrowSubsysID;
1142 GetAdapterDeviceID(deviceID);
1143 CopyUTF16toUTF8(deviceID, narrowDeviceID);
1144 GetAdapterVendorID(vendorID);
1145 CopyUTF16toUTF8(vendorID, narrowVendorID);
1146 GetAdapterDriverVersion(driverVersion);
1147 CopyUTF16toUTF8(driverVersion, narrowDriverVersion);
1148 GetAdapterSubsysID(subsysID);
1149 CopyUTF16toUTF8(subsysID, narrowSubsysID);
1151 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterVendorID,
1152 narrowVendorID);
1153 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterDeviceID,
1154 narrowDeviceID);
1155 CrashReporter::AnnotateCrashReport(
1156 CrashReporter::Annotation::AdapterDriverVersion, narrowDriverVersion);
1157 CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AdapterSubsysID,
1158 narrowSubsysID);
1160 /* Add an App Note, this contains extra information. */
1161 nsAutoCString note;
1163 // TODO: We should probably convert this into a proper annotation
1164 if (vendorID == GfxDriverInfo::GetDeviceVendor(DeviceVendor::All)) {
1165 /* if we didn't find a valid vendorID lets append the mDeviceID string to
1166 * try to find out why */
1167 LossyAppendUTF16toASCII(mDeviceID[mActiveGPUIndex], note);
1168 note.AppendLiteral(", ");
1169 LossyAppendUTF16toASCII(mDeviceKeyDebug, note);
1171 note.AppendLiteral("\n");
1173 if (mHasDualGPU) {
1174 nsString deviceID2, vendorID2, subsysID2;
1175 nsAutoString adapterDriverVersionString2;
1176 nsCString narrowDeviceID2, narrowVendorID2, narrowSubsysID2;
1178 // Make a slight difference between the two cases so that we
1179 // can see it in the crash reports. It may come in handy.
1180 if (mActiveGPUIndex == 1) {
1181 note.AppendLiteral("Has dual GPUs. GPU-#2: ");
1182 } else {
1183 note.AppendLiteral("Has dual GPUs. GPU #2: ");
1185 GetAdapterDeviceID2(deviceID2);
1186 CopyUTF16toUTF8(deviceID2, narrowDeviceID2);
1187 GetAdapterVendorID2(vendorID2);
1188 CopyUTF16toUTF8(vendorID2, narrowVendorID2);
1189 GetAdapterDriverVersion2(adapterDriverVersionString2);
1190 GetAdapterSubsysID(subsysID2);
1191 CopyUTF16toUTF8(subsysID2, narrowSubsysID2);
1192 note.AppendLiteral("AdapterVendorID2: ");
1193 note.Append(narrowVendorID2);
1194 note.AppendLiteral(", AdapterDeviceID2: ");
1195 note.Append(narrowDeviceID2);
1196 note.AppendLiteral(", AdapterSubsysID2: ");
1197 note.Append(narrowSubsysID2);
1198 note.AppendLiteral(", AdapterDriverVersion2: ");
1199 note.Append(NS_LossyConvertUTF16toASCII(adapterDriverVersionString2));
1201 CrashReporter::AppendAppNotesToCrashReport(note);
1204 static OperatingSystem WindowsVersionToOperatingSystem(
1205 int32_t aWindowsVersion) {
1206 switch (aWindowsVersion) {
1207 case kWindows7:
1208 return OperatingSystem::Windows7;
1209 case kWindows8:
1210 return OperatingSystem::Windows8;
1211 case kWindows8_1:
1212 return OperatingSystem::Windows8_1;
1213 case kWindows10:
1214 return OperatingSystem::Windows10;
1215 case kWindowsUnknown:
1216 default:
1217 return OperatingSystem::Unknown;
1221 static bool OnlyAllowFeatureOnWhitelistedVendor(int32_t aFeature) {
1222 switch (aFeature) {
1223 // The GPU process doesn't need hardware acceleration and can run on
1224 // devices that we normally block from not being on our whitelist.
1225 case nsIGfxInfo::FEATURE_GPU_PROCESS:
1226 // We can mostly assume that ANGLE will work
1227 case nsIGfxInfo::FEATURE_DIRECT3D_11_ANGLE:
1228 // Software WebRender is our Basic compositor replacement. It needs to
1229 // always work.
1230 case nsIGfxInfo::FEATURE_WEBRENDER_SOFTWARE:
1231 return false;
1232 default:
1233 return true;
1237 // Return true if the CPU supports AVX, but the operating system does not.
1238 #if defined(_M_X64)
1239 static inline bool DetectBrokenAVX() {
1240 int regs[4];
1241 __cpuid(regs, 0);
1242 if (regs[0] == 0) {
1243 // Level not supported.
1244 return false;
1247 __cpuid(regs, 1);
1249 const unsigned AVX = 1u << 28;
1250 const unsigned XSAVE = 1u << 26;
1251 if ((regs[2] & (AVX | XSAVE)) != (AVX | XSAVE)) {
1252 // AVX is not supported on this CPU.
1253 return false;
1256 const unsigned OSXSAVE = 1u << 27;
1257 if ((regs[2] & OSXSAVE) != OSXSAVE) {
1258 // AVX is supported, but the OS didn't enable it.
1259 // This can be forced via bcdedit /set xsavedisable 1.
1260 return true;
1263 const unsigned AVX_CTRL_BITS = (1 << 1) | (1 << 2);
1264 return (xgetbv(0) & AVX_CTRL_BITS) != AVX_CTRL_BITS;
1266 #endif
1268 const nsTArray<GfxDriverInfo>& GfxInfo::GetGfxDriverInfo() {
1269 if (!sDriverInfo->Length()) {
1271 * It should be noted here that more specialized rules on certain features
1272 * should be inserted -before- more generalized restriction. As the first
1273 * match for feature/OS/device found in the list will be used for the final
1274 * blocklisting call.
1278 * NVIDIA entries
1281 * The last 5 digit of the NVIDIA driver version maps to the version that
1282 * NVIDIA uses. The minor version (15, 16, 17) corresponds roughtly to the
1283 * OS (Vista, Win7, Win7) but they show up in smaller numbers across all
1284 * OS versions (perhaps due to OS upgrades). So we want to support
1285 * October 2009+ drivers across all these minor versions.
1287 * 187.45 (late October 2009) and earlier contain a bug which can cause us
1288 * to crash on shutdown.
1290 APPEND_TO_DRIVER_BLOCKLIST(
1291 OperatingSystem::Windows7, DeviceFamily::NvidiaAll,
1292 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1293 DRIVER_LESS_THAN_OR_EQUAL, V(8, 15, 11, 8745),
1294 "FEATURE_FAILURE_NV_W7_15", "nVidia driver > 187.45");
1295 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1296 OperatingSystem::Windows7, DeviceFamily::NvidiaAll,
1297 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1298 DRIVER_BETWEEN_INCLUSIVE_START, V(8, 16, 10, 0000), V(8, 16, 11, 8745),
1299 "FEATURE_FAILURE_NV_W7_16", "nVidia driver > 187.45");
1300 // Telemetry doesn't show any driver in this range so it might not even be
1301 // required.
1302 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1303 OperatingSystem::Windows7, DeviceFamily::NvidiaAll,
1304 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1305 DRIVER_BETWEEN_INCLUSIVE_START, V(8, 17, 10, 0000), V(8, 17, 11, 8745),
1306 "FEATURE_FAILURE_NV_W7_17", "nVidia driver > 187.45");
1309 * AMD/ATI entries. 8.56.1.15 is the driver that shipped with Windows 7 RTM
1311 APPEND_TO_DRIVER_BLOCKLIST(
1312 OperatingSystem::Windows, DeviceFamily::AtiAll,
1313 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1314 DRIVER_LESS_THAN, V(8, 56, 1, 15), "FEATURE_FAILURE_AMD1", "8.56.1.15");
1316 // Bug 1099252
1317 APPEND_TO_DRIVER_BLOCKLIST2(
1318 OperatingSystem::Windows7, DeviceFamily::AtiAll,
1319 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1320 DRIVER_EQUAL, V(8, 832, 0, 0), "FEATURE_FAILURE_BUG_1099252");
1322 // Bug 1118695
1323 APPEND_TO_DRIVER_BLOCKLIST2(
1324 OperatingSystem::Windows7, DeviceFamily::AtiAll,
1325 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1326 DRIVER_EQUAL, V(8, 783, 2, 2000), "FEATURE_FAILURE_BUG_1118695");
1328 // Bug 1587155
1330 // There are a several reports of strange rendering corruptions with this
1331 // driver version, with and without webrender. We weren't able to
1332 // reproduce these problems, but the users were able to update their
1333 // drivers and it went away. So just to be safe, let's blocklist all
1334 // gpu use with this particular (very old) driver, restricted
1335 // to Win10 since we only have reports from that platform.
1336 APPEND_TO_DRIVER_BLOCKLIST2(
1337 OperatingSystem::Windows10, DeviceFamily::AtiAll,
1338 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1339 DRIVER_EQUAL, V(22, 19, 162, 4), "FEATURE_FAILURE_BUG_1587155");
1341 // Bug 1198815
1342 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1343 OperatingSystem::Windows, DeviceFamily::AtiAll,
1344 nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1345 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_BETWEEN_INCLUSIVE,
1346 V(15, 200, 0, 0), V(15, 200, 1062, 1004), "FEATURE_FAILURE_BUG_1198815",
1347 "15.200.0.0-15.200.1062.1004");
1349 // Bug 1267970
1350 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1351 OperatingSystem::Windows10, DeviceFamily::AtiAll,
1352 nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1353 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_BETWEEN_INCLUSIVE,
1354 V(15, 200, 0, 0), V(15, 301, 2301, 1002), "FEATURE_FAILURE_BUG_1267970",
1355 "15.200.0.0-15.301.2301.1002");
1356 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1357 OperatingSystem::Windows10, DeviceFamily::AtiAll,
1358 nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1359 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_BETWEEN_INCLUSIVE,
1360 V(16, 100, 0, 0), V(16, 300, 2311, 0), "FEATURE_FAILURE_BUG_1267970",
1361 "16.100.0.0-16.300.2311.0");
1364 * Bug 783517 - crashes in AMD driver on Windows 8
1366 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1367 OperatingSystem::Windows8, DeviceFamily::AtiAll,
1368 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1369 DRIVER_BETWEEN_INCLUSIVE_START, V(8, 982, 0, 0), V(8, 983, 0, 0),
1370 "FEATURE_FAILURE_BUG_783517_AMD", "!= 8.982.*.*");
1373 * Bug 1599981 - crashes in AMD driver on Windows 10
1375 APPEND_TO_DRIVER_BLOCKLIST2(
1376 OperatingSystem::Windows10, DeviceFamily::RadeonCaicos,
1377 nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS,
1378 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
1379 V(15, 301, 1901, 0), "FEATURE_FAILURE_BUG_1599981");
1381 /* OpenGL on any ATI/AMD hardware is discouraged
1382 * See:
1383 * bug 619773 - WebGL: Crash with blue screen : "NMI: Parity Check / Memory
1384 * Parity Error" bugs 584403, 584404, 620924 - crashes in atioglxx
1385 * + many complaints about incorrect rendering
1387 APPEND_TO_DRIVER_BLOCKLIST2(
1388 OperatingSystem::Windows, DeviceFamily::AtiAll,
1389 nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
1390 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions,
1391 "FEATURE_FAILURE_OGL_ATI_DIS");
1394 * Intel entries
1397 /* The driver versions used here come from bug 594877. They might not
1398 * be particularly relevant anymore.
1400 #define IMPLEMENT_INTEL_DRIVER_BLOCKLIST(winVer, devFamily, driverVer, ruleId) \
1401 APPEND_TO_DRIVER_BLOCKLIST2(winVer, devFamily, GfxDriverInfo::allFeatures, \
1402 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, \
1403 DRIVER_LESS_THAN, driverVer, ruleId)
1405 #define IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(winVer, devFamily, driverVer, \
1406 ruleId) \
1407 APPEND_TO_DRIVER_BLOCKLIST2(winVer, devFamily, nsIGfxInfo::FEATURE_DIRECT2D, \
1408 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, \
1409 DRIVER_BUILD_ID_LESS_THAN, driverVer, ruleId)
1411 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7,
1412 DeviceFamily::IntelGMA500, 2026,
1413 "FEATURE_FAILURE_594877_7");
1414 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(
1415 OperatingSystem::Windows7, DeviceFamily::IntelGMA900,
1416 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_594877_8");
1417 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7,
1418 DeviceFamily::IntelGMA950, 1930,
1419 "FEATURE_FAILURE_594877_9");
1420 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7,
1421 DeviceFamily::IntelGMA3150, 2117,
1422 "FEATURE_FAILURE_594877_10");
1423 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7,
1424 DeviceFamily::IntelGMAX3000, 1930,
1425 "FEATURE_FAILURE_594877_11");
1426 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(
1427 OperatingSystem::Windows7, DeviceFamily::IntelHDGraphicsToSandyBridge,
1428 2202, "FEATURE_FAILURE_594877_12");
1430 /* Disable Direct2D on Intel GMAX4500 devices because of rendering
1431 * corruption discovered in bug 1180379. These seems to affect even the most
1432 * recent drivers. We're black listing all of the devices to be safe even
1433 * though we've only confirmed the issue on the G45
1435 APPEND_TO_DRIVER_BLOCKLIST2(
1436 OperatingSystem::Windows, DeviceFamily::IntelGMAX4500HD,
1437 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1438 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions,
1439 "FEATURE_FAILURE_1180379");
1441 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(
1442 OperatingSystem::Windows7, DeviceFamily::IntelGMA500, V(5, 0, 0, 2026),
1443 "FEATURE_FAILURE_INTEL_16");
1444 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(
1445 OperatingSystem::Windows7, DeviceFamily::IntelGMA900,
1446 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_INTEL_17");
1447 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(
1448 OperatingSystem::Windows7, DeviceFamily::IntelGMA950,
1449 V(8, 15, 10, 1930), "FEATURE_FAILURE_INTEL_18");
1450 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(
1451 OperatingSystem::Windows7, DeviceFamily::IntelGMA3150,
1452 V(8, 14, 10, 1972), "FEATURE_FAILURE_INTEL_19");
1453 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(
1454 OperatingSystem::Windows7, DeviceFamily::IntelGMAX3000,
1455 V(7, 15, 10, 1666), "FEATURE_FAILURE_INTEL_20");
1456 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(
1457 OperatingSystem::Windows7, DeviceFamily::IntelGMAX4500HD,
1458 V(7, 15, 10, 1666), "FEATURE_FAILURE_INTEL_21");
1459 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(
1460 OperatingSystem::Windows7, DeviceFamily::IntelHDGraphicsToSandyBridge,
1461 V(7, 15, 10, 1666), "FEATURE_FAILURE_INTEL_22");
1463 // Bug 1074378
1464 APPEND_TO_DRIVER_BLOCKLIST(
1465 OperatingSystem::Windows7, DeviceFamily::IntelGMAX4500HD,
1466 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1467 DRIVER_EQUAL, V(8, 15, 10, 1749), "FEATURE_FAILURE_BUG_1074378_1",
1468 "8.15.10.2342");
1469 APPEND_TO_DRIVER_BLOCKLIST(
1470 OperatingSystem::Windows7, DeviceFamily::IntelHDGraphicsToSandyBridge,
1471 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1472 DRIVER_EQUAL, V(8, 15, 10, 1749), "FEATURE_FAILURE_BUG_1074378_2",
1473 "8.15.10.2342");
1475 /* OpenGL on any Intel hardware is discouraged */
1476 APPEND_TO_DRIVER_BLOCKLIST2(
1477 OperatingSystem::Windows, DeviceFamily::IntelAll,
1478 nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
1479 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions,
1480 "FEATURE_FAILURE_INTEL_OGL_DIS");
1483 * Disable acceleration on Intel HD 3000 for graphics drivers
1484 * <= 8.15.10.2321. See bug 1018278 and bug 1060736.
1486 APPEND_TO_DRIVER_BLOCKLIST(
1487 OperatingSystem::Windows, DeviceFamily::IntelSandyBridge,
1488 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1489 DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL, 2321, "FEATURE_FAILURE_BUG_1018278",
1490 "X.X.X.2342");
1493 * Disable D2D on Win7 on Intel Haswell for graphics drivers build id <=
1494 * 4578. See bug 1432610
1496 APPEND_TO_DRIVER_BLOCKLIST2(OperatingSystem::Windows7,
1497 DeviceFamily::IntelHaswell,
1498 nsIGfxInfo::FEATURE_DIRECT2D,
1499 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1500 DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL, 4578,
1501 "FEATURE_FAILURE_BUG_1432610");
1503 /* Disable D2D on Win7 on Intel HD Graphics on driver <= 8.15.10.2302
1504 * See bug 806786
1506 APPEND_TO_DRIVER_BLOCKLIST2(
1507 OperatingSystem::Windows7, DeviceFamily::IntelMobileHDGraphics,
1508 nsIGfxInfo::FEATURE_DIRECT2D,
1509 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN_OR_EQUAL,
1510 V(8, 15, 10, 2302), "FEATURE_FAILURE_BUG_806786");
1512 /* Disable D2D on Win8 on Intel HD Graphics on driver <= 8.15.10.2302
1513 * See bug 804144 and 863683
1515 APPEND_TO_DRIVER_BLOCKLIST2(
1516 OperatingSystem::Windows8, DeviceFamily::IntelMobileHDGraphics,
1517 nsIGfxInfo::FEATURE_DIRECT2D,
1518 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN_OR_EQUAL,
1519 V(8, 15, 10, 2302), "FEATURE_FAILURE_BUG_804144");
1521 /* Disable D2D on Win7 on Intel HD Graphics on driver == 8.15.10.2418
1522 * See bug 1433790
1524 APPEND_TO_DRIVER_BLOCKLIST2(
1525 OperatingSystem::Windows7, DeviceFamily::IntelHDGraphicsToSandyBridge,
1526 nsIGfxInfo::FEATURE_DIRECT2D,
1527 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_EQUAL,
1528 V(8, 15, 10, 2418), "FEATURE_FAILURE_BUG_1433790");
1530 /* Disable D3D11 layers on Intel G41 express graphics and Intel GM965, Intel
1531 * X3100, for causing device resets. See bug 1116812.
1533 APPEND_TO_DRIVER_BLOCKLIST2(
1534 OperatingSystem::Windows, DeviceFamily::Bug1116812,
1535 nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS,
1536 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_LESS_THAN,
1537 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_BUG_1116812");
1539 /* Disable D3D11 layers on Intel GMA 3150 for failing to allocate a shared
1540 * handle for textures. See bug 1207665. Additionally block D2D so we don't
1541 * accidentally use WARP.
1543 APPEND_TO_DRIVER_BLOCKLIST2(
1544 OperatingSystem::Windows, DeviceFamily::Bug1207665,
1545 nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS,
1546 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_LESS_THAN,
1547 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_BUG_1207665_1");
1548 APPEND_TO_DRIVER_BLOCKLIST2(
1549 OperatingSystem::Windows, DeviceFamily::Bug1207665,
1550 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1551 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions,
1552 "FEATURE_FAILURE_BUG_1207665_2");
1554 APPEND_TO_DRIVER_BLOCKLIST2(
1555 OperatingSystem::Windows10, DeviceFamily::QualcommAll,
1556 nsIGfxInfo::FEATURE_DIRECT2D,
1557 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
1558 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_QUALCOMM");
1560 // Bug 1548410. Disable hardware accelerated video decoding on
1561 // Qualcomm drivers used on Windows on ARM64 which are known to
1562 // cause BSOD's and output suprious green frames while decoding video.
1563 // Bug 1592826 expands the blocklist.
1564 APPEND_TO_DRIVER_BLOCKLIST2(
1565 OperatingSystem::Windows10, DeviceFamily::QualcommAll,
1566 nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1567 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN_OR_EQUAL,
1568 V(25, 18, 10440, 0), "FEATURE_FAILURE_BUG_1592826");
1570 /* Disable D2D on AMD Catalyst 14.4 until 14.6
1571 * See bug 984488
1573 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1574 OperatingSystem::Windows, DeviceFamily::AtiAll,
1575 nsIGfxInfo::FEATURE_DIRECT2D,
1576 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1577 DRIVER_BETWEEN_INCLUSIVE_START, V(14, 1, 0, 0), V(14, 2, 0, 0),
1578 "FEATURE_FAILURE_BUG_984488_1", "ATI Catalyst 14.6+");
1580 /* Disable D3D9 layers on NVIDIA 6100/6150/6200 series due to glitches
1581 * whilst scrolling. See bugs: 612007, 644787 & 645872.
1583 APPEND_TO_DRIVER_BLOCKLIST2(
1584 OperatingSystem::Windows, DeviceFamily::NvidiaBlockD3D9Layers,
1585 nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS,
1586 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_LESS_THAN,
1587 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_BUG_612007");
1589 /* Microsoft RemoteFX; blocked less than 6.2.0.0 */
1590 APPEND_TO_DRIVER_BLOCKLIST(
1591 OperatingSystem::Windows, DeviceFamily::MicrosoftAll,
1592 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1593 DRIVER_LESS_THAN, V(6, 2, 0, 0), "< 6.2.0.0",
1594 "FEATURE_FAILURE_REMOTE_FX");
1596 /* Bug 1008759: Optimus (NVidia) crash. Disable D2D on NV 310M. */
1597 APPEND_TO_DRIVER_BLOCKLIST2(
1598 OperatingSystem::Windows, DeviceFamily::Nvidia310M,
1599 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1600 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions,
1601 "FEATURE_FAILURE_BUG_1008759");
1603 /* Bug 1139503: DXVA crashes with ATI cards on windows 10. */
1604 APPEND_TO_DRIVER_BLOCKLIST2(
1605 OperatingSystem::Windows10, DeviceFamily::AtiAll,
1606 nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1607 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_EQUAL,
1608 V(15, 200, 1006, 0), "FEATURE_FAILURE_BUG_1139503");
1610 /* Bug 1213107: D3D9 crashes with ATI cards on Windows 7. */
1611 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1612 OperatingSystem::Windows7, DeviceFamily::AtiAll,
1613 nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1614 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_BETWEEN_INCLUSIVE,
1615 V(8, 861, 0, 0), V(8, 862, 6, 5000), "FEATURE_FAILURE_BUG_1213107_1",
1616 "Radeon driver > 8.862.6.5000");
1617 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1618 OperatingSystem::Windows7, DeviceFamily::AtiAll,
1619 nsIGfxInfo::FEATURE_WEBGL_ANGLE,
1620 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_BETWEEN_INCLUSIVE,
1621 V(8, 861, 0, 0), V(8, 862, 6, 5000), "FEATURE_FAILURE_BUG_1213107_2",
1622 "Radeon driver > 8.862.6.5000");
1624 /* This may not be needed at all */
1625 APPEND_TO_DRIVER_BLOCKLIST2(
1626 OperatingSystem::Windows7, DeviceFamily::Bug1155608,
1627 nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1628 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
1629 V(8, 15, 10, 2869), "FEATURE_FAILURE_INTEL_W7_HW_DECODING");
1631 /* Bug 1203199/1092166: DXVA startup crashes on some intel drivers. */
1632 APPEND_TO_DRIVER_BLOCKLIST(OperatingSystem::Windows, DeviceFamily::IntelAll,
1633 nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1634 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1635 DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL, 2849,
1636 "FEATURE_FAILURE_BUG_1203199_1",
1637 "Intel driver > X.X.X.2849");
1639 APPEND_TO_DRIVER_BLOCKLIST2(
1640 OperatingSystem::Windows, DeviceFamily::Nvidia8800GTS,
1641 nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1642 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_EQUAL,
1643 V(9, 18, 13, 4052), "FEATURE_FAILURE_BUG_1203199_2");
1645 /* Bug 1137716: XXX this should really check for the matching Intel piece as
1646 * well. Unfortunately, we don't have the infrastructure to do that */
1647 APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2(
1648 OperatingSystem::Windows7, DeviceFamily::Bug1137716,
1649 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1650 DRIVER_BETWEEN_INCLUSIVE, V(8, 17, 12, 5730), V(8, 17, 12, 6901),
1651 "FEATURE_FAILURE_BUG_1137716", "Nvidia driver > 8.17.12.6901");
1653 /* Bug 1153381: WebGL issues with D3D11 ANGLE on Intel. These may be fixed
1654 * by an ANGLE update. */
1655 APPEND_TO_DRIVER_BLOCKLIST2(
1656 OperatingSystem::Windows, DeviceFamily::IntelGMAX4500HD,
1657 nsIGfxInfo::FEATURE_DIRECT3D_11_ANGLE,
1658 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_LESS_THAN,
1659 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_BUG_1153381");
1661 /* Bug 1336710: Crash in rx::Blit9::initialize. */
1662 APPEND_TO_DRIVER_BLOCKLIST2(
1663 OperatingSystem::WindowsXP, DeviceFamily::IntelGMAX4500HD,
1664 nsIGfxInfo::FEATURE_WEBGL_ANGLE, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1665 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions,
1666 "FEATURE_FAILURE_BUG_1336710");
1668 APPEND_TO_DRIVER_BLOCKLIST2(
1669 OperatingSystem::WindowsXP, DeviceFamily::IntelHDGraphicsToSandyBridge,
1670 nsIGfxInfo::FEATURE_WEBGL_ANGLE, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1671 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions,
1672 "FEATURE_FAILURE_BUG_1336710");
1674 /* Bug 1304360: Graphical artifacts with D3D9 on Windows 7. */
1675 APPEND_TO_DRIVER_BLOCKLIST2(OperatingSystem::Windows7,
1676 DeviceFamily::IntelGMAX3000,
1677 nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS,
1678 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1679 DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL, 1749,
1680 "FEATURE_FAILURE_INTEL_W7_D3D9_LAYERS");
1682 #if defined(_M_X64)
1683 if (DetectBrokenAVX()) {
1684 APPEND_TO_DRIVER_BLOCKLIST2(
1685 OperatingSystem::Windows7, DeviceFamily::IntelAll,
1686 nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS,
1687 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
1688 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_BUG_1403353");
1690 #endif
1692 ////////////////////////////////////
1693 // WebGL
1695 // Older than 5-15-2016
1696 APPEND_TO_DRIVER_BLOCKLIST2(
1697 OperatingSystem::Windows, DeviceFamily::AtiAll,
1698 nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
1699 DRIVER_LESS_THAN, V(16, 200, 1010, 1002), "WEBGL_NATIVE_GL_OLD_AMD");
1701 // Older than 11-18-2015
1702 APPEND_TO_DRIVER_BLOCKLIST2(
1703 OperatingSystem::Windows, DeviceFamily::IntelAll,
1704 nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
1705 DRIVER_BUILD_ID_LESS_THAN, 4331, "WEBGL_NATIVE_GL_OLD_INTEL");
1707 // Older than 2-23-2016
1708 APPEND_TO_DRIVER_BLOCKLIST2(
1709 OperatingSystem::Windows, DeviceFamily::NvidiaAll,
1710 nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
1711 DRIVER_LESS_THAN, V(10, 18, 13, 6200), "WEBGL_NATIVE_GL_OLD_NVIDIA");
1713 ////////////////////////////////////
1714 // FEATURE_DX_INTEROP2
1716 // All AMD.
1717 APPEND_TO_DRIVER_BLOCKLIST2(
1718 OperatingSystem::Windows, DeviceFamily::AtiAll,
1719 nsIGfxInfo::FEATURE_DX_INTEROP2,
1720 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
1721 GfxDriverInfo::allDriverVersions, "DX_INTEROP2_AMD_CRASH");
1723 ////////////////////////////////////
1724 // FEATURE_D3D11_KEYED_MUTEX
1726 // bug 1359416
1727 APPEND_TO_DRIVER_BLOCKLIST2(
1728 OperatingSystem::Windows, DeviceFamily::IntelHDGraphicsToSandyBridge,
1729 nsIGfxInfo::FEATURE_D3D11_KEYED_MUTEX,
1730 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_LESS_THAN,
1731 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_BUG_1359416");
1733 // Bug 1447141, for causing device creation crashes.
1734 APPEND_TO_DRIVER_BLOCKLIST2(
1735 OperatingSystem::Windows7, DeviceFamily::Bug1447141,
1736 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1737 DRIVER_EQUAL, V(15, 201, 2201, 0), "FEATURE_FAILURE_BUG_1447141_1");
1738 APPEND_TO_DRIVER_BLOCKLIST2(
1739 OperatingSystem::Windows7, DeviceFamily::Bug1447141,
1740 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1741 DRIVER_EQUAL, V(15, 201, 1701, 0), "FEATURE_FAILURE_BUG_1447141_1");
1743 // bug 1457758
1744 APPEND_TO_DRIVER_BLOCKLIST2(
1745 OperatingSystem::Windows, DeviceFamily::NvidiaAll,
1746 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1747 DRIVER_EQUAL, V(24, 21, 13, 9731), "FEATURE_FAILURE_BUG_1457758");
1749 ////////////////////////////////////
1750 // FEATURE_DX_NV12
1752 // Bug 1437334
1753 APPEND_TO_DRIVER_BLOCKLIST2(
1754 OperatingSystem::Windows, DeviceFamily::IntelHDGraphicsToSandyBridge,
1755 nsIGfxInfo::FEATURE_DX_NV12, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1756 DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL, 4459,
1757 "FEATURE_BLOCKED_DRIVER_VERSION");
1759 ////////////////////////////////////
1760 // FEATURE_DX_P010
1762 APPEND_TO_DRIVER_BLOCKLIST2(
1763 OperatingSystem::Windows, DeviceFamily::NvidiaAll,
1764 nsIGfxInfo::FEATURE_DX_P010, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1765 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions,
1766 "FEATURE_UNQUALIFIED_P010_NVIDIA");
1768 ////////////////////////////////////
1769 // FEATURE_WEBRENDER
1770 #ifndef EARLY_BETA_OR_EARLIER
1771 // Block some specific Nvidia cards for being too low-powered.
1772 APPEND_TO_DRIVER_BLOCKLIST2(
1773 OperatingSystem::Windows, DeviceFamily::NvidiaBlockWebRender,
1774 nsIGfxInfo::FEATURE_WEBRENDER, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1775 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions,
1776 "FEATURE_UNQUALIFIED_WEBRENDER_NVIDIA_BLOCKED");
1777 #endif
1779 // Block 8.56.1.15/16
1780 APPEND_TO_DRIVER_BLOCKLIST2(OperatingSystem::Windows, DeviceFamily::AtiAll,
1781 nsIGfxInfo::FEATURE_WEBRENDER,
1782 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1783 DRIVER_LESS_THAN_OR_EQUAL, V(8, 56, 1, 16),
1784 "CRASHY_DRIVERS_BUG_1678808");
1786 ////////////////////////////////////
1787 // FEATURE_WEBRENDER - ALLOWLIST
1788 APPEND_TO_DRIVER_BLOCKLIST2_EXT(
1789 OperatingSystem::Windows, ScreenSizeStatus::All, BatteryStatus::All,
1790 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::All,
1791 DeviceFamily::AmdR600, nsIGfxInfo::FEATURE_WEBRENDER,
1792 nsIGfxInfo::FEATURE_ALLOW_ALWAYS, DRIVER_COMPARISON_IGNORED,
1793 V(0, 0, 0, 0), "FEATURE_ROLLOUT_AMD_R600");
1795 APPEND_TO_DRIVER_BLOCKLIST2_EXT(
1796 OperatingSystem::Windows, ScreenSizeStatus::All, BatteryStatus::All,
1797 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::All,
1798 DeviceFamily::AtiRolloutWebRender, nsIGfxInfo::FEATURE_WEBRENDER,
1799 nsIGfxInfo::FEATURE_ALLOW_ALWAYS, DRIVER_COMPARISON_IGNORED,
1800 V(0, 0, 0, 0), "FEATURE_ROLLOUT_DESKTOP_AMD");
1802 APPEND_TO_DRIVER_BLOCKLIST2_EXT(
1803 OperatingSystem::Windows, ScreenSizeStatus::All, BatteryStatus::All,
1804 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::All,
1805 DeviceFamily::NvidiaRolloutWebRender, nsIGfxInfo::FEATURE_WEBRENDER,
1806 nsIGfxInfo::FEATURE_ALLOW_ALWAYS, DRIVER_COMPARISON_IGNORED,
1807 V(0, 0, 0, 0), "FEATURE_ROLLOUT_NV");
1809 APPEND_TO_DRIVER_BLOCKLIST2_EXT(
1810 OperatingSystem::Windows, ScreenSizeStatus::All, BatteryStatus::All,
1811 DesktopEnvironment::All, WindowProtocol::All, DriverVendor::All,
1812 DeviceFamily::IntelRolloutWebRender, nsIGfxInfo::FEATURE_WEBRENDER,
1813 nsIGfxInfo::FEATURE_ALLOW_ALWAYS, DRIVER_COMPARISON_IGNORED,
1814 V(0, 0, 0, 0), "FEATURE_ROLLOUT_INTEL");
1816 ////////////////////////////////////
1817 // FEATURE_WEBRENDER_COMPOSITOR
1819 #ifndef EARLY_BETA_OR_EARLIER
1820 // See also bug 161687
1821 APPEND_TO_DRIVER_BLOCKLIST2(
1822 OperatingSystem::Windows, DeviceFamily::IntelAll,
1823 nsIGfxInfo::FEATURE_WEBRENDER_COMPOSITOR,
1824 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_EQUAL, V(24, 20, 100, 6293),
1825 "FEATURE_FAILURE_BUG_1602511");
1827 APPEND_TO_DRIVER_BLOCKLIST2(OperatingSystem::Windows, DeviceFamily::AtiAll,
1828 nsIGfxInfo::FEATURE_WEBRENDER_COMPOSITOR,
1829 nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1830 DRIVER_LESS_THAN_OR_EQUAL, V(8, 17, 10, 1129),
1831 "FEATURE_FAILURE_CHROME_BUG_800950");
1832 #endif
1834 // WebRender is unable to use scissored clears in some cases
1835 APPEND_TO_DRIVER_BLOCKLIST2(
1836 OperatingSystem::Windows, DeviceFamily::IntelAll,
1837 nsIGfxInfo::FEATURE_WEBRENDER_SCISSORED_CACHE_CLEARS,
1838 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
1839 V(0, 0, 0, 0), "FEATURE_FAILURE_BUG_1603515");
1841 ////////////////////////////////////
1842 // FEATURE_WEBRENDER_SOFTWARE
1844 // TODO(aosmond): Bug 1678044 - wdspec tests ignore enable/disable-webrender
1845 // Once the test infrastructure is fixed, we can remove this blocklist rule
1846 APPEND_TO_DRIVER_BLOCKLIST2(
1847 OperatingSystem::Windows, DeviceFamily::AmazonAll,
1848 nsIGfxInfo::FEATURE_WEBRENDER_SOFTWARE,
1849 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED,
1850 V(0, 0, 0, 0), "FEATURE_FAILURE_BUG_1678044");
1852 ////////////////////////////////////
1853 // FEATURE_WEBRENDER_SOFTWARE - ALLOWLIST
1854 #ifdef EARLY_BETA_OR_EARLIER
1855 # if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \
1856 defined(__i386) || defined(__amd64__)
1857 APPEND_TO_DRIVER_BLOCKLIST2(OperatingSystem::Windows, DeviceFamily::All,
1858 nsIGfxInfo::FEATURE_WEBRENDER_SOFTWARE,
1859 nsIGfxInfo::FEATURE_ALLOW_ALWAYS,
1860 DRIVER_COMPARISON_IGNORED, V(0, 0, 0, 0),
1861 "FEATURE_ROLLOUT_NIGHTLY_SOFTWARE_WR_S_M_SCRN");
1862 # endif
1863 #endif
1865 return *sDriverInfo;
1868 nsresult GfxInfo::GetFeatureStatusImpl(
1869 int32_t aFeature, int32_t* aStatus, nsAString& aSuggestedDriverVersion,
1870 const nsTArray<GfxDriverInfo>& aDriverInfo, nsACString& aFailureId,
1871 OperatingSystem* aOS /* = nullptr */) {
1872 NS_ENSURE_ARG_POINTER(aStatus);
1873 aSuggestedDriverVersion.SetIsVoid(true);
1874 OperatingSystem os = WindowsVersionToOperatingSystem(mWindowsVersion);
1875 *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
1876 if (aOS) *aOS = os;
1878 if (sShutdownOccurred) {
1879 return NS_OK;
1882 // Don't evaluate special cases if we're checking the downloaded blocklist.
1883 if (!aDriverInfo.Length()) {
1884 nsAutoString adapterVendorID;
1885 nsAutoString adapterDeviceID;
1886 nsAutoString adapterDriverVersionString;
1887 if (NS_FAILED(GetAdapterVendorID(adapterVendorID)) ||
1888 NS_FAILED(GetAdapterDeviceID(adapterDeviceID)) ||
1889 NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString))) {
1890 aFailureId = "FEATURE_FAILURE_GET_ADAPTER";
1891 *aStatus = FEATURE_BLOCKED_DEVICE;
1892 return NS_OK;
1895 if (OnlyAllowFeatureOnWhitelistedVendor(aFeature) &&
1896 !adapterVendorID.Equals(
1897 GfxDriverInfo::GetDeviceVendor(DeviceVendor::Intel),
1898 nsCaseInsensitiveStringComparator) &&
1899 !adapterVendorID.Equals(
1900 GfxDriverInfo::GetDeviceVendor(DeviceVendor::NVIDIA),
1901 nsCaseInsensitiveStringComparator) &&
1902 !adapterVendorID.Equals(
1903 GfxDriverInfo::GetDeviceVendor(DeviceVendor::ATI),
1904 nsCaseInsensitiveStringComparator) &&
1905 !adapterVendorID.Equals(
1906 GfxDriverInfo::GetDeviceVendor(DeviceVendor::Microsoft),
1907 nsCaseInsensitiveStringComparator) &&
1908 !adapterVendorID.Equals(
1909 GfxDriverInfo::GetDeviceVendor(DeviceVendor::Parallels),
1910 nsCaseInsensitiveStringComparator) &&
1911 !adapterVendorID.Equals(
1912 GfxDriverInfo::GetDeviceVendor(DeviceVendor::Qualcomm),
1913 nsCaseInsensitiveStringComparator) &&
1914 // FIXME - these special hex values are currently used in xpcshell tests
1915 // introduced by bug 625160 patch 8/8. Maybe these tests need to be
1916 // adjusted now that we're only whitelisting intel/ati/nvidia.
1917 !adapterVendorID.LowerCaseEqualsLiteral("0xabcd") &&
1918 !adapterVendorID.LowerCaseEqualsLiteral("0xdcba") &&
1919 !adapterVendorID.LowerCaseEqualsLiteral("0xabab") &&
1920 !adapterVendorID.LowerCaseEqualsLiteral("0xdcdc")) {
1921 if (adapterVendorID.Equals(
1922 GfxDriverInfo::GetDeviceVendor(DeviceVendor::MicrosoftHyperV),
1923 nsCaseInsensitiveStringComparator) ||
1924 adapterVendorID.Equals(
1925 GfxDriverInfo::GetDeviceVendor(DeviceVendor::VMWare),
1926 nsCaseInsensitiveStringComparator) ||
1927 adapterVendorID.Equals(
1928 GfxDriverInfo::GetDeviceVendor(DeviceVendor::VirtualBox),
1929 nsCaseInsensitiveStringComparator)) {
1930 aFailureId = "FEATURE_FAILURE_VM_VENDOR";
1931 } else if (adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(
1932 DeviceVendor::MicrosoftBasic),
1933 nsCaseInsensitiveStringComparator)) {
1934 aFailureId = "FEATURE_FAILURE_MICROSOFT_BASIC_VENDOR";
1935 } else if (adapterVendorID.IsEmpty()) {
1936 aFailureId = "FEATURE_FAILURE_EMPTY_DEVICE_VENDOR";
1937 } else {
1938 aFailureId = "FEATURE_FAILURE_UNKNOWN_DEVICE_VENDOR";
1940 *aStatus = FEATURE_BLOCKED_DEVICE;
1941 return NS_OK;
1944 uint64_t driverVersion;
1945 if (!ParseDriverVersion(adapterDriverVersionString, &driverVersion)) {
1946 aFailureId = "FEATURE_FAILURE_PARSE_DRIVER";
1947 *aStatus = FEATURE_BLOCKED_DRIVER_VERSION;
1948 return NS_OK;
1951 if (mHasDriverVersionMismatch) {
1952 *aStatus = nsIGfxInfo::FEATURE_BLOCKED_MISMATCHED_VERSION;
1953 return NS_OK;
1957 return GfxInfoBase::GetFeatureStatusImpl(
1958 aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aFailureId, &os);
1961 nsresult GfxInfo::FindMonitors(JSContext* aCx, JS::HandleObject aOutArray) {
1962 int deviceCount = 0;
1963 for (auto displayInfo : mDisplayInfo) {
1964 JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
1966 JS::Rooted<JS::Value> screenWidth(aCx,
1967 JS::Int32Value(displayInfo.mScreenWidth));
1968 JS_SetProperty(aCx, obj, "screenWidth", screenWidth);
1970 JS::Rooted<JS::Value> screenHeight(
1971 aCx, JS::Int32Value(displayInfo.mScreenHeight));
1972 JS_SetProperty(aCx, obj, "screenHeight", screenHeight);
1974 JS::Rooted<JS::Value> refreshRate(aCx,
1975 JS::Int32Value(displayInfo.mRefreshRate));
1976 JS_SetProperty(aCx, obj, "refreshRate", refreshRate);
1978 JS::Rooted<JS::Value> pseudoDisplay(
1979 aCx, JS::BooleanValue(displayInfo.mIsPseudoDisplay));
1980 JS_SetProperty(aCx, obj, "pseudoDisplay", pseudoDisplay);
1982 JS::Rooted<JS::Value> element(aCx, JS::ObjectValue(*obj));
1983 JS_SetElement(aCx, aOutArray, deviceCount++, element);
1985 return NS_OK;
1988 void GfxInfo::DescribeFeatures(JSContext* aCx, JS::Handle<JSObject*> aObj) {
1989 // Add the platform neutral features
1990 GfxInfoBase::DescribeFeatures(aCx, aObj);
1992 JS::Rooted<JSObject*> obj(aCx);
1994 gfx::FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING);
1995 if (!InitFeatureObject(aCx, aObj, "d3d11", d3d11, &obj)) {
1996 return;
1998 if (d3d11.GetValue() == gfx::FeatureStatus::Available) {
1999 DeviceManagerDx* dm = DeviceManagerDx::Get();
2000 JS::Rooted<JS::Value> val(aCx,
2001 JS::Int32Value(dm->GetCompositorFeatureLevel()));
2002 JS_SetProperty(aCx, obj, "version", val);
2004 val = JS::BooleanValue(dm->IsWARP());
2005 JS_SetProperty(aCx, obj, "warp", val);
2007 val = JS::BooleanValue(dm->TextureSharingWorks());
2008 JS_SetProperty(aCx, obj, "textureSharing", val);
2010 bool blocklisted = false;
2011 if (nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service()) {
2012 int32_t status;
2013 nsCString discardFailureId;
2014 if (SUCCEEDED(
2015 gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS,
2016 discardFailureId, &status))) {
2017 blocklisted = (status != nsIGfxInfo::FEATURE_STATUS_OK);
2021 val = JS::BooleanValue(blocklisted);
2022 JS_SetProperty(aCx, obj, "blocklisted", val);
2025 gfx::FeatureState& d2d = gfxConfig::GetFeature(Feature::DIRECT2D);
2026 if (!InitFeatureObject(aCx, aObj, "d2d", d2d, &obj)) {
2027 return;
2030 const char* version = "1.1";
2031 JS::Rooted<JSString*> str(aCx, JS_NewStringCopyZ(aCx, version));
2032 JS::Rooted<JS::Value> val(aCx, JS::StringValue(str));
2033 JS_SetProperty(aCx, obj, "version", val);
2037 #ifdef DEBUG
2039 // Implement nsIGfxInfoDebug
2041 NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString& aVendorID) {
2042 mAdapterVendorID[mActiveGPUIndex] = aVendorID;
2043 return NS_OK;
2046 NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString& aDeviceID) {
2047 mAdapterDeviceID[mActiveGPUIndex] = aDeviceID;
2048 return NS_OK;
2051 NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString& aDriverVersion) {
2052 mDriverVersion[mActiveGPUIndex] = aDriverVersion;
2053 return NS_OK;
2056 NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion) {
2057 mWindowsVersion = aVersion;
2058 return NS_OK;
2061 NS_IMETHODIMP GfxInfo::FireTestProcess() { return NS_OK; }
2063 #endif