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/. */
5
6 #include "mozilla/ArrayUtils.h"
7
8 #include <windows.h>
9 #include <setupapi.h>
10 #include "gfxConfig.h"
11 #include "gfxWindowsPlatform.h"
12 #include "GfxInfo.h"
13 #include "nsUnicharUtils.h"
14 #include "prenv.h"
15 #include "prprf.h"
16 #include "GfxDriverInfo.h"
17 #include "mozilla/Preferences.h"
18 #include "mozilla/gfx/DeviceManagerDx.h"
19 #include "mozilla/gfx/Logging.h"
20 #include "nsExceptionHandler.h"
21 #include "nsICrashReporter.h"
22 #include "nsPrintfCString.h"
23 #include "jsapi.h"
24 #include <intrin.h>
25
26 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
27
28 using namespace mozilla;
29 using namespace mozilla::gfx;
30 using namespace mozilla::widget;
31
32 #ifdef DEBUG
33 NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug)
34 #endif
35
36 static const uint32_t allWindowsVersions = 0xffffffff;
37
GfxInfo()38 GfxInfo::GfxInfo()
39 : mWindowsVersion(0), mActiveGPUIndex(0), mHasDualGPU(false) {}
40
41 /* GetD2DEnabled and GetDwriteEnabled shouldn't be called until after
42 * gfxPlatform initialization has occurred because they depend on it for
43 * information. (See bug 591561) */
GetD2DEnabled(bool * aEnabled)44 nsresult GfxInfo::GetD2DEnabled(bool* aEnabled) {
45 // Telemetry queries this during XPCOM initialization, and there's no
46 // gfxPlatform by then. Just bail out if gfxPlatform isn't initialized.
47 if (!gfxPlatform::Initialized()) {
48 *aEnabled = false;
49 return NS_OK;
50 }
51
52 // We check gfxConfig rather than the actual render mode, since the UI
53 // process does not use Direct2D if the GPU process is enabled. However,
54 // content processes can still use Direct2D.
55 *aEnabled = gfx::gfxConfig::IsEnabled(gfx::Feature::DIRECT2D);
56 return NS_OK;
57 }
58
GetDWriteEnabled(bool * aEnabled)59 nsresult GfxInfo::GetDWriteEnabled(bool* aEnabled) {
60 *aEnabled = gfxWindowsPlatform::GetPlatform()->DWriteEnabled();
61 return NS_OK;
62 }
63
64 NS_IMETHODIMP
GetDWriteVersion(nsAString & aDwriteVersion)65 GfxInfo::GetDWriteVersion(nsAString& aDwriteVersion) {
66 gfxWindowsPlatform::GetDLLVersion(L"dwrite.dll", aDwriteVersion);
67 return NS_OK;
68 }
69
70 #define PIXEL_STRUCT_RGB 1
71 #define PIXEL_STRUCT_BGR 2
72
73 NS_IMETHODIMP
GetCleartypeParameters(nsAString & aCleartypeParams)74 GfxInfo::GetCleartypeParameters(nsAString& aCleartypeParams) {
75 nsTArray<ClearTypeParameterInfo> clearTypeParams;
76
77 gfxWindowsPlatform::GetPlatform()->GetCleartypeParams(clearTypeParams);
78 uint32_t d, numDisplays = clearTypeParams.Length();
79 bool displayNames = (numDisplays > 1);
80 bool foundData = false;
81 nsString outStr;
82
83 for (d = 0; d < numDisplays; d++) {
84 ClearTypeParameterInfo& params = clearTypeParams[d];
85
86 if (displayNames) {
87 outStr.AppendPrintf("%S [ ", params.displayName.get());
88 }
89
90 if (params.gamma >= 0) {
91 foundData = true;
92 outStr.AppendPrintf("Gamma: %.4g ", params.gamma / 1000.0);
93 }
94
95 if (params.pixelStructure >= 0) {
96 foundData = true;
97 if (params.pixelStructure == PIXEL_STRUCT_RGB ||
98 params.pixelStructure == PIXEL_STRUCT_BGR) {
99 outStr.AppendPrintf(
100 "Pixel Structure: %S ",
101 (params.pixelStructure == PIXEL_STRUCT_RGB ? u"RGB" : u"BGR"));
102 } else {
103 outStr.AppendPrintf("Pixel Structure: %d ", params.pixelStructure);
104 }
105 }
106
107 if (params.clearTypeLevel >= 0) {
108 foundData = true;
109 outStr.AppendPrintf("ClearType Level: %d ", params.clearTypeLevel);
110 }
111
112 if (params.enhancedContrast >= 0) {
113 foundData = true;
114 outStr.AppendPrintf("Enhanced Contrast: %d ", params.enhancedContrast);
115 }
116
117 if (displayNames) {
118 outStr.Append(u"] ");
119 }
120 }
121
122 if (foundData) {
123 aCleartypeParams.Assign(outStr);
124 return NS_OK;
125 }
126 return NS_ERROR_FAILURE;
127 }
128
GetKeyValue(const WCHAR * keyLocation,const WCHAR * keyName,nsAString & destString,int type)129 static nsresult GetKeyValue(const WCHAR* keyLocation, const WCHAR* keyName,
130 nsAString& destString, int type) {
131 HKEY key;
132 DWORD dwcbData;
133 DWORD dValue;
134 DWORD resultType;
135 LONG result;
136 nsresult retval = NS_OK;
137
138 result =
139 RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyLocation, 0, KEY_QUERY_VALUE, &key);
140 if (result != ERROR_SUCCESS) {
141 return NS_ERROR_FAILURE;
142 }
143
144 switch (type) {
145 case REG_DWORD: {
146 // We only use this for vram size
147 dwcbData = sizeof(dValue);
148 result = RegQueryValueExW(key, keyName, nullptr, &resultType,
149 (LPBYTE)&dValue, &dwcbData);
150 if (result == ERROR_SUCCESS && resultType == REG_DWORD) {
151 dValue = dValue / 1024 / 1024;
152 destString.AppendInt(int32_t(dValue));
153 } else {
154 retval = NS_ERROR_FAILURE;
155 }
156 break;
157 }
158 case REG_QWORD: {
159 // We only use this for vram size
160 LONGLONG qValue;
161 dwcbData = sizeof(qValue);
162 result = RegQueryValueExW(key, keyName, nullptr, &resultType,
163 (LPBYTE)&qValue, &dwcbData);
164 if (result == ERROR_SUCCESS && resultType == REG_QWORD) {
165 qValue = qValue / 1024 / 1024;
166 destString.AppendInt(int32_t(qValue));
167 } else {
168 retval = NS_ERROR_FAILURE;
169 }
170 break;
171 }
172 case REG_MULTI_SZ: {
173 // A chain of null-separated strings; we convert the nulls to spaces
174 WCHAR wCharValue[1024];
175 dwcbData = sizeof(wCharValue);
176
177 result = RegQueryValueExW(key, keyName, nullptr, &resultType,
178 (LPBYTE)wCharValue, &dwcbData);
179 if (result == ERROR_SUCCESS && resultType == REG_MULTI_SZ) {
180 // This bit here could probably be cleaner.
181 bool isValid = false;
182
183 DWORD strLen = dwcbData / sizeof(wCharValue[0]);
184 for (DWORD i = 0; i < strLen; i++) {
185 if (wCharValue[i] == '\0') {
186 if (i < strLen - 1 && wCharValue[i + 1] == '\0') {
187 isValid = true;
188 break;
189 } else {
190 wCharValue[i] = ' ';
191 }
192 }
193 }
194
195 // ensure wCharValue is null terminated
196 wCharValue[strLen - 1] = '\0';
197
198 if (isValid) destString = wCharValue;
199
200 } else {
201 retval = NS_ERROR_FAILURE;
202 }
203
204 break;
205 }
206 }
207 RegCloseKey(key);
208
209 return retval;
210 }
211
GetKeyValues(const WCHAR * keyLocation,const WCHAR * keyName,nsTArray<nsString> & destStrings)212 static nsresult GetKeyValues(const WCHAR* keyLocation, const WCHAR* keyName,
213 nsTArray<nsString>& destStrings) {
214 // First ask for the size of the value
215 DWORD size;
216 LONG rv = RegGetValueW(HKEY_LOCAL_MACHINE, keyLocation, keyName,
217 RRF_RT_REG_MULTI_SZ, nullptr, nullptr, &size);
218 if (rv != ERROR_SUCCESS) {
219 return NS_ERROR_FAILURE;
220 }
221
222 // Create a buffer with the proper size and retrieve the value
223 WCHAR* wCharValue = new WCHAR[size / sizeof(WCHAR)];
224 rv = RegGetValueW(HKEY_LOCAL_MACHINE, keyLocation, keyName,
225 RRF_RT_REG_MULTI_SZ, nullptr, (LPBYTE)wCharValue, &size);
226 if (rv != ERROR_SUCCESS) {
227 delete[] wCharValue;
228 return NS_ERROR_FAILURE;
229 }
230
231 // The value is a sequence of null-terminated strings, usually terminated by
232 // an empty string (\0). RegGetValue ensures that the value is properly
233 // terminated with a null character.
234 DWORD i = 0;
235 DWORD strLen = size / sizeof(WCHAR);
236 while (i < strLen) {
237 nsString value(wCharValue + i);
238 if (!value.IsEmpty()) {
239 destStrings.AppendElement(value);
240 }
241 i += value.Length() + 1;
242 }
243 delete[] wCharValue;
244
245 return NS_OK;
246 }
247
248 // The device ID is a string like PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD
249 // this function is used to extract the id's out of it
ParseIDFromDeviceID(const nsAString & key,const char * prefix,int length)250 uint32_t ParseIDFromDeviceID(const nsAString& key, const char* prefix,
251 int length) {
252 nsAutoString id(key);
253 ToUpperCase(id);
254 int32_t start = id.Find(prefix);
255 if (start != -1) {
256 id.Cut(0, start + strlen(prefix));
257 id.Truncate(length);
258 }
259 if (id.Equals(L"QCOM", nsCaseInsensitiveStringComparator())) {
260 // String format assumptions are broken, so use a Qualcomm PCI Vendor ID
261 // for now. See also GfxDriverInfo::GetDeviceVendor.
262 return 0x5143;
263 }
264 nsresult err;
265 return id.ToInteger(&err, 16);
266 }
267
268 // OS version in 16.16 major/minor form
269 // based on http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
270 enum {
271 kWindowsUnknown = 0,
272 kWindows7 = 0x60001,
273 kWindows8 = 0x60002,
274 kWindows8_1 = 0x60003,
275 kWindows10 = 0xA0000
276 };
277
WindowsOSVersion()278 static int32_t WindowsOSVersion() {
279 static int32_t winVersion = UNINITIALIZED_VALUE;
280
281 OSVERSIONINFO vinfo;
282
283 if (winVersion == UNINITIALIZED_VALUE) {
284 vinfo.dwOSVersionInfoSize = sizeof(vinfo);
285 #ifdef _MSC_VER
286 #pragma warning(push)
287 #pragma warning(disable : 4996)
288 #endif
289 if (!GetVersionEx(&vinfo)) {
290 #ifdef _MSC_VER
291 #pragma warning(pop)
292 #endif
293 winVersion = kWindowsUnknown;
294 } else {
295 winVersion = int32_t(vinfo.dwMajorVersion << 16) + vinfo.dwMinorVersion;
296 }
297 }
298
299 return winVersion;
300 }
301
302 /* Other interesting places for info:
303 * IDXGIAdapter::GetDesc()
304 * IDirectDraw7::GetAvailableVidMem()
305 * e->GetAvailableTextureMem()
306 * */
307
308 #define DEVICE_KEY_PREFIX L"\\Registry\\Machine\\"
Init()309 nsresult GfxInfo::Init() {
310 nsresult rv = GfxInfoBase::Init();
311
312 DISPLAY_DEVICEW displayDevice;
313 displayDevice.cb = sizeof(displayDevice);
314 int deviceIndex = 0;
315
316 const char* spoofedWindowsVersion =
317 PR_GetEnv("MOZ_GFX_SPOOF_WINDOWS_VERSION");
318 if (spoofedWindowsVersion) {
319 PR_sscanf(spoofedWindowsVersion, "%x", &mWindowsVersion);
320 } else {
321 mWindowsVersion = WindowsOSVersion();
322 }
323
324 mDeviceKeyDebug = NS_LITERAL_STRING("PrimarySearch");
325
326 while (EnumDisplayDevicesW(nullptr, deviceIndex, &displayDevice, 0)) {
327 if (displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
328 mDeviceKeyDebug = NS_LITERAL_STRING("NullSearch");
329 break;
330 }
331 deviceIndex++;
332 }
333
334 // make sure the string is nullptr terminated
335 if (wcsnlen(displayDevice.DeviceKey, ArrayLength(displayDevice.DeviceKey)) ==
336 ArrayLength(displayDevice.DeviceKey)) {
337 // we did not find a nullptr
338 return rv;
339 }
340
341 mDeviceKeyDebug = displayDevice.DeviceKey;
342
343 /* DeviceKey is "reserved" according to MSDN so we'll be careful with it */
344 /* check that DeviceKey begins with DEVICE_KEY_PREFIX */
345 /* some systems have a DeviceKey starting with \REGISTRY\Machine\ so we need
346 * to compare case insenstively */
347 if (_wcsnicmp(displayDevice.DeviceKey, DEVICE_KEY_PREFIX,
348 ArrayLength(DEVICE_KEY_PREFIX) - 1) != 0)
349 return rv;
350
351 // chop off DEVICE_KEY_PREFIX
352 mDeviceKey[0] = displayDevice.DeviceKey + ArrayLength(DEVICE_KEY_PREFIX) - 1;
353
354 mDeviceID[0] = displayDevice.DeviceID;
355 mDeviceString[0] = displayDevice.DeviceString;
356
357 // On Windows 8 and Server 2012 hosts, we want to not block RDP
358 // sessions from attempting hardware acceleration. RemoteFX
359 // provides features and functionaltiy that can give a good D3D10 +
360 // D2D + DirectWrite experience emulated via a software GPU.
361 //
362 // Unfortunately, the Device ID is nullptr, and we can't enumerate
363 // it using the setup infrastructure (SetupDiGetClassDevsW below
364 // will return INVALID_HANDLE_VALUE).
365 UINT flags = DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES;
366 if (mWindowsVersion >= kWindows8 && mDeviceID[0].Length() == 0 &&
367 mDeviceString[0].EqualsLiteral("RDPUDD Chained DD")) {
368 WCHAR sysdir[255];
369 UINT len = GetSystemDirectory(sysdir, sizeof(sysdir));
370 if (len < sizeof(sysdir)) {
371 nsString rdpudd(sysdir);
372 rdpudd.AppendLiteral("\\rdpudd.dll");
373 gfxWindowsPlatform::GetDLLVersion(rdpudd.BeginReading(),
374 mDriverVersion[0]);
375 mDriverDate[0].AssignLiteral("01-01-1970");
376
377 // 0x1414 is Microsoft; 0xfefe is an invented (and unused) code
378 mDeviceID[0].AssignLiteral("PCI\\VEN_1414&DEV_FEFE&SUBSYS_00000000");
379 flags |= DIGCF_DEVICEINTERFACE;
380 }
381 }
382
383 /* create a device information set composed of the current display device */
384 HDEVINFO devinfo =
385 SetupDiGetClassDevsW(nullptr, mDeviceID[0].get(), nullptr, flags);
386
387 if (devinfo != INVALID_HANDLE_VALUE) {
388 HKEY key;
389 LONG result;
390 WCHAR value[255];
391 DWORD dwcbData;
392 SP_DEVINFO_DATA devinfoData;
393 DWORD memberIndex = 0;
394
395 devinfoData.cbSize = sizeof(devinfoData);
396 NS_NAMED_LITERAL_STRING(driverKeyPre,
397 "System\\CurrentControlSet\\Control\\Class\\");
398 /* enumerate device information elements in the device information set */
399 while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) {
400 /* get a string that identifies the device's driver key */
401 if (SetupDiGetDeviceRegistryPropertyW(devinfo, &devinfoData, SPDRP_DRIVER,
402 nullptr, (PBYTE)value,
403 sizeof(value), nullptr)) {
404 nsAutoString driverKey(driverKeyPre);
405 driverKey += value;
406 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey.get(), 0,
407 KEY_QUERY_VALUE, &key);
408 if (result == ERROR_SUCCESS) {
409 /* we've found the driver we're looking for */
410 dwcbData = sizeof(value);
411 result = RegQueryValueExW(key, L"DriverVersion", nullptr, nullptr,
412 (LPBYTE)value, &dwcbData);
413 if (result == ERROR_SUCCESS) {
414 mDriverVersion[0] = value;
415 } else {
416 // If the entry wasn't found, assume the worst (0.0.0.0).
417 mDriverVersion[0].AssignLiteral("0.0.0.0");
418 }
419 dwcbData = sizeof(value);
420 result = RegQueryValueExW(key, L"DriverDate", nullptr, nullptr,
421 (LPBYTE)value, &dwcbData);
422 if (result == ERROR_SUCCESS) {
423 mDriverDate[0] = value;
424 } else {
425 // Again, assume the worst
426 mDriverDate[0].AssignLiteral("01-01-1970");
427 }
428 RegCloseKey(key);
429 break;
430 }
431 }
432 }
433
434 SetupDiDestroyDeviceInfoList(devinfo);
435 }
436
437 // It is convenient to have these as integers
438 uint32_t adapterVendorID[2] = {0, 0};
439 uint32_t adapterDeviceID[2] = {0, 0};
440 uint32_t adapterSubsysID[2] = {0, 0};
441
442 adapterVendorID[0] = ParseIDFromDeviceID(mDeviceID[0], "VEN_", 4);
443 adapterDeviceID[0] = ParseIDFromDeviceID(mDeviceID[0], "&DEV_", 4);
444 adapterSubsysID[0] = ParseIDFromDeviceID(mDeviceID[0], "&SUBSYS_", 8);
445
446 // Sometimes we don't get the valid device using this method. For now,
447 // allow zero vendor or device as valid, as long as the other value is
448 // non-zero.
449 bool foundValidDevice = (adapterVendorID[0] != 0 || adapterDeviceID[0] != 0);
450
451 // We now check for second display adapter. If we didn't find the valid
452 // device using the original approach, we will try the alternative.
453
454 // Device interface class for display adapters.
455 CLSID GUID_DISPLAY_DEVICE_ARRIVAL;
456 HRESULT hresult = CLSIDFromString(L"{1CA05180-A699-450A-9A0C-DE4FBE3DDD89}",
457 &GUID_DISPLAY_DEVICE_ARRIVAL);
458 if (hresult == NOERROR) {
459 devinfo =
460 SetupDiGetClassDevsW(&GUID_DISPLAY_DEVICE_ARRIVAL, nullptr, nullptr,
461 DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
462
463 if (devinfo != INVALID_HANDLE_VALUE) {
464 HKEY key;
465 LONG result;
466 WCHAR value[255];
467 DWORD dwcbData;
468 SP_DEVINFO_DATA devinfoData;
469 DWORD memberIndex = 0;
470 devinfoData.cbSize = sizeof(devinfoData);
471
472 nsAutoString adapterDriver2;
473 nsAutoString deviceID2;
474 nsAutoString driverVersion2;
475 nsAutoString driverDate2;
476
477 NS_NAMED_LITERAL_STRING(driverKeyPre,
478 "System\\CurrentControlSet\\Control\\Class\\");
479 /* enumerate device information elements in the device information set */
480 while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) {
481 /* get a string that identifies the device's driver key */
482 if (SetupDiGetDeviceRegistryPropertyW(
483 devinfo, &devinfoData, SPDRP_DRIVER, nullptr, (PBYTE)value,
484 sizeof(value), nullptr)) {
485 nsAutoString driverKey2(driverKeyPre);
486 driverKey2 += value;
487 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey2.get(), 0,
488 KEY_QUERY_VALUE, &key);
489 if (result == ERROR_SUCCESS) {
490 dwcbData = sizeof(value);
491 result = RegQueryValueExW(key, L"MatchingDeviceId", nullptr,
492 nullptr, (LPBYTE)value, &dwcbData);
493 if (result != ERROR_SUCCESS) {
494 continue;
495 }
496 deviceID2 = value;
497 adapterVendorID[1] = ParseIDFromDeviceID(deviceID2, "VEN_", 4);
498 adapterDeviceID[1] = ParseIDFromDeviceID(deviceID2, "&DEV_", 4);
499 // Skip the devices we already considered, as well as any
500 // "zero" ones.
501 if ((adapterVendorID[0] == adapterVendorID[1] &&
502 adapterDeviceID[0] == adapterDeviceID[1]) ||
503 (adapterVendorID[1] == 0 && adapterDeviceID[1] == 0)) {
504 RegCloseKey(key);
505 continue;
506 }
507
508 // If this device is missing driver information, it is unlikely to
509 // be a real display adapter.
510 if (NS_FAILED(GetKeyValue(driverKey2.get(),
511 L"InstalledDisplayDrivers",
512 adapterDriver2, REG_MULTI_SZ))) {
513 RegCloseKey(key);
514 continue;
515 }
516 dwcbData = sizeof(value);
517 result = RegQueryValueExW(key, L"DriverVersion", nullptr, nullptr,
518 (LPBYTE)value, &dwcbData);
519 if (result != ERROR_SUCCESS) {
520 RegCloseKey(key);
521 continue;
522 }
523 driverVersion2 = value;
524 dwcbData = sizeof(value);
525 result = RegQueryValueExW(key, L"DriverDate", nullptr, nullptr,
526 (LPBYTE)value, &dwcbData);
527 if (result != ERROR_SUCCESS) {
528 RegCloseKey(key);
529 continue;
530 }
531 driverDate2 = value;
532 dwcbData = sizeof(value);
533 result = RegQueryValueExW(key, L"Device Description", nullptr,
534 nullptr, (LPBYTE)value, &dwcbData);
535 if (result != ERROR_SUCCESS) {
536 dwcbData = sizeof(value);
537 result = RegQueryValueExW(key, L"DriverDesc", nullptr, nullptr,
538 (LPBYTE)value, &dwcbData);
539 }
540 RegCloseKey(key);
541 if (result == ERROR_SUCCESS) {
542 // If we didn't find a valid device with the original method
543 // take this one, and continue looking for the second GPU.
544 if (!foundValidDevice) {
545 foundValidDevice = true;
546 adapterVendorID[0] = adapterVendorID[1];
547 adapterDeviceID[0] = adapterDeviceID[1];
548 mDeviceString[0] = value;
549 mDeviceID[0] = deviceID2;
550 mDeviceKey[0] = driverKey2;
551 mDriverVersion[0] = driverVersion2;
552 mDriverDate[0] = driverDate2;
553 adapterSubsysID[0] =
554 ParseIDFromDeviceID(mDeviceID[0], "&SUBSYS_", 8);
555 continue;
556 }
557
558 mHasDualGPU = true;
559 mDeviceString[1] = value;
560 mDeviceID[1] = deviceID2;
561 mDeviceKey[1] = driverKey2;
562 mDriverVersion[1] = driverVersion2;
563 mDriverDate[1] = driverDate2;
564 adapterSubsysID[1] =
565 ParseIDFromDeviceID(mDeviceID[1], "&SUBSYS_", 8);
566 mAdapterVendorID[1].AppendPrintf("0x%04x", adapterVendorID[1]);
567 mAdapterDeviceID[1].AppendPrintf("0x%04x", adapterDeviceID[1]);
568 mAdapterSubsysID[1].AppendPrintf("%08x", adapterSubsysID[1]);
569 break;
570 }
571 }
572 }
573 }
574
575 SetupDiDestroyDeviceInfoList(devinfo);
576 }
577 }
578
579 mAdapterVendorID[0].AppendPrintf("0x%04x", adapterVendorID[0]);
580 mAdapterDeviceID[0].AppendPrintf("0x%04x", adapterDeviceID[0]);
581 mAdapterSubsysID[0].AppendPrintf("%08x", adapterSubsysID[0]);
582
583 // Sometimes, the enumeration is not quite right and the two adapters
584 // end up being swapped. Actually enumerate the adapters that come
585 // back from the DXGI factory to check, and tag the second as active
586 // if found.
587 if (mHasDualGPU) {
588 nsModuleHandle dxgiModule(LoadLibrarySystem32(L"dxgi.dll"));
589 decltype(CreateDXGIFactory)* createDXGIFactory =
590 (decltype(CreateDXGIFactory)*)GetProcAddress(dxgiModule,
591 "CreateDXGIFactory");
592
593 if (createDXGIFactory) {
594 RefPtr<IDXGIFactory> factory = nullptr;
595 createDXGIFactory(__uuidof(IDXGIFactory), (void**)(&factory));
596 if (factory) {
597 RefPtr<IDXGIAdapter> adapter;
598 if (SUCCEEDED(factory->EnumAdapters(0, getter_AddRefs(adapter)))) {
599 DXGI_ADAPTER_DESC desc;
600 PodZero(&desc);
601 if (SUCCEEDED(adapter->GetDesc(&desc))) {
602 if (desc.VendorId != adapterVendorID[0] &&
603 desc.DeviceId != adapterDeviceID[0] &&
604 desc.VendorId == adapterVendorID[1] &&
605 desc.DeviceId == adapterDeviceID[1]) {
606 mActiveGPUIndex = 1;
607 }
608 }
609 }
610 }
611 }
612 }
613
614 mHasDriverVersionMismatch = false;
615 if (mAdapterVendorID[mActiveGPUIndex] ==
616 GfxDriverInfo::GetDeviceVendor(VendorIntel)) {
617 // we've had big crashers (bugs 590373 and 595364) apparently correlated
618 // with bad Intel driver installations where the DriverVersion reported
619 // by the registry was not the version of the DLL.
620
621 // Note that these start without the .dll extension but eventually gain it.
622 bool is64bitApp = sizeof(void*) == 8;
623 nsAutoString dllFileName(is64bitApp ? u"igd10umd64" : u"igd10umd32");
624 nsAutoString dllFileName2(is64bitApp ? u"igd10iumd64" : u"igd10iumd32");
625
626 nsString dllVersion, dllVersion2;
627 uint64_t dllNumericVersion = 0, dllNumericVersion2 = 0,
628 driverNumericVersion = 0, knownSafeMismatchVersion = 0;
629
630 // Only parse the DLL version for those found in the driver list
631 nsAutoString eligibleDLLs;
632 if (NS_SUCCEEDED(GetAdapterDriver(eligibleDLLs))) {
633 if (FindInReadable(dllFileName, eligibleDLLs)) {
634 dllFileName += NS_LITERAL_STRING(".dll");
635 gfxWindowsPlatform::GetDLLVersion(dllFileName.get(), dllVersion);
636 ParseDriverVersion(dllVersion, &dllNumericVersion);
637 }
638 if (FindInReadable(dllFileName2, eligibleDLLs)) {
639 dllFileName2 += NS_LITERAL_STRING(".dll");
640 gfxWindowsPlatform::GetDLLVersion(dllFileName2.get(), dllVersion2);
641 ParseDriverVersion(dllVersion2, &dllNumericVersion2);
642 }
643 }
644
645 // Sometimes the DLL is not in the System32 nor SysWOW64 directories. But
646 // UserModeDriverName (or UserModeDriverNameWow, if available) might provide
647 // the full path to the DLL in some DriverStore FileRepository.
648 if (dllNumericVersion == 0 && dllNumericVersion2 == 0) {
649 nsTArray<nsString> eligibleDLLpaths;
650 const WCHAR* keyLocation = mDeviceKey[mActiveGPUIndex].get();
651 GetKeyValues(keyLocation, L"UserModeDriverName", eligibleDLLpaths);
652 GetKeyValues(keyLocation, L"UserModeDriverNameWow", eligibleDLLpaths);
653 size_t length = eligibleDLLpaths.Length();
654 for (size_t i = 0;
655 i < length && dllNumericVersion == 0 && dllNumericVersion2 == 0;
656 ++i) {
657 if (FindInReadable(dllFileName, eligibleDLLpaths[i])) {
658 gfxWindowsPlatform::GetDLLVersion(eligibleDLLpaths[i].get(),
659 dllVersion);
660 ParseDriverVersion(dllVersion, &dllNumericVersion);
661 } else if (FindInReadable(dllFileName2, eligibleDLLpaths[i])) {
662 gfxWindowsPlatform::GetDLLVersion(eligibleDLLpaths[i].get(),
663 dllVersion2);
664 ParseDriverVersion(dllVersion2, &dllNumericVersion2);
665 }
666 }
667 }
668
669 ParseDriverVersion(mDriverVersion[mActiveGPUIndex], &driverNumericVersion);
670 ParseDriverVersion(NS_LITERAL_STRING("9.17.10.0"),
671 &knownSafeMismatchVersion);
672
673 // If there's a driver version mismatch, consider this harmful only when
674 // the driver version is less than knownSafeMismatchVersion. See the
675 // above comment about crashes with old mismatches. If the GetDllVersion
676 // call fails, we are not calling it a mismatch.
677 if ((dllNumericVersion != 0 && dllNumericVersion != driverNumericVersion) ||
678 (dllNumericVersion2 != 0 &&
679 dllNumericVersion2 != driverNumericVersion)) {
680 if (driverNumericVersion < knownSafeMismatchVersion ||
681 std::max(dllNumericVersion, dllNumericVersion2) <
682 knownSafeMismatchVersion) {
683 mHasDriverVersionMismatch = true;
684 gfxCriticalNoteOnce
685 << "Mismatched driver versions between the registry "
686 << NS_ConvertUTF16toUTF8(mDriverVersion[mActiveGPUIndex]).get()
687 << " and DLL(s) " << NS_ConvertUTF16toUTF8(dllVersion).get() << ", "
688 << NS_ConvertUTF16toUTF8(dllVersion2).get() << " reported.";
689 }
690 } else if (dllNumericVersion == 0 && dllNumericVersion2 == 0) {
691 // Leave it as an asserting error for now, to see if we can find
692 // a system that exhibits this kind of a problem internally.
693 gfxCriticalErrorOnce()
694 << "Potential driver version mismatch ignored due to missing DLLs "
695 << NS_ConvertUTF16toUTF8(dllFileName).get()
696 << " v=" << NS_ConvertUTF16toUTF8(dllVersion).get() << " and "
697 << NS_ConvertUTF16toUTF8(dllFileName2).get()
698 << " v=" << NS_ConvertUTF16toUTF8(dllVersion2).get();
699 }
700 }
701
702 const char* spoofedDriverVersionString =
703 PR_GetEnv("MOZ_GFX_SPOOF_DRIVER_VERSION");
704 if (spoofedDriverVersionString) {
705 mDriverVersion[mActiveGPUIndex].AssignASCII(spoofedDriverVersionString);
706 }
707
708 const char* spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_VENDOR_ID");
709 if (spoofedVendor) {
710 mAdapterVendorID[mActiveGPUIndex].AssignASCII(spoofedVendor);
711 }
712
713 const char* spoofedDevice = PR_GetEnv("MOZ_GFX_SPOOF_DEVICE_ID");
714 if (spoofedDevice) {
715 mAdapterDeviceID[mActiveGPUIndex].AssignASCII(spoofedDevice);
716 }
717
718 AddCrashReportAnnotations();
719
720 return rv;
721 }
722
723 NS_IMETHODIMP
GetAdapterDescription(nsAString & aAdapterDescription)724 GfxInfo::GetAdapterDescription(nsAString& aAdapterDescription) {
725 aAdapterDescription = mDeviceString[mActiveGPUIndex];
726 return NS_OK;
727 }
728
729 NS_IMETHODIMP
GetAdapterDescription2(nsAString & aAdapterDescription)730 GfxInfo::GetAdapterDescription2(nsAString& aAdapterDescription) {
731 aAdapterDescription = mDeviceString[1 - mActiveGPUIndex];
732 return NS_OK;
733 }
734
735 NS_IMETHODIMP
GetAdapterRAM(nsAString & aAdapterRAM)736 GfxInfo::GetAdapterRAM(nsAString& aAdapterRAM) {
737 if (NS_FAILED(GetKeyValue(mDeviceKey[mActiveGPUIndex].get(),
738 L"HardwareInformation.qwMemorySize", aAdapterRAM,
739 REG_QWORD)) ||
740 aAdapterRAM.Length() == 0) {
741 if (NS_FAILED(GetKeyValue(mDeviceKey[mActiveGPUIndex].get(),
742 L"HardwareInformation.MemorySize", aAdapterRAM,
743 REG_DWORD))) {
744 aAdapterRAM = L"Unknown";
745 }
746 }
747 return NS_OK;
748 }
749
750 NS_IMETHODIMP
GetAdapterRAM2(nsAString & aAdapterRAM)751 GfxInfo::GetAdapterRAM2(nsAString& aAdapterRAM) {
752 if (!mHasDualGPU) {
753 aAdapterRAM.Truncate();
754 } else if (NS_FAILED(GetKeyValue(mDeviceKey[1 - mActiveGPUIndex].get(),
755 L"HardwareInformation.qwMemorySize",
756 aAdapterRAM, REG_QWORD)) ||
757 aAdapterRAM.Length() == 0) {
758 if (NS_FAILED(GetKeyValue(mDeviceKey[1 - mActiveGPUIndex].get(),
759 L"HardwareInformation.MemorySize", aAdapterRAM,
760 REG_DWORD))) {
761 aAdapterRAM = L"Unknown";
762 }
763 }
764 return NS_OK;
765 }
766
767 NS_IMETHODIMP
GetAdapterDriver(nsAString & aAdapterDriver)768 GfxInfo::GetAdapterDriver(nsAString& aAdapterDriver) {
769 if (NS_FAILED(GetKeyValue(mDeviceKey[mActiveGPUIndex].get(),
770 L"InstalledDisplayDrivers", aAdapterDriver,
771 REG_MULTI_SZ)))
772 aAdapterDriver = L"Unknown";
773 return NS_OK;
774 }
775
776 NS_IMETHODIMP
GetAdapterDriver2(nsAString & aAdapterDriver)777 GfxInfo::GetAdapterDriver2(nsAString& aAdapterDriver) {
778 if (!mHasDualGPU) {
779 aAdapterDriver.Truncate();
780 } else if (NS_FAILED(GetKeyValue(mDeviceKey[1 - mActiveGPUIndex].get(),
781 L"InstalledDisplayDrivers", aAdapterDriver,
782 REG_MULTI_SZ))) {
783 aAdapterDriver = L"Unknown";
784 }
785 return NS_OK;
786 }
787
788 NS_IMETHODIMP
GetAdapterDriverVersion(nsAString & aAdapterDriverVersion)789 GfxInfo::GetAdapterDriverVersion(nsAString& aAdapterDriverVersion) {
790 aAdapterDriverVersion = mDriverVersion[mActiveGPUIndex];
791 return NS_OK;
792 }
793
794 NS_IMETHODIMP
GetAdapterDriverDate(nsAString & aAdapterDriverDate)795 GfxInfo::GetAdapterDriverDate(nsAString& aAdapterDriverDate) {
796 aAdapterDriverDate = mDriverDate[mActiveGPUIndex];
797 return NS_OK;
798 }
799
800 NS_IMETHODIMP
GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion)801 GfxInfo::GetAdapterDriverVersion2(nsAString& aAdapterDriverVersion) {
802 aAdapterDriverVersion = mDriverVersion[1 - mActiveGPUIndex];
803 return NS_OK;
804 }
805
806 NS_IMETHODIMP
GetAdapterDriverDate2(nsAString & aAdapterDriverDate)807 GfxInfo::GetAdapterDriverDate2(nsAString& aAdapterDriverDate) {
808 aAdapterDriverDate = mDriverDate[1 - mActiveGPUIndex];
809 return NS_OK;
810 }
811
812 NS_IMETHODIMP
GetAdapterVendorID(nsAString & aAdapterVendorID)813 GfxInfo::GetAdapterVendorID(nsAString& aAdapterVendorID) {
814 aAdapterVendorID = mAdapterVendorID[mActiveGPUIndex];
815 return NS_OK;
816 }
817
818 NS_IMETHODIMP
GetAdapterVendorID2(nsAString & aAdapterVendorID)819 GfxInfo::GetAdapterVendorID2(nsAString& aAdapterVendorID) {
820 aAdapterVendorID = mAdapterVendorID[1 - mActiveGPUIndex];
821 return NS_OK;
822 }
823
824 NS_IMETHODIMP
GetAdapterDeviceID(nsAString & aAdapterDeviceID)825 GfxInfo::GetAdapterDeviceID(nsAString& aAdapterDeviceID) {
826 aAdapterDeviceID = mAdapterDeviceID[mActiveGPUIndex];
827 return NS_OK;
828 }
829
830 NS_IMETHODIMP
GetAdapterDeviceID2(nsAString & aAdapterDeviceID)831 GfxInfo::GetAdapterDeviceID2(nsAString& aAdapterDeviceID) {
832 aAdapterDeviceID = mAdapterDeviceID[1 - mActiveGPUIndex];
833 return NS_OK;
834 }
835
836 NS_IMETHODIMP
GetAdapterSubsysID(nsAString & aAdapterSubsysID)837 GfxInfo::GetAdapterSubsysID(nsAString& aAdapterSubsysID) {
838 aAdapterSubsysID = mAdapterSubsysID[mActiveGPUIndex];
839 return NS_OK;
840 }
841
842 NS_IMETHODIMP
GetAdapterSubsysID2(nsAString & aAdapterSubsysID)843 GfxInfo::GetAdapterSubsysID2(nsAString& aAdapterSubsysID) {
844 aAdapterSubsysID = mAdapterSubsysID[1 - mActiveGPUIndex];
845 return NS_OK;
846 }
847
848 NS_IMETHODIMP
GetIsGPU2Active(bool * aIsGPU2Active)849 GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active) {
850 // This is never the case, as the active GPU ends up being
851 // the first one. It should probably be removed.
852 *aIsGPU2Active = false;
853 return NS_OK;
854 }
855
856 /* Cisco's VPN software can cause corruption of the floating point state.
857 * Make a note of this in our crash reports so that some weird crashes
858 * make more sense */
CheckForCiscoVPN()859 static void CheckForCiscoVPN() {
860 LONG result;
861 HKEY key;
862 /* This will give false positives, but hopefully no false negatives */
863 result =
864 RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Cisco Systems\\VPN Client",
865 0, KEY_QUERY_VALUE, &key);
866 if (result == ERROR_SUCCESS) {
867 RegCloseKey(key);
868 CrashReporter::AppendAppNotesToCrashReport(
869 NS_LITERAL_CSTRING("Cisco VPN\n"));
870 }
871 }
872
AddCrashReportAnnotations()873 void GfxInfo::AddCrashReportAnnotations() {
874 CheckForCiscoVPN();
875
876 if (mHasDriverVersionMismatch) {
877 CrashReporter::AppendAppNotesToCrashReport(
878 NS_LITERAL_CSTRING("DriverVersionMismatch\n"));
879 }
880
881 nsString deviceID, vendorID, driverVersion, subsysID;
882 nsCString narrowDeviceID, narrowVendorID, narrowDriverVersion, narrowSubsysID;
883
884 GetAdapterDeviceID(deviceID);
885 CopyUTF16toUTF8(deviceID, narrowDeviceID);
886 GetAdapterVendorID(vendorID);
887 CopyUTF16toUTF8(vendorID, narrowVendorID);
888 GetAdapterDriverVersion(driverVersion);
889 CopyUTF16toUTF8(driverVersion, narrowDriverVersion);
890 GetAdapterSubsysID(subsysID);
891 CopyUTF16toUTF8(subsysID, narrowSubsysID);
892
893 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterVendorID"),
894 narrowVendorID);
895 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterDeviceID"),
896 narrowDeviceID);
897 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterDriverVersion"),
898 narrowDriverVersion);
899 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterSubsysID"),
900 narrowSubsysID);
901
902 /* Add an App Note for now so that we get the data immediately. These
903 * can go away after we store the above in the socorro db */
904 nsAutoCString note;
905 /* AppendPrintf only supports 32 character strings, mrghh. */
906 note.AppendLiteral("AdapterVendorID: ");
907 note.Append(narrowVendorID);
908 note.AppendLiteral(", AdapterDeviceID: ");
909 note.Append(narrowDeviceID);
910 note.AppendLiteral(", AdapterSubsysID: ");
911 note.Append(narrowSubsysID);
912 note.AppendLiteral(", AdapterDriverVersion: ");
913 note.Append(NS_LossyConvertUTF16toASCII(driverVersion));
914
915 if (vendorID == GfxDriverInfo::GetDeviceVendor(VendorAll)) {
916 /* if we didn't find a valid vendorID lets append the mDeviceID string to
917 * try to find out why */
918 note.AppendLiteral(", ");
919 LossyAppendUTF16toASCII(mDeviceID[mActiveGPUIndex], note);
920 note.AppendLiteral(", ");
921 LossyAppendUTF16toASCII(mDeviceKeyDebug, note);
922 LossyAppendUTF16toASCII(mDeviceKeyDebug, note);
923 }
924 note.AppendLiteral("\n");
925
926 if (mHasDualGPU) {
927 nsString deviceID2, vendorID2, subsysID2;
928 nsAutoString adapterDriverVersionString2;
929 nsCString narrowDeviceID2, narrowVendorID2, narrowSubsysID2;
930
931 // Make a slight difference between the two cases so that we
932 // can see it in the crash reports. It may come in handy.
933 if (mActiveGPUIndex == 1) {
934 note.AppendLiteral("Has dual GPUs. GPU-#2: ");
935 } else {
936 note.AppendLiteral("Has dual GPUs. GPU #2: ");
937 }
938 GetAdapterDeviceID2(deviceID2);
939 CopyUTF16toUTF8(deviceID2, narrowDeviceID2);
940 GetAdapterVendorID2(vendorID2);
941 CopyUTF16toUTF8(vendorID2, narrowVendorID2);
942 GetAdapterDriverVersion2(adapterDriverVersionString2);
943 GetAdapterSubsysID(subsysID2);
944 CopyUTF16toUTF8(subsysID2, narrowSubsysID2);
945 note.AppendLiteral("AdapterVendorID2: ");
946 note.Append(narrowVendorID2);
947 note.AppendLiteral(", AdapterDeviceID2: ");
948 note.Append(narrowDeviceID2);
949 note.AppendLiteral(", AdapterSubsysID2: ");
950 note.Append(narrowSubsysID2);
951 note.AppendLiteral(", AdapterDriverVersion2: ");
952 note.Append(NS_LossyConvertUTF16toASCII(adapterDriverVersionString2));
953 }
954 CrashReporter::AppendAppNotesToCrashReport(note);
955 }
956
WindowsVersionToOperatingSystem(int32_t aWindowsVersion)957 static OperatingSystem WindowsVersionToOperatingSystem(
958 int32_t aWindowsVersion) {
959 switch (aWindowsVersion) {
960 case kWindows7:
961 return OperatingSystem::Windows7;
962 case kWindows8:
963 return OperatingSystem::Windows8;
964 case kWindows8_1:
965 return OperatingSystem::Windows8_1;
966 case kWindows10:
967 return OperatingSystem::Windows10;
968 case kWindowsUnknown:
969 default:
970 return OperatingSystem::Unknown;
971 }
972 }
973
974 // Return true if the CPU supports AVX, but the operating system does not.
975 #if defined(_M_X64)
DetectBrokenAVX()976 static inline bool DetectBrokenAVX() {
977 int regs[4];
978 __cpuid(regs, 0);
979 if (regs[0] == 0) {
980 // Level not supported.
981 return false;
982 }
983
984 __cpuid(regs, 1);
985
986 const unsigned AVX = 1u << 28;
987 const unsigned XSAVE = 1u << 26;
988 if ((regs[2] & (AVX | XSAVE)) != (AVX | XSAVE)) {
989 // AVX is not supported on this CPU.
990 return false;
991 }
992
993 const unsigned OSXSAVE = 1u << 27;
994 if ((regs[2] & OSXSAVE) != OSXSAVE) {
995 // AVX is supported, but the OS didn't enable it.
996 // This can be forced via bcdedit /set xsavedisable 1.
997 return true;
998 }
999
1000 const unsigned AVX_CTRL_BITS = (1 << 1) | (1 << 2);
1001 return (_xgetbv(0) & AVX_CTRL_BITS) != AVX_CTRL_BITS;
1002 }
1003 #endif
1004
GetGfxDriverInfo()1005 const nsTArray<GfxDriverInfo>& GfxInfo::GetGfxDriverInfo() {
1006 if (!mDriverInfo->Length()) {
1007 /*
1008 * It should be noted here that more specialized rules on certain features
1009 * should be inserted -before- more generalized restriction. As the first
1010 * match for feature/OS/device found in the list will be used for the final
1011 * blacklisting call.
1012 */
1013
1014 /*
1015 * NVIDIA entries
1016 */
1017 /*
1018 * The last 5 digit of the NVIDIA driver version maps to the version that
1019 * NVIDIA uses. The minor version (15, 16, 17) corresponds roughtly to the
1020 * OS (Vista, Win7, Win7) but they show up in smaller numbers across all
1021 * OS versions (perhaps due to OS upgrades). So we want to support
1022 * October 2009+ drivers across all these minor versions.
1023 *
1024 * 187.45 (late October 2009) and earlier contain a bug which can cause us
1025 * to crash on shutdown.
1026 */
1027 APPEND_TO_DRIVER_BLOCKLIST(
1028 OperatingSystem::Windows7,
1029 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorNVIDIA),
1030 GfxDriverInfo::allDevices, GfxDriverInfo::allFeatures,
1031 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN_OR_EQUAL,
1032 V(8, 15, 11, 8745), "FEATURE_FAILURE_NV_W7_15",
1033 "nVidia driver > 187.45");
1034 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1035 OperatingSystem::Windows7,
1036 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorNVIDIA),
1037 GfxDriverInfo::allDevices, GfxDriverInfo::allFeatures,
1038 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1039 DRIVER_BETWEEN_INCLUSIVE_START, V(8, 16, 10, 0000), V(8, 16, 11, 8745),
1040 "FEATURE_FAILURE_NV_W7_16", "nVidia driver > 187.45");
1041 // Telemetry doesn't show any driver in this range so it might not even be
1042 // required.
1043 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1044 OperatingSystem::Windows7,
1045 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorNVIDIA),
1046 GfxDriverInfo::allDevices, GfxDriverInfo::allFeatures,
1047 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1048 DRIVER_BETWEEN_INCLUSIVE_START, V(8, 17, 10, 0000), V(8, 17, 11, 8745),
1049 "FEATURE_FAILURE_NV_W7_17", "nVidia driver > 187.45");
1050
1051 /*
1052 * AMD/ATI entries. 8.56.1.15 is the driver that shipped with Windows 7 RTM
1053 */
1054 APPEND_TO_DRIVER_BLOCKLIST(
1055 OperatingSystem::Windows,
1056 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI),
1057 GfxDriverInfo::allDevices, GfxDriverInfo::allFeatures,
1058 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
1059 V(8, 56, 1, 15), "FEATURE_FAILURE_AMD1", "8.56.1.15");
1060 APPEND_TO_DRIVER_BLOCKLIST(
1061 OperatingSystem::Windows,
1062 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorAMD),
1063 GfxDriverInfo::allDevices, GfxDriverInfo::allFeatures,
1064 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
1065 V(8, 56, 1, 15), "FEATURE_FAILURE_AMD2", "8.56.1.15");
1066
1067 // Bug 1099252
1068 APPEND_TO_DRIVER_BLOCKLIST2(
1069 OperatingSystem::Windows7,
1070 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI),
1071 GfxDriverInfo::allDevices, GfxDriverInfo::allFeatures,
1072 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_EQUAL,
1073 V(8, 832, 0, 0), "FEATURE_FAILURE_BUG_1099252");
1074
1075 // Bug 1118695
1076 APPEND_TO_DRIVER_BLOCKLIST2(
1077 OperatingSystem::Windows7,
1078 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI),
1079 GfxDriverInfo::allDevices, GfxDriverInfo::allFeatures,
1080 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_EQUAL,
1081 V(8, 783, 2, 2000), "FEATURE_FAILURE_BUG_1118695");
1082
1083 // Bug 1198815
1084 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1085 OperatingSystem::Windows,
1086 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI),
1087 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1088 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_BETWEEN_INCLUSIVE,
1089 V(15, 200, 0, 0), V(15, 200, 1062, 1004), "FEATURE_FAILURE_BUG_1198815",
1090 "15.200.0.0-15.200.1062.1004");
1091
1092 // Bug 1267970
1093 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1094 OperatingSystem::Windows10,
1095 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI),
1096 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1097 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_BETWEEN_INCLUSIVE,
1098 V(15, 200, 0, 0), V(15, 301, 2301, 1002), "FEATURE_FAILURE_BUG_1267970",
1099 "15.200.0.0-15.301.2301.1002");
1100 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1101 OperatingSystem::Windows10,
1102 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI),
1103 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1104 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_BETWEEN_INCLUSIVE,
1105 V(16, 100, 0, 0), V(16, 300, 2311, 0), "FEATURE_FAILURE_BUG_1267970",
1106 "16.100.0.0-16.300.2311.0");
1107
1108 /*
1109 * Bug 783517 - crashes in AMD driver on Windows 8
1110 */
1111 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1112 OperatingSystem::Windows8,
1113 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI),
1114 GfxDriverInfo::allDevices, GfxDriverInfo::allFeatures,
1115 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1116 DRIVER_BETWEEN_INCLUSIVE_START, V(8, 982, 0, 0), V(8, 983, 0, 0),
1117 "FEATURE_FAILURE_BUG_783517_AMD", "!= 8.982.*.*");
1118 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1119 OperatingSystem::Windows8,
1120 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorAMD),
1121 GfxDriverInfo::allDevices, GfxDriverInfo::allFeatures,
1122 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1123 DRIVER_BETWEEN_INCLUSIVE_START, V(8, 982, 0, 0), V(8, 983, 0, 0),
1124 "FEATURE_FAILURE_BUG_783517_ATI", "!= 8.982.*.*");
1125
1126 /* OpenGL on any ATI/AMD hardware is discouraged
1127 * See:
1128 * bug 619773 - WebGL: Crash with blue screen : "NMI: Parity Check / Memory
1129 * Parity Error" bugs 584403, 584404, 620924 - crashes in atioglxx
1130 * + many complaints about incorrect rendering
1131 */
1132 APPEND_TO_DRIVER_BLOCKLIST2(
1133 OperatingSystem::Windows,
1134 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI),
1135 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_OPENGL_LAYERS,
1136 nsIGfxInfo::FEATURE_DISCOURAGED, DRIVER_LESS_THAN,
1137 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_OGL_ATI_DIS");
1138 APPEND_TO_DRIVER_BLOCKLIST2(
1139 OperatingSystem::Windows,
1140 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorAMD),
1141 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_OPENGL_LAYERS,
1142 nsIGfxInfo::FEATURE_DISCOURAGED, DRIVER_LESS_THAN,
1143 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_OGL_AMD_DIS");
1144
1145 /*
1146 * Intel entries
1147 */
1148
1149 /* The driver versions used here come from bug 594877. They might not
1150 * be particularly relevant anymore.
1151 */
1152 #define IMPLEMENT_INTEL_DRIVER_BLOCKLIST(winVer, devFamily, driverVer, ruleId) \
1153 APPEND_TO_DRIVER_BLOCKLIST2( \
1154 winVer, (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel), \
1155 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(devFamily), \
1156 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, \
1157 DRIVER_LESS_THAN, driverVer, ruleId)
1158
1159 #define IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(winVer, devFamily, driverVer, \
1160 ruleId) \
1161 APPEND_TO_DRIVER_BLOCKLIST2( \
1162 winVer, (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel), \
1163 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(devFamily), \
1164 nsIGfxInfo::FEATURE_DIRECT2D, \
1165 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_BUILD_ID_LESS_THAN, \
1166 driverVer, ruleId)
1167
1168 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7, IntelGMA500,
1169 2026, "FEATURE_FAILURE_594877_7");
1170 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7, IntelGMA900,
1171 GfxDriverInfo::allDriverVersions,
1172 "FEATURE_FAILURE_594877_8");
1173 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7, IntelGMA950,
1174 1930, "FEATURE_FAILURE_594877_9");
1175 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7,
1176 IntelGMA3150, 2117,
1177 "FEATURE_FAILURE_594877_10");
1178 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7,
1179 IntelGMAX3000, 1930,
1180 "FEATURE_FAILURE_594877_11");
1181 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7,
1182 IntelHDGraphicsToSandyBridge, 2202,
1183 "FEATURE_FAILURE_594877_12");
1184
1185 /* Disable Direct2D on Intel GMAX4500 devices because of rendering
1186 * corruption discovered in bug 1180379. These seems to affect even the most
1187 * recent drivers. We're black listing all of the devices to be safe even
1188 * though we've only confirmed the issue on the G45
1189 */
1190 APPEND_TO_DRIVER_BLOCKLIST2(
1191 OperatingSystem::Windows,
1192 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1193 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(IntelGMAX4500HD),
1194 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1195 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions,
1196 "FEATURE_FAILURE_1180379");
1197
1198 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::Windows7, IntelGMA500,
1199 V(5, 0, 0, 2026),
1200 "FEATURE_FAILURE_INTEL_16");
1201 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::Windows7, IntelGMA900,
1202 GfxDriverInfo::allDriverVersions,
1203 "FEATURE_FAILURE_INTEL_17");
1204 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::Windows7, IntelGMA950,
1205 V(8, 15, 10, 1930),
1206 "FEATURE_FAILURE_INTEL_18");
1207 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::Windows7, IntelGMA3150,
1208 V(8, 14, 10, 1972),
1209 "FEATURE_FAILURE_INTEL_19");
1210 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::Windows7, IntelGMAX3000,
1211 V(7, 15, 10, 1666),
1212 "FEATURE_FAILURE_INTEL_20");
1213 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::Windows7, IntelGMAX4500HD,
1214 V(7, 15, 10, 1666),
1215 "FEATURE_FAILURE_INTEL_21");
1216 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(
1217 OperatingSystem::Windows7, IntelHDGraphicsToSandyBridge,
1218 V(7, 15, 10, 1666), "FEATURE_FAILURE_INTEL_22");
1219
1220 // Bug 1074378
1221 APPEND_TO_DRIVER_BLOCKLIST(
1222 OperatingSystem::Windows7,
1223 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1224 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(IntelGMAX4500HD),
1225 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1226 DRIVER_EQUAL, V(8, 15, 10, 1749), "FEATURE_FAILURE_BUG_1074378_1",
1227 "8.15.10.2342");
1228 APPEND_TO_DRIVER_BLOCKLIST(
1229 OperatingSystem::Windows7,
1230 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1231 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(
1232 IntelHDGraphicsToSandyBridge),
1233 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1234 DRIVER_EQUAL, V(8, 15, 10, 1749), "FEATURE_FAILURE_BUG_1074378_2",
1235 "8.15.10.2342");
1236
1237 /* OpenGL on any Intel hardware is discouraged */
1238 APPEND_TO_DRIVER_BLOCKLIST2(
1239 OperatingSystem::Windows,
1240 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1241 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_OPENGL_LAYERS,
1242 nsIGfxInfo::FEATURE_DISCOURAGED, DRIVER_LESS_THAN,
1243 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_INTEL_OGL_DIS");
1244
1245 /**
1246 * Disable acceleration on Intel HD 3000 for graphics drivers
1247 * <= 8.15.10.2321. See bug 1018278 and bug 1060736.
1248 */
1249 APPEND_TO_DRIVER_BLOCKLIST(
1250 OperatingSystem::Windows,
1251 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1252 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(IntelHD3000),
1253 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1254 DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL, 2321, "FEATURE_FAILURE_BUG_1018278",
1255 "X.X.X.2342");
1256
1257 /* Disable D2D on Win7 on Intel HD Graphics on driver <= 8.15.10.2302
1258 * See bug 806786
1259 */
1260 APPEND_TO_DRIVER_BLOCKLIST2(
1261 OperatingSystem::Windows7,
1262 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1263 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(IntelMobileHDGraphics),
1264 nsIGfxInfo::FEATURE_DIRECT2D,
1265 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN_OR_EQUAL,
1266 V(8, 15, 10, 2302), "FEATURE_FAILURE_BUG_806786");
1267
1268 /* Disable D2D on Win8 on Intel HD Graphics on driver <= 8.15.10.2302
1269 * See bug 804144 and 863683
1270 */
1271 APPEND_TO_DRIVER_BLOCKLIST2(
1272 OperatingSystem::Windows8,
1273 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1274 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(IntelMobileHDGraphics),
1275 nsIGfxInfo::FEATURE_DIRECT2D,
1276 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN_OR_EQUAL,
1277 V(8, 15, 10, 2302), "FEATURE_FAILURE_BUG_804144");
1278
1279 /* Disable D2D on Win7 on Intel HD Graphics on driver == 8.15.10.2418
1280 * See bug 1433790
1281 */
1282 APPEND_TO_DRIVER_BLOCKLIST2(
1283 OperatingSystem::Windows7,
1284 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1285 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(
1286 IntelHDGraphicsToSandyBridge),
1287 nsIGfxInfo::FEATURE_DIRECT2D,
1288 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_EQUAL,
1289 V(8, 15, 10, 2418), "FEATURE_FAILURE_BUG_1433790");
1290
1291 /* Disable D3D11 layers on Intel G41 express graphics and Intel GM965, Intel
1292 * X3100, for causing device resets. See bug 1116812.
1293 */
1294 APPEND_TO_DRIVER_BLOCKLIST2(
1295 OperatingSystem::Windows,
1296 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1297 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(Bug1116812),
1298 nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS,
1299 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_LESS_THAN,
1300 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_BUG_1116812");
1301
1302 /* Disable D3D11 layers on Intel GMA 3150 for failing to allocate a shared
1303 * handle for textures. See bug 1207665. Additionally block D2D so we don't
1304 * accidentally use WARP.
1305 */
1306 APPEND_TO_DRIVER_BLOCKLIST2(
1307 OperatingSystem::Windows,
1308 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1309 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(Bug1207665),
1310 nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS,
1311 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_LESS_THAN,
1312 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_BUG_1207665_1");
1313 APPEND_TO_DRIVER_BLOCKLIST2(
1314 OperatingSystem::Windows,
1315 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1316 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(Bug1207665),
1317 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1318 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions,
1319 "FEATURE_FAILURE_BUG_1207665_2");
1320
1321 /* Disable D2D on AMD Catalyst 14.4 until 14.6
1322 * See bug 984488
1323 */
1324 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1325 OperatingSystem::Windows,
1326 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI),
1327 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_DIRECT2D,
1328 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1329 DRIVER_BETWEEN_INCLUSIVE_START, V(14, 1, 0, 0), V(14, 2, 0, 0),
1330 "FEATURE_FAILURE_BUG_984488_1", "ATI Catalyst 14.6+");
1331 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1332 OperatingSystem::Windows,
1333 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorAMD),
1334 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_DIRECT2D,
1335 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1336 DRIVER_BETWEEN_INCLUSIVE_START, V(14, 1, 0, 0), V(14, 2, 0, 0),
1337 "FEATURE_FAILURE_BUG_984488_2", "ATI Catalyst 14.6+");
1338
1339 /* Disable D3D9 layers on NVIDIA 6100/6150/6200 series due to glitches
1340 * whilst scrolling. See bugs: 612007, 644787 & 645872.
1341 */
1342 APPEND_TO_DRIVER_BLOCKLIST2(
1343 OperatingSystem::Windows,
1344 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorNVIDIA),
1345 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(NvidiaBlockD3D9Layers),
1346 nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS,
1347 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_LESS_THAN,
1348 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_BUG_612007");
1349
1350 /* Microsoft RemoteFX; blocked less than 6.2.0.0 */
1351 APPEND_TO_DRIVER_BLOCKLIST(
1352 OperatingSystem::Windows,
1353 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorMicrosoft),
1354 GfxDriverInfo::allDevices, GfxDriverInfo::allFeatures,
1355 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
1356 V(6, 2, 0, 0), "< 6.2.0.0", "FEATURE_FAILURE_REMOTE_FX");
1357
1358 /* Bug 1008759: Optimus (NVidia) crash. Disable D2D on NV 310M. */
1359 APPEND_TO_DRIVER_BLOCKLIST2(
1360 OperatingSystem::Windows,
1361 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorNVIDIA),
1362 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(Nvidia310M),
1363 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1364 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions,
1365 "FEATURE_FAILURE_BUG_1008759");
1366
1367 /* Bug 1139503: DXVA crashes with ATI cards on windows 10. */
1368 APPEND_TO_DRIVER_BLOCKLIST2(
1369 OperatingSystem::Windows10,
1370 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI),
1371 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1372 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_EQUAL,
1373 V(15, 200, 1006, 0), "FEATURE_FAILURE_BUG_1139503");
1374
1375 /* Bug 1213107: D3D9 crashes with ATI cards on Windows 7. */
1376 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1377 OperatingSystem::Windows7,
1378 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI),
1379 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1380 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_BETWEEN_INCLUSIVE,
1381 V(8, 861, 0, 0), V(8, 862, 6, 5000), "FEATURE_FAILURE_BUG_1213107_1",
1382 "Radeon driver > 8.862.6.5000");
1383 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1384 OperatingSystem::Windows7,
1385 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI),
1386 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_WEBGL_ANGLE,
1387 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_BETWEEN_INCLUSIVE,
1388 V(8, 861, 0, 0), V(8, 862, 6, 5000), "FEATURE_FAILURE_BUG_1213107_2",
1389 "Radeon driver > 8.862.6.5000");
1390
1391 /* This may not be needed at all */
1392 APPEND_TO_DRIVER_BLOCKLIST2(
1393 OperatingSystem::Windows7,
1394 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1395 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(Bug1155608),
1396 nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1397 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
1398 V(8, 15, 10, 2869), "FEATURE_FAILURE_INTEL_W7_HW_DECODING");
1399
1400 /* Bug 1203199/1092166: DXVA startup crashes on some intel drivers. */
1401 APPEND_TO_DRIVER_BLOCKLIST(
1402 OperatingSystem::Windows,
1403 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1404 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1405 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1406 DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL, 2849,
1407 "FEATURE_FAILURE_BUG_1203199_1", "Intel driver > X.X.X.2849");
1408
1409 APPEND_TO_DRIVER_BLOCKLIST2(
1410 OperatingSystem::Windows,
1411 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorNVIDIA),
1412 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(Nvidia8800GTS),
1413 nsIGfxInfo::FEATURE_HARDWARE_VIDEO_DECODING,
1414 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_EQUAL,
1415 V(9, 18, 13, 4052), "FEATURE_FAILURE_BUG_1203199_2");
1416
1417 /* Bug 1137716: XXX this should really check for the matching Intel piece as
1418 * well. Unfortunately, we don't have the infrastructure to do that */
1419 APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2(
1420 OperatingSystem::Windows7,
1421 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorNVIDIA),
1422 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(Bug1137716),
1423 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1424 DRIVER_BETWEEN_INCLUSIVE, V(8, 17, 12, 5730), V(8, 17, 12, 6901),
1425 "FEATURE_FAILURE_BUG_1137716", "Nvidia driver > 8.17.12.6901");
1426
1427 /* Bug 1153381: WebGL issues with D3D11 ANGLE on Intel. These may be fixed
1428 * by an ANGLE update. */
1429 APPEND_TO_DRIVER_BLOCKLIST2(
1430 OperatingSystem::Windows,
1431 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1432 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(IntelGMAX4500HD),
1433 nsIGfxInfo::FEATURE_DIRECT3D_11_ANGLE,
1434 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_LESS_THAN,
1435 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_BUG_1153381");
1436
1437 /* Bug 1336710: Crash in rx::Blit9::initialize. */
1438 APPEND_TO_DRIVER_BLOCKLIST2(
1439 OperatingSystem::WindowsXP,
1440 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1441 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(IntelGMAX4500HD),
1442 nsIGfxInfo::FEATURE_WEBGL_ANGLE, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1443 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions,
1444 "FEATURE_FAILURE_BUG_1336710");
1445
1446 APPEND_TO_DRIVER_BLOCKLIST2(
1447 OperatingSystem::WindowsXP,
1448 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1449 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(
1450 IntelHDGraphicsToSandyBridge),
1451 nsIGfxInfo::FEATURE_WEBGL_ANGLE, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1452 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions,
1453 "FEATURE_FAILURE_BUG_1336710");
1454
1455 /* Bug 1304360: Graphical artifacts with D3D9 on Windows 7. */
1456 APPEND_TO_DRIVER_BLOCKLIST2(
1457 OperatingSystem::Windows7,
1458 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1459 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(IntelGMAX3000),
1460 nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS,
1461 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1462 DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL, 1749,
1463 "FEATURE_FAILURE_INTEL_W7_D3D9_LAYERS");
1464
1465 #if defined(_M_X64)
1466 if (DetectBrokenAVX()) {
1467 APPEND_TO_DRIVER_BLOCKLIST2(
1468 OperatingSystem::Windows7,
1469 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1470 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS,
1471 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
1472 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_BUG_1403353");
1473 }
1474 #endif
1475
1476 ////////////////////////////////////
1477 // WebGL
1478
1479 // Older than 5-15-2016
1480 APPEND_TO_DRIVER_BLOCKLIST2(
1481 OperatingSystem::Windows,
1482 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorAMD),
1483 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_WEBGL_OPENGL,
1484 nsIGfxInfo::FEATURE_DISCOURAGED, DRIVER_LESS_THAN,
1485 V(16, 200, 1010, 1002), "WEBGL_NATIVE_GL_OLD_AMD");
1486
1487 // Older than 11-18-2015
1488 APPEND_TO_DRIVER_BLOCKLIST2(
1489 OperatingSystem::Windows,
1490 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1491 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_WEBGL_OPENGL,
1492 nsIGfxInfo::FEATURE_DISCOURAGED, DRIVER_BUILD_ID_LESS_THAN, 4331,
1493 "WEBGL_NATIVE_GL_OLD_INTEL");
1494
1495 // Older than 2-23-2016
1496 APPEND_TO_DRIVER_BLOCKLIST2(
1497 OperatingSystem::Windows,
1498 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorNVIDIA),
1499 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_WEBGL_OPENGL,
1500 nsIGfxInfo::FEATURE_DISCOURAGED, DRIVER_LESS_THAN, V(10, 18, 13, 6200),
1501 "WEBGL_NATIVE_GL_OLD_NVIDIA");
1502
1503 ////////////////////////////////////
1504 // FEATURE_DX_INTEROP2
1505
1506 // All AMD.
1507 APPEND_TO_DRIVER_BLOCKLIST2(
1508 OperatingSystem::Windows,
1509 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorAMD),
1510 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_DX_INTEROP2,
1511 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN,
1512 GfxDriverInfo::allDriverVersions, "DX_INTEROP2_AMD_CRASH");
1513
1514 ////////////////////////////////////
1515 // FEATURE_D3D11_KEYED_MUTEX
1516
1517 // bug 1359416
1518 APPEND_TO_DRIVER_BLOCKLIST2(
1519 OperatingSystem::Windows,
1520 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1521 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(
1522 IntelHDGraphicsToSandyBridge),
1523 nsIGfxInfo::FEATURE_D3D11_KEYED_MUTEX,
1524 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_LESS_THAN,
1525 GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_BUG_1359416");
1526
1527 // bug 1419264
1528 APPEND_TO_DRIVER_BLOCKLIST_RANGE(
1529 OperatingSystem::Windows7,
1530 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorNVIDIA),
1531 GfxDriverInfo::allDevices, nsIGfxInfo::FEATURE_ADVANCED_LAYERS,
1532 nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_BETWEEN_INCLUSIVE,
1533 V(23, 21, 13, 8569), V(23, 21, 13, 9135), "FEATURE_FAILURE_BUG_1419264",
1534 "Windows 10");
1535
1536 // Bug 1447141, for causing device creation crashes.
1537 APPEND_TO_DRIVER_BLOCKLIST2(
1538 OperatingSystem::Windows7,
1539 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI),
1540 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(Bug1447141),
1541 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1542 DRIVER_EQUAL, V(15, 201, 2201, 0), "FEATURE_FAILURE_BUG_1447141_1");
1543 APPEND_TO_DRIVER_BLOCKLIST2(
1544 OperatingSystem::Windows7,
1545 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI),
1546 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(Bug1447141),
1547 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1548 DRIVER_EQUAL, V(15, 201, 1701, 0), "FEATURE_FAILURE_BUG_1447141_1");
1549
1550 // bug 1457758
1551 APPEND_TO_DRIVER_BLOCKLIST2(
1552 OperatingSystem::Windows,
1553 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorNVIDIA),
1554 GfxDriverInfo::allDevices, GfxDriverInfo::allFeatures,
1555 nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_EQUAL, V(24, 21, 13, 9731),
1556 "FEATURE_FAILURE_BUG_1457758");
1557
1558 ////////////////////////////////////
1559 // FEATURE_DX_NV12
1560
1561 // Bug 1437334
1562 APPEND_TO_DRIVER_BLOCKLIST2(
1563 OperatingSystem::Windows,
1564 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorIntel),
1565 (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(
1566 IntelHDGraphicsToSandyBridge),
1567 nsIGfxInfo::FEATURE_DX_NV12, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1568 DRIVER_BUILD_ID_LESS_THAN_OR_EQUAL, 4459,
1569 "FEATURE_BLOCKED_DRIVER_VERSION");
1570 }
1571 return *mDriverInfo;
1572 }
1573
GetFeatureStatusImpl(int32_t aFeature,int32_t * aStatus,nsAString & aSuggestedDriverVersion,const nsTArray<GfxDriverInfo> & aDriverInfo,nsACString & aFailureId,OperatingSystem * aOS)1574 nsresult GfxInfo::GetFeatureStatusImpl(
1575 int32_t aFeature, int32_t* aStatus, nsAString& aSuggestedDriverVersion,
1576 const nsTArray<GfxDriverInfo>& aDriverInfo, nsACString& aFailureId,
1577 OperatingSystem* aOS /* = nullptr */) {
1578 NS_ENSURE_ARG_POINTER(aStatus);
1579 aSuggestedDriverVersion.SetIsVoid(true);
1580 OperatingSystem os = WindowsVersionToOperatingSystem(mWindowsVersion);
1581 *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
1582 if (aOS) *aOS = os;
1583
1584 if (mShutdownOccurred) {
1585 return NS_OK;
1586 }
1587
1588 // Don't evaluate special cases if we're checking the downloaded blocklist.
1589 if (!aDriverInfo.Length()) {
1590 nsAutoString adapterVendorID;
1591 nsAutoString adapterDeviceID;
1592 nsAutoString adapterDriverVersionString;
1593 if (NS_FAILED(GetAdapterVendorID(adapterVendorID)) ||
1594 NS_FAILED(GetAdapterDeviceID(adapterDeviceID)) ||
1595 NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString))) {
1596 aFailureId = "FEATURE_FAILURE_GET_ADAPTER";
1597 *aStatus = FEATURE_BLOCKED_DEVICE;
1598 return NS_OK;
1599 }
1600
1601 if (!adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorIntel),
1602 nsCaseInsensitiveStringComparator()) &&
1603 !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorNVIDIA),
1604 nsCaseInsensitiveStringComparator()) &&
1605 !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorAMD),
1606 nsCaseInsensitiveStringComparator()) &&
1607 !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorATI),
1608 nsCaseInsensitiveStringComparator()) &&
1609 !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorMicrosoft),
1610 nsCaseInsensitiveStringComparator()) &&
1611 !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorParallels),
1612 nsCaseInsensitiveStringComparator()) &&
1613 !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorQualcomm),
1614 nsCaseInsensitiveStringComparator()) &&
1615 // FIXME - these special hex values are currently used in xpcshell tests
1616 // introduced by bug 625160 patch 8/8. Maybe these tests need to be
1617 // adjusted now that we're only whitelisting intel/ati/nvidia.
1618 !adapterVendorID.LowerCaseEqualsLiteral("0xabcd") &&
1619 !adapterVendorID.LowerCaseEqualsLiteral("0xdcba") &&
1620 !adapterVendorID.LowerCaseEqualsLiteral("0xabab") &&
1621 !adapterVendorID.LowerCaseEqualsLiteral("0xdcdc")) {
1622 aFailureId = "FEATURE_FAILURE_UNKNOWN_DEVICE_VENDOR";
1623 *aStatus = FEATURE_BLOCKED_DEVICE;
1624 return NS_OK;
1625 }
1626
1627 uint64_t driverVersion;
1628 if (!ParseDriverVersion(adapterDriverVersionString, &driverVersion)) {
1629 aFailureId = "FEATURE_FAILURE_PARSE_DRIVER";
1630 *aStatus = FEATURE_BLOCKED_DRIVER_VERSION;
1631 return NS_OK;
1632 }
1633
1634 if (mHasDriverVersionMismatch) {
1635 *aStatus = nsIGfxInfo::FEATURE_BLOCKED_MISMATCHED_VERSION;
1636 return NS_OK;
1637 }
1638 }
1639
1640 return GfxInfoBase::GetFeatureStatusImpl(
1641 aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aFailureId, &os);
1642 }
1643
FindMonitors(JSContext * aCx,JS::HandleObject aOutArray)1644 nsresult GfxInfo::FindMonitors(JSContext* aCx, JS::HandleObject aOutArray) {
1645 int deviceCount = 0;
1646 for (int deviceIndex = 0;; deviceIndex++) {
1647 DISPLAY_DEVICEA device;
1648 device.cb = sizeof(device);
1649 if (!::EnumDisplayDevicesA(nullptr, deviceIndex, &device, 0)) {
1650 break;
1651 }
1652
1653 if (!(device.StateFlags & DISPLAY_DEVICE_ACTIVE)) {
1654 continue;
1655 }
1656
1657 DEVMODEA mode;
1658 mode.dmSize = sizeof(mode);
1659 mode.dmDriverExtra = 0;
1660 if (!::EnumDisplaySettingsA(device.DeviceName, ENUM_CURRENT_SETTINGS,
1661 &mode)) {
1662 continue;
1663 }
1664
1665 JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
1666
1667 JS::Rooted<JS::Value> screenWidth(aCx, JS::Int32Value(mode.dmPelsWidth));
1668 JS_SetProperty(aCx, obj, "screenWidth", screenWidth);
1669
1670 JS::Rooted<JS::Value> screenHeight(aCx, JS::Int32Value(mode.dmPelsHeight));
1671 JS_SetProperty(aCx, obj, "screenHeight", screenHeight);
1672
1673 JS::Rooted<JS::Value> refreshRate(aCx,
1674 JS::Int32Value(mode.dmDisplayFrequency));
1675 JS_SetProperty(aCx, obj, "refreshRate", refreshRate);
1676
1677 JS::Rooted<JS::Value> pseudoDisplay(
1678 aCx, JS::BooleanValue(
1679 !!(device.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)));
1680 JS_SetProperty(aCx, obj, "pseudoDisplay", pseudoDisplay);
1681
1682 JS::Rooted<JS::Value> element(aCx, JS::ObjectValue(*obj));
1683 JS_SetElement(aCx, aOutArray, deviceCount++, element);
1684 }
1685 return NS_OK;
1686 }
1687
DescribeFeatures(JSContext * aCx,JS::Handle<JSObject * > aObj)1688 void GfxInfo::DescribeFeatures(JSContext* aCx, JS::Handle<JSObject*> aObj) {
1689 // Add the platform neutral features
1690 GfxInfoBase::DescribeFeatures(aCx, aObj);
1691
1692 JS::Rooted<JSObject*> obj(aCx);
1693
1694 gfx::FeatureStatus d3d11 = gfxConfig::GetValue(Feature::D3D11_COMPOSITING);
1695 if (!InitFeatureObject(aCx, aObj, "d3d11", FEATURE_DIRECT3D_11_ANGLE,
1696 Some(d3d11), &obj)) {
1697 return;
1698 }
1699 if (d3d11 == gfx::FeatureStatus::Available) {
1700 DeviceManagerDx* dm = DeviceManagerDx::Get();
1701 JS::Rooted<JS::Value> val(aCx,
1702 JS::Int32Value(dm->GetCompositorFeatureLevel()));
1703 JS_SetProperty(aCx, obj, "version", val);
1704
1705 val = JS::BooleanValue(dm->IsWARP());
1706 JS_SetProperty(aCx, obj, "warp", val);
1707
1708 val = JS::BooleanValue(dm->TextureSharingWorks());
1709 JS_SetProperty(aCx, obj, "textureSharing", val);
1710
1711 bool blacklisted = false;
1712 if (nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo()) {
1713 int32_t status;
1714 nsCString discardFailureId;
1715 if (SUCCEEDED(
1716 gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS,
1717 discardFailureId, &status))) {
1718 blacklisted = (status != nsIGfxInfo::FEATURE_STATUS_OK);
1719 }
1720 }
1721
1722 val = JS::BooleanValue(blacklisted);
1723 JS_SetProperty(aCx, obj, "blacklisted", val);
1724 }
1725
1726 gfx::FeatureStatus d2d = gfxConfig::GetValue(Feature::DIRECT2D);
1727 if (!InitFeatureObject(aCx, aObj, "d2d", nsIGfxInfo::FEATURE_DIRECT2D,
1728 Some(d2d), &obj)) {
1729 return;
1730 }
1731 {
1732 const char* version = "1.1";
1733 JS::Rooted<JSString*> str(aCx, JS_NewStringCopyZ(aCx, version));
1734 JS::Rooted<JS::Value> val(aCx, JS::StringValue(str));
1735 JS_SetProperty(aCx, obj, "version", val);
1736 }
1737 }
1738
1739 #ifdef DEBUG
1740
1741 // Implement nsIGfxInfoDebug
1742
SpoofVendorID(const nsAString & aVendorID)1743 NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString& aVendorID) {
1744 mAdapterVendorID[mActiveGPUIndex] = aVendorID;
1745 return NS_OK;
1746 }
1747
SpoofDeviceID(const nsAString & aDeviceID)1748 NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString& aDeviceID) {
1749 mAdapterDeviceID[mActiveGPUIndex] = aDeviceID;
1750 return NS_OK;
1751 }
1752
SpoofDriverVersion(const nsAString & aDriverVersion)1753 NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString& aDriverVersion) {
1754 mDriverVersion[mActiveGPUIndex] = aDriverVersion;
1755 return NS_OK;
1756 }
1757
SpoofOSVersion(uint32_t aVersion)1758 NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion) {
1759 mWindowsVersion = aVersion;
1760 return NS_OK;
1761 }
1762
1763 #endif
1764