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