Bumping manifests a=b2g-bump
[gecko.git] / widget / windows / GfxInfo.cpp
blobd4d73f92250d1282771f298f57f5393339ce88ad
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/ArrayUtils.h"
8 #include <windows.h>
9 #include <setupapi.h>
10 #include "gfxWindowsPlatform.h"
11 #include "GfxInfo.h"
12 #include "GfxInfoWebGL.h"
13 #include "nsUnicharUtils.h"
14 #include "prenv.h"
15 #include "prprf.h"
16 #include "GfxDriverInfo.h"
17 #include "mozilla/Preferences.h"
18 #include "nsPrintfCString.h"
20 #if defined(MOZ_CRASHREPORTER)
21 #include "nsExceptionHandler.h"
22 #include "nsICrashReporter.h"
23 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
24 #endif
26 using namespace mozilla;
27 using namespace mozilla::widget;
29 #ifdef DEBUG
30 NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfo2, nsIGfxInfoDebug)
31 #else
32 NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfo2)
33 #endif
35 static const uint32_t allWindowsVersions = 0xffffffff;
37 GfxInfo::GfxInfo()
38 : mWindowsVersion(0),
39 mHasDualGPU(false),
40 mIsGPU2Active(false)
44 /* GetD2DEnabled and GetDwriteEnabled shouldn't be called until after gfxPlatform initialization
45 * has occurred because they depend on it for information. (See bug 591561) */
46 nsresult
47 GfxInfo::GetD2DEnabled(bool *aEnabled)
49 *aEnabled = gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D;
50 return NS_OK;
53 nsresult
54 GfxInfo::GetDWriteEnabled(bool *aEnabled)
56 *aEnabled = gfxWindowsPlatform::GetPlatform()->DWriteEnabled();
57 return NS_OK;
60 /* readonly attribute DOMString DWriteVersion; */
61 NS_IMETHODIMP
62 GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
64 gfxWindowsPlatform::GetDLLVersion(L"dwrite.dll", aDwriteVersion);
65 return NS_OK;
68 #define PIXEL_STRUCT_RGB 1
69 #define PIXEL_STRUCT_BGR 2
71 /* readonly attribute DOMString cleartypeParameters; */
72 NS_IMETHODIMP
73 GfxInfo::GetCleartypeParameters(nsAString & aCleartypeParams)
75 nsTArray<ClearTypeParameterInfo> clearTypeParams;
77 gfxWindowsPlatform::GetPlatform()->GetCleartypeParams(clearTypeParams);
78 uint32_t d, numDisplays = clearTypeParams.Length();
79 bool displayNames = (numDisplays > 1);
80 bool foundData = false;
81 nsString outStr;
83 for (d = 0; d < numDisplays; d++) {
84 ClearTypeParameterInfo& params = clearTypeParams[d];
86 if (displayNames) {
87 outStr.AppendPrintf("%s [ ", params.displayName.get());
90 if (params.gamma >= 0) {
91 foundData = true;
92 outStr.AppendPrintf("Gamma: %d ", params.gamma);
95 if (params.pixelStructure >= 0) {
96 foundData = true;
97 if (params.pixelStructure == PIXEL_STRUCT_RGB ||
98 params.pixelStructure == PIXEL_STRUCT_BGR)
100 outStr.AppendPrintf("Pixel Structure: %s ",
101 (params.pixelStructure == PIXEL_STRUCT_RGB ?
102 L"RGB" : L"BGR"));
103 } else {
104 outStr.AppendPrintf("Pixel Structure: %d ", params.pixelStructure);
108 if (params.clearTypeLevel >= 0) {
109 foundData = true;
110 outStr.AppendPrintf("ClearType Level: %d ", params.clearTypeLevel);
113 if (params.enhancedContrast >= 0) {
114 foundData = true;
115 outStr.AppendPrintf("Enhanced Contrast: %d ", params.enhancedContrast);
118 if (displayNames) {
119 outStr.Append(MOZ_UTF16("] "));
123 if (foundData) {
124 aCleartypeParams.Assign(outStr);
125 return NS_OK;
127 return NS_ERROR_FAILURE;
130 static nsresult GetKeyValue(const WCHAR* keyLocation, const WCHAR* keyName, nsAString& destString, int type)
132 HKEY key;
133 DWORD dwcbData;
134 DWORD dValue;
135 DWORD resultType;
136 LONG result;
137 nsresult retval = NS_OK;
139 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyLocation, 0, KEY_QUERY_VALUE, &key);
140 if (result != ERROR_SUCCESS) {
141 return NS_ERROR_FAILURE;
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;
156 break;
158 case REG_MULTI_SZ: {
159 // A chain of null-separated strings; we convert the nulls to spaces
160 WCHAR wCharValue[1024];
161 dwcbData = sizeof(wCharValue);
163 result = RegQueryValueExW(key, keyName, nullptr, &resultType,
164 (LPBYTE)wCharValue, &dwcbData);
165 if (result == ERROR_SUCCESS && resultType == REG_MULTI_SZ) {
166 // This bit here could probably be cleaner.
167 bool isValid = false;
169 DWORD strLen = dwcbData/sizeof(wCharValue[0]);
170 for (DWORD i = 0; i < strLen; i++) {
171 if (wCharValue[i] == '\0') {
172 if (i < strLen - 1 && wCharValue[i + 1] == '\0') {
173 isValid = true;
174 break;
175 } else {
176 wCharValue[i] = ' ';
181 // ensure wCharValue is null terminated
182 wCharValue[strLen-1] = '\0';
184 if (isValid)
185 destString = wCharValue;
187 } else {
188 retval = NS_ERROR_FAILURE;
191 break;
194 RegCloseKey(key);
196 return retval;
199 // The device ID is a string like PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD
200 // this function is used to extract the id's out of it
201 uint32_t
202 ParseIDFromDeviceID(const nsAString &key, const char *prefix, int length)
204 nsAutoString id(key);
205 ToUpperCase(id);
206 int32_t start = id.Find(prefix);
207 if (start != -1) {
208 id.Cut(0, start + strlen(prefix));
209 id.Truncate(length);
211 nsresult err;
212 return id.ToInteger(&err, 16);
215 // OS version in 16.16 major/minor form
216 // based on http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
217 enum {
218 kWindowsUnknown = 0,
219 kWindowsXP = 0x50001,
220 kWindowsServer2003 = 0x50002,
221 kWindowsVista = 0x60000,
222 kWindows7 = 0x60001,
223 kWindows8 = 0x60002,
224 kWindows8_1 = 0x60003,
225 kWindows10 = 0x60004
228 static int32_t
229 WindowsOSVersion()
231 static int32_t winVersion = UNINITIALIZED_VALUE;
233 OSVERSIONINFO vinfo;
235 if (winVersion == UNINITIALIZED_VALUE) {
236 vinfo.dwOSVersionInfoSize = sizeof (vinfo);
237 #pragma warning(push)
238 #pragma warning(disable:4996)
239 if (!GetVersionEx(&vinfo)) {
240 #pragma warning(pop)
241 winVersion = kWindowsUnknown;
242 } else {
243 winVersion = int32_t(vinfo.dwMajorVersion << 16) + vinfo.dwMinorVersion;
247 return winVersion;
250 /* Other interesting places for info:
251 * IDXGIAdapter::GetDesc()
252 * IDirectDraw7::GetAvailableVidMem()
253 * e->GetAvailableTextureMem()
254 * */
256 #define DEVICE_KEY_PREFIX L"\\Registry\\Machine\\"
257 nsresult
258 GfxInfo::Init()
260 nsresult rv = GfxInfoBase::Init();
262 DISPLAY_DEVICEW displayDevice;
263 displayDevice.cb = sizeof(displayDevice);
264 int deviceIndex = 0;
266 const char *spoofedWindowsVersion = PR_GetEnv("MOZ_GFX_SPOOF_WINDOWS_VERSION");
267 if (spoofedWindowsVersion) {
268 PR_sscanf(spoofedWindowsVersion, "%x", &mWindowsVersion);
269 } else {
270 mWindowsVersion = WindowsOSVersion();
273 mDeviceKeyDebug = NS_LITERAL_STRING("PrimarySearch");
275 while (EnumDisplayDevicesW(nullptr, deviceIndex, &displayDevice, 0)) {
276 if (displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
277 mDeviceKeyDebug = NS_LITERAL_STRING("NullSearch");
278 break;
280 deviceIndex++;
283 // make sure the string is nullptr terminated
284 if (wcsnlen(displayDevice.DeviceKey, ArrayLength(displayDevice.DeviceKey))
285 == ArrayLength(displayDevice.DeviceKey)) {
286 // we did not find a nullptr
287 return rv;
290 mDeviceKeyDebug = displayDevice.DeviceKey;
292 /* DeviceKey is "reserved" according to MSDN so we'll be careful with it */
293 /* check that DeviceKey begins with DEVICE_KEY_PREFIX */
294 /* some systems have a DeviceKey starting with \REGISTRY\Machine\ so we need to compare case insenstively */
295 if (_wcsnicmp(displayDevice.DeviceKey, DEVICE_KEY_PREFIX, ArrayLength(DEVICE_KEY_PREFIX)-1) != 0)
296 return rv;
298 // chop off DEVICE_KEY_PREFIX
299 mDeviceKey = displayDevice.DeviceKey + ArrayLength(DEVICE_KEY_PREFIX)-1;
301 mDeviceID = displayDevice.DeviceID;
302 mDeviceString = displayDevice.DeviceString;
304 // On Windows 8 and Server 2012 hosts, we want to not block RDP
305 // sessions from attempting hardware acceleration. RemoteFX
306 // provides features and functionaltiy that can give a good D3D10 +
307 // D2D + DirectWrite experience emulated via a software GPU.
309 // Unfortunately, the Device ID is nullptr, and we can't enumerate
310 // it using the setup infrastructure (SetupDiGetClassDevsW below
311 // will return INVALID_HANDLE_VALUE).
312 if (mWindowsVersion == kWindows8 &&
313 mDeviceID.Length() == 0 &&
314 mDeviceString.EqualsLiteral("RDPUDD Chained DD"))
316 WCHAR sysdir[255];
317 UINT len = GetSystemDirectory(sysdir, sizeof(sysdir));
318 if (len < sizeof(sysdir)) {
319 nsString rdpudd(sysdir);
320 rdpudd.AppendLiteral("\\rdpudd.dll");
321 gfxWindowsPlatform::GetDLLVersion(rdpudd.BeginReading(), mDriverVersion);
322 mDriverDate.AssignLiteral("01-01-1970");
324 // 0x1414 is Microsoft; 0xfefe is an invented (and unused) code
325 mDeviceID.AssignLiteral("PCI\\VEN_1414&DEV_FEFE&SUBSYS_00000000");
329 /* create a device information set composed of the current display device */
330 HDEVINFO devinfo = SetupDiGetClassDevsW(nullptr, mDeviceID.get(), nullptr,
331 DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
333 if (devinfo != INVALID_HANDLE_VALUE) {
334 HKEY key;
335 LONG result;
336 WCHAR value[255];
337 DWORD dwcbData;
338 SP_DEVINFO_DATA devinfoData;
339 DWORD memberIndex = 0;
341 devinfoData.cbSize = sizeof(devinfoData);
342 NS_NAMED_LITERAL_STRING(driverKeyPre, "System\\CurrentControlSet\\Control\\Class\\");
343 /* enumerate device information elements in the device information set */
344 while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) {
345 /* get a string that identifies the device's driver key */
346 if (SetupDiGetDeviceRegistryPropertyW(devinfo,
347 &devinfoData,
348 SPDRP_DRIVER,
349 nullptr,
350 (PBYTE)value,
351 sizeof(value),
352 nullptr)) {
353 nsAutoString driverKey(driverKeyPre);
354 driverKey += value;
355 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey.get(), 0, KEY_QUERY_VALUE, &key);
356 if (result == ERROR_SUCCESS) {
357 /* we've found the driver we're looking for */
358 dwcbData = sizeof(value);
359 result = RegQueryValueExW(key, L"DriverVersion", nullptr, nullptr,
360 (LPBYTE)value, &dwcbData);
361 if (result == ERROR_SUCCESS) {
362 mDriverVersion = value;
363 } else {
364 // If the entry wasn't found, assume the worst (0.0.0.0).
365 mDriverVersion.AssignLiteral("0.0.0.0");
367 dwcbData = sizeof(value);
368 result = RegQueryValueExW(key, L"DriverDate", nullptr, nullptr,
369 (LPBYTE)value, &dwcbData);
370 if (result == ERROR_SUCCESS) {
371 mDriverDate = value;
372 } else {
373 // Again, assume the worst
374 mDriverDate.AssignLiteral("01-01-1970");
376 RegCloseKey(key);
377 break;
382 SetupDiDestroyDeviceInfoList(devinfo);
385 mAdapterVendorID.AppendPrintf("0x%04x", ParseIDFromDeviceID(mDeviceID, "VEN_", 4));
386 mAdapterDeviceID.AppendPrintf("0x%04x", ParseIDFromDeviceID(mDeviceID, "&DEV_", 4));
387 mAdapterSubsysID.AppendPrintf("%08x", ParseIDFromDeviceID(mDeviceID, "&SUBSYS_", 8));
389 // We now check for second display adapter.
391 // Device interface class for display adapters.
392 CLSID GUID_DISPLAY_DEVICE_ARRIVAL;
393 HRESULT hresult = CLSIDFromString(L"{1CA05180-A699-450A-9A0C-DE4FBE3DDD89}",
394 &GUID_DISPLAY_DEVICE_ARRIVAL);
395 if (hresult == NOERROR) {
396 devinfo = SetupDiGetClassDevsW(&GUID_DISPLAY_DEVICE_ARRIVAL,
397 nullptr, nullptr,
398 DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
400 if (devinfo != INVALID_HANDLE_VALUE) {
401 HKEY key;
402 LONG result;
403 WCHAR value[255];
404 DWORD dwcbData;
405 SP_DEVINFO_DATA devinfoData;
406 DWORD memberIndex = 0;
407 devinfoData.cbSize = sizeof(devinfoData);
409 nsAutoString adapterDriver2;
410 nsAutoString deviceID2;
411 nsAutoString driverVersion2;
412 nsAutoString driverDate2;
413 uint32_t adapterVendorID2;
414 uint32_t adapterDeviceID2;
416 NS_NAMED_LITERAL_STRING(driverKeyPre, "System\\CurrentControlSet\\Control\\Class\\");
417 /* enumerate device information elements in the device information set */
418 while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) {
419 /* get a string that identifies the device's driver key */
420 if (SetupDiGetDeviceRegistryPropertyW(devinfo,
421 &devinfoData,
422 SPDRP_DRIVER,
423 nullptr,
424 (PBYTE)value,
425 sizeof(value),
426 nullptr)) {
427 nsAutoString driverKey2(driverKeyPre);
428 driverKey2 += value;
429 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey2.get(), 0, KEY_QUERY_VALUE, &key);
430 if (result == ERROR_SUCCESS) {
431 dwcbData = sizeof(value);
432 result = RegQueryValueExW(key, L"MatchingDeviceId", nullptr,
433 nullptr, (LPBYTE)value, &dwcbData);
434 if (result != ERROR_SUCCESS) {
435 continue;
437 deviceID2 = value;
438 nsAutoString adapterVendorID2String;
439 nsAutoString adapterDeviceID2String;
440 adapterVendorID2 = ParseIDFromDeviceID(deviceID2, "VEN_", 4);
441 adapterVendorID2String.AppendPrintf("0x%04x", adapterVendorID2);
442 adapterDeviceID2 = ParseIDFromDeviceID(deviceID2, "&DEV_", 4);
443 adapterDeviceID2String.AppendPrintf("0x%04x", adapterDeviceID2);
444 if (mAdapterVendorID == adapterVendorID2String &&
445 mAdapterDeviceID == adapterDeviceID2String) {
446 RegCloseKey(key);
447 continue;
450 // If this device is missing driver information, it is unlikely to
451 // be a real display adapter.
452 if (NS_FAILED(GetKeyValue(driverKey2.get(), L"InstalledDisplayDrivers",
453 adapterDriver2, REG_MULTI_SZ))) {
454 RegCloseKey(key);
455 continue;
457 dwcbData = sizeof(value);
458 result = RegQueryValueExW(key, L"DriverVersion", nullptr, nullptr,
459 (LPBYTE)value, &dwcbData);
460 if (result != ERROR_SUCCESS) {
461 RegCloseKey(key);
462 continue;
464 driverVersion2 = value;
465 dwcbData = sizeof(value);
466 result = RegQueryValueExW(key, L"DriverDate", nullptr, nullptr,
467 (LPBYTE)value, &dwcbData);
468 if (result != ERROR_SUCCESS) {
469 RegCloseKey(key);
470 continue;
472 driverDate2 = value;
473 dwcbData = sizeof(value);
474 result = RegQueryValueExW(key, L"Device Description", nullptr,
475 nullptr, (LPBYTE)value, &dwcbData);
476 if (result != ERROR_SUCCESS) {
477 dwcbData = sizeof(value);
478 result = RegQueryValueExW(key, L"DriverDesc", nullptr, nullptr,
479 (LPBYTE)value, &dwcbData);
481 RegCloseKey(key);
482 if (result == ERROR_SUCCESS) {
483 mHasDualGPU = true;
484 mDeviceString2 = value;
485 mDeviceID2 = deviceID2;
486 mDeviceKey2 = driverKey2;
487 mDriverVersion2 = driverVersion2;
488 mDriverDate2 = driverDate2;
489 mAdapterVendorID2.AppendPrintf("0x%04x", adapterVendorID2);
490 mAdapterDeviceID2.AppendPrintf("0x%04x", adapterDeviceID2);
491 mAdapterSubsysID2.AppendPrintf("%08x", ParseIDFromDeviceID(mDeviceID2, "&SUBSYS_", 8));
492 break;
498 SetupDiDestroyDeviceInfoList(devinfo);
502 mHasDriverVersionMismatch = false;
503 if (mAdapterVendorID == GfxDriverInfo::GetDeviceVendor(VendorIntel)) {
504 // we've had big crashers (bugs 590373 and 595364) apparently correlated
505 // with bad Intel driver installations where the DriverVersion reported
506 // by the registry was not the version of the DLL.
507 bool is64bitApp = sizeof(void*) == 8;
508 const char16_t *dllFileName = is64bitApp
509 ? MOZ_UTF16("igd10umd64.dll")
510 : MOZ_UTF16("igd10umd32.dll"),
511 *dllFileName2 = is64bitApp
512 ? MOZ_UTF16("igd10iumd64.dll")
513 : MOZ_UTF16("igd10iumd32.dll");
514 nsString dllVersion, dllVersion2;
515 gfxWindowsPlatform::GetDLLVersion((char16_t*)dllFileName, dllVersion);
516 gfxWindowsPlatform::GetDLLVersion((char16_t*)dllFileName2, dllVersion2);
518 uint64_t dllNumericVersion = 0, dllNumericVersion2 = 0,
519 driverNumericVersion = 0, knownSafeMismatchVersion = 0;
520 ParseDriverVersion(dllVersion, &dllNumericVersion);
521 ParseDriverVersion(dllVersion2, &dllNumericVersion2);
522 ParseDriverVersion(mDriverVersion, &driverNumericVersion);
523 ParseDriverVersion(NS_LITERAL_STRING("9.17.10.0"), &knownSafeMismatchVersion);
525 // If there's a driver version mismatch, consider this harmful only when
526 // the driver version is less than knownSafeMismatchVersion. See the
527 // above comment about crashes with old mismatches. If the GetDllVersion
528 // call fails, then they return 0, so that will be considered a mismatch.
529 if (dllNumericVersion != driverNumericVersion &&
530 dllNumericVersion2 != driverNumericVersion &&
531 (driverNumericVersion < knownSafeMismatchVersion ||
532 std::max(dllNumericVersion, dllNumericVersion2) < knownSafeMismatchVersion)) {
533 mHasDriverVersionMismatch = true;
537 const char *spoofedDriverVersionString = PR_GetEnv("MOZ_GFX_SPOOF_DRIVER_VERSION");
538 if (spoofedDriverVersionString) {
539 mDriverVersion.AssignASCII(spoofedDriverVersionString);
542 const char *spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_VENDOR_ID");
543 if (spoofedVendor) {
544 mAdapterVendorID.AssignASCII(spoofedVendor);
547 const char *spoofedDevice = PR_GetEnv("MOZ_GFX_SPOOF_DEVICE_ID");
548 if (spoofedDevice) {
549 mAdapterDeviceID.AssignASCII(spoofedDevice);
552 AddCrashReportAnnotations();
554 GetCountryCode();
556 return rv;
559 /* readonly attribute DOMString adapterDescription; */
560 NS_IMETHODIMP
561 GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription)
563 aAdapterDescription = mDeviceString;
564 return NS_OK;
567 /* readonly attribute DOMString adapterDescription2; */
568 NS_IMETHODIMP
569 GfxInfo::GetAdapterDescription2(nsAString & aAdapterDescription)
571 aAdapterDescription = mDeviceString2;
572 return NS_OK;
575 /* readonly attribute DOMString adapterRAM; */
576 NS_IMETHODIMP
577 GfxInfo::GetAdapterRAM(nsAString & aAdapterRAM)
579 if (NS_FAILED(GetKeyValue(mDeviceKey.get(), L"HardwareInformation.MemorySize", aAdapterRAM, REG_DWORD)))
580 aAdapterRAM = L"Unknown";
581 return NS_OK;
584 /* readonly attribute DOMString adapterRAM2; */
585 NS_IMETHODIMP
586 GfxInfo::GetAdapterRAM2(nsAString & aAdapterRAM)
588 if (!mHasDualGPU) {
589 aAdapterRAM.Truncate();
590 } else if (NS_FAILED(GetKeyValue(mDeviceKey2.get(), L"HardwareInformation.MemorySize", aAdapterRAM, REG_DWORD))) {
591 aAdapterRAM = L"Unknown";
593 return NS_OK;
596 /* readonly attribute DOMString adapterDriver; */
597 NS_IMETHODIMP
598 GfxInfo::GetAdapterDriver(nsAString & aAdapterDriver)
600 if (NS_FAILED(GetKeyValue(mDeviceKey.get(), L"InstalledDisplayDrivers", aAdapterDriver, REG_MULTI_SZ)))
601 aAdapterDriver = L"Unknown";
602 return NS_OK;
605 /* readonly attribute DOMString adapterDriver2; */
606 NS_IMETHODIMP
607 GfxInfo::GetAdapterDriver2(nsAString & aAdapterDriver)
609 if (!mHasDualGPU) {
610 aAdapterDriver.Truncate();
611 } else if (NS_FAILED(GetKeyValue(mDeviceKey2.get(), L"InstalledDisplayDrivers", aAdapterDriver, REG_MULTI_SZ))) {
612 aAdapterDriver = L"Unknown";
614 return NS_OK;
617 /* readonly attribute DOMString adapterDriverVersion; */
618 NS_IMETHODIMP
619 GfxInfo::GetAdapterDriverVersion(nsAString & aAdapterDriverVersion)
621 aAdapterDriverVersion = mDriverVersion;
622 return NS_OK;
625 /* readonly attribute DOMString adapterDriverDate; */
626 NS_IMETHODIMP
627 GfxInfo::GetAdapterDriverDate(nsAString & aAdapterDriverDate)
629 aAdapterDriverDate = mDriverDate;
630 return NS_OK;
633 /* readonly attribute DOMString adapterDriverVersion2; */
634 NS_IMETHODIMP
635 GfxInfo::GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion)
637 aAdapterDriverVersion = mDriverVersion2;
638 return NS_OK;
641 /* readonly attribute DOMString adapterDriverDate2; */
642 NS_IMETHODIMP
643 GfxInfo::GetAdapterDriverDate2(nsAString & aAdapterDriverDate)
645 aAdapterDriverDate = mDriverDate2;
646 return NS_OK;
649 /* readonly attribute DOMString adapterVendorID; */
650 NS_IMETHODIMP
651 GfxInfo::GetAdapterVendorID(nsAString & aAdapterVendorID)
653 aAdapterVendorID = mAdapterVendorID;
654 return NS_OK;
657 /* readonly attribute DOMString adapterVendorID2; */
658 NS_IMETHODIMP
659 GfxInfo::GetAdapterVendorID2(nsAString & aAdapterVendorID)
661 aAdapterVendorID = mAdapterVendorID2;
662 return NS_OK;
665 /* readonly attribute DOMString adapterDeviceID; */
666 NS_IMETHODIMP
667 GfxInfo::GetAdapterDeviceID(nsAString & aAdapterDeviceID)
669 aAdapterDeviceID = mAdapterDeviceID;
670 return NS_OK;
673 /* readonly attribute DOMString adapterDeviceID2; */
674 NS_IMETHODIMP
675 GfxInfo::GetAdapterDeviceID2(nsAString & aAdapterDeviceID)
677 aAdapterDeviceID = mAdapterDeviceID2;
678 return NS_OK;
681 /* readonly attribute DOMString adapterSubsysID; */
682 NS_IMETHODIMP
683 GfxInfo::GetAdapterSubsysID(nsAString & aAdapterSubsysID)
685 aAdapterSubsysID = mAdapterSubsysID;
686 return NS_OK;
689 /* readonly attribute DOMString adapterSubsysID2; */
690 NS_IMETHODIMP
691 GfxInfo::GetAdapterSubsysID2(nsAString & aAdapterSubsysID)
693 aAdapterSubsysID = mAdapterSubsysID2;
694 return NS_OK;
697 /* readonly attribute boolean isGPU2Active; */
698 NS_IMETHODIMP
699 GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active)
701 *aIsGPU2Active = mIsGPU2Active;
702 return NS_OK;
705 #if defined(MOZ_CRASHREPORTER)
706 /* Cisco's VPN software can cause corruption of the floating point state.
707 * Make a note of this in our crash reports so that some weird crashes
708 * make more sense */
709 static void
710 CheckForCiscoVPN() {
711 LONG result;
712 HKEY key;
713 /* This will give false positives, but hopefully no false negatives */
714 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Cisco Systems\\VPN Client", 0, KEY_QUERY_VALUE, &key);
715 if (result == ERROR_SUCCESS) {
716 RegCloseKey(key);
717 CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("Cisco VPN\n"));
720 #endif
722 /* interface nsIGfxInfo2 */
723 /* readonly attribute DOMString countryCode; */
724 NS_IMETHODIMP
725 GfxInfo::GetCountryCode(nsAString& aCountryCode)
727 aCountryCode = mCountryCode;
728 return NS_OK;
731 void
732 GfxInfo::AddCrashReportAnnotations()
734 #if defined(MOZ_CRASHREPORTER)
735 CheckForCiscoVPN();
737 if (mHasDriverVersionMismatch) {
738 CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("DriverVersionMismatch\n"));
741 nsString deviceID, vendorID, driverVersion, subsysID;
742 nsCString narrowDeviceID, narrowVendorID, narrowDriverVersion, narrowSubsysID;
744 GetAdapterDeviceID(deviceID);
745 CopyUTF16toUTF8(deviceID, narrowDeviceID);
746 GetAdapterVendorID(vendorID);
747 CopyUTF16toUTF8(vendorID, narrowVendorID);
748 GetAdapterDriverVersion(driverVersion);
749 CopyUTF16toUTF8(driverVersion, narrowDriverVersion);
750 GetAdapterSubsysID(subsysID);
751 CopyUTF16toUTF8(subsysID, narrowSubsysID);
753 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterVendorID"),
754 narrowVendorID);
755 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterDeviceID"),
756 narrowDeviceID);
757 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterDriverVersion"),
758 narrowDriverVersion);
759 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterSubsysID"),
760 narrowSubsysID);
762 /* Add an App Note for now so that we get the data immediately. These
763 * can go away after we store the above in the socorro db */
764 nsAutoCString note;
765 /* AppendPrintf only supports 32 character strings, mrghh. */
766 note.AppendLiteral("AdapterVendorID: ");
767 note.Append(narrowVendorID);
768 note.AppendLiteral(", AdapterDeviceID: ");
769 note.Append(narrowDeviceID);
770 note.AppendLiteral(", AdapterSubsysID: ");
771 note.Append(narrowSubsysID);
772 note.AppendLiteral(", AdapterDriverVersion: ");
773 note.Append(NS_LossyConvertUTF16toASCII(driverVersion));
775 if (vendorID == GfxDriverInfo::GetDeviceVendor(VendorAll)) {
776 /* if we didn't find a valid vendorID lets append the mDeviceID string to try to find out why */
777 note.AppendLiteral(", ");
778 LossyAppendUTF16toASCII(mDeviceID, note);
779 note.AppendLiteral(", ");
780 LossyAppendUTF16toASCII(mDeviceKeyDebug, note);
781 LossyAppendUTF16toASCII(mDeviceKeyDebug, note);
783 note.Append("\n");
785 if (mHasDualGPU) {
786 nsString deviceID2, vendorID2, subsysID2;
787 nsAutoString adapterDriverVersionString2;
788 nsCString narrowDeviceID2, narrowVendorID2, narrowSubsysID2;
790 note.AppendLiteral("Has dual GPUs. GPU #2: ");
791 GetAdapterDeviceID2(deviceID2);
792 CopyUTF16toUTF8(deviceID2, narrowDeviceID2);
793 GetAdapterVendorID2(vendorID2);
794 CopyUTF16toUTF8(vendorID2, narrowVendorID2);
795 GetAdapterDriverVersion2(adapterDriverVersionString2);
796 GetAdapterSubsysID(subsysID2);
797 CopyUTF16toUTF8(subsysID2, narrowSubsysID2);
798 note.AppendLiteral("AdapterVendorID2: ");
799 note.Append(narrowVendorID2);
800 note.AppendLiteral(", AdapterDeviceID2: ");
801 note.Append(narrowDeviceID2);
802 note.AppendLiteral(", AdapterSubsysID2: ");
803 note.Append(narrowSubsysID2);
804 note.AppendLiteral(", AdapterDriverVersion2: ");
805 note.Append(NS_LossyConvertUTF16toASCII(adapterDriverVersionString2));
807 CrashReporter::AppendAppNotesToCrashReport(note);
809 #endif
812 void
813 GfxInfo::GetCountryCode()
815 GEOID geoid = GetUserGeoID(GEOCLASS_NATION);
816 if (geoid == GEOID_NOT_AVAILABLE) {
817 return;
819 // Get required length
820 int numChars = GetGeoInfoW(geoid, GEO_ISO2, nullptr, 0, 0);
821 if (!numChars) {
822 return;
824 // Now get the string for real
825 mCountryCode.SetLength(numChars);
826 numChars = GetGeoInfoW(geoid, GEO_ISO2, mCountryCode.BeginWriting(),
827 mCountryCode.Length(), 0);
828 if (numChars) {
829 // numChars includes null terminator
830 mCountryCode.Truncate(numChars - 1);
834 static OperatingSystem
835 WindowsVersionToOperatingSystem(int32_t aWindowsVersion)
837 switch(aWindowsVersion) {
838 case kWindowsXP:
839 return DRIVER_OS_WINDOWS_XP;
840 case kWindowsServer2003:
841 return DRIVER_OS_WINDOWS_SERVER_2003;
842 case kWindowsVista:
843 return DRIVER_OS_WINDOWS_VISTA;
844 case kWindows7:
845 return DRIVER_OS_WINDOWS_7;
846 case kWindows8:
847 return DRIVER_OS_WINDOWS_8;
848 case kWindows8_1:
849 return DRIVER_OS_WINDOWS_8_1;
850 case kWindows10:
851 return DRIVER_OS_WINDOWS_10;
852 case kWindowsUnknown:
853 default:
854 return DRIVER_OS_UNKNOWN;
858 const nsTArray<GfxDriverInfo>&
859 GfxInfo::GetGfxDriverInfo()
861 if (!mDriverInfo->Length()) {
863 * It should be noted here that more specialized rules on certain features
864 * should be inserted -before- more generalized restriction. As the first
865 * match for feature/OS/device found in the list will be used for the final
866 * blacklisting call.
870 * NVIDIA entries
872 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_XP,
873 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
874 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
875 DRIVER_LESS_THAN, V(6,14,11,8265), "182.65" );
876 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_VISTA,
877 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
878 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
879 DRIVER_LESS_THAN, V(8,17,11,8265), "182.65" );
880 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_7,
881 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
882 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
883 DRIVER_LESS_THAN, V(8,17,11,8265), "182.65" );
886 * AMD/ATI entries
888 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL,
889 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
890 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
891 DRIVER_LESS_THAN, V(8,62,0,0), "9.6" );
892 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL,
893 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices,
894 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
895 DRIVER_LESS_THAN, V(8,62,0,0), "9.6" );
897 // Bug 1099252
898 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_WINDOWS_7,
899 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
900 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
901 DRIVER_EQUAL, V(8,832,0,0));
904 * Bug 783517 - crashes in AMD driver on Windows 8
906 APPEND_TO_DRIVER_BLOCKLIST_RANGE( DRIVER_OS_WINDOWS_8,
907 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
908 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
909 DRIVER_BETWEEN_INCLUSIVE_START, V(8,982,0,0), V(8,983,0,0), "!= 8.982.*.*" );
910 APPEND_TO_DRIVER_BLOCKLIST_RANGE( DRIVER_OS_WINDOWS_8,
911 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices,
912 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
913 DRIVER_BETWEEN_INCLUSIVE_START, V(8,982,0,0), V(8,983,0,0), "!= 8.982.*.*" );
915 /* OpenGL on any ATI/AMD hardware is discouraged
916 * See:
917 * bug 619773 - WebGL: Crash with blue screen : "NMI: Parity Check / Memory Parity Error"
918 * bugs 584403, 584404, 620924 - crashes in atioglxx
919 * + many complaints about incorrect rendering
921 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
922 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
923 nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
924 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
925 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
926 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
927 nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
928 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
929 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
930 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices,
931 nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
932 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
933 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
934 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices,
935 nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
936 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
939 * Intel entries
942 /* The driver versions used here come from bug 594877. They might not
943 * be particularly relevant anymore.
945 #define IMPLEMENT_INTEL_DRIVER_BLOCKLIST(winVer, devFamily, driverVer) \
946 APPEND_TO_DRIVER_BLOCKLIST2( winVer, \
947 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(devFamily), \
948 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, \
949 DRIVER_LESS_THAN, driverVer )
951 #define IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(winVer, devFamily, driverVer) \
952 APPEND_TO_DRIVER_BLOCKLIST2( winVer, \
953 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(devFamily), \
954 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, \
955 DRIVER_LESS_THAN, driverVer )
957 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMA500, V(7,14,10,1006));
958 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMA900, GfxDriverInfo::allDriverVersions);
959 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMA950, V(7,14,10,1504));
960 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMA3150, V(7,14,10,2124));
961 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMAX3000, V(7,15,10,1666));
962 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMAX4500HD, V(8,15,10,2202));
964 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMA500, V(5,0,0,2026));
965 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMA900, GfxDriverInfo::allDriverVersions);
966 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMA950, V(8,15,10,1930));
967 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMA3150, V(8,14,10,2117));
968 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMAX3000, V(8,15,10,1930));
969 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMAX4500HD, V(8,15,10,2202));
971 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMA500, V(3,0,20,3200));
972 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMA900, V(6,14,10,4764));
973 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMA950, V(6,14,10,4926));
974 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMA3150, V(6,14,10,5134));
975 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMAX3000, V(6,14,10,5218));
976 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMAX4500HD, V(6,14,10,4969));
978 // StrechRect seems to suffer from precision issues which leads to artifacting
979 // during content drawing starting with at least version 6.14.10.5082
980 // and going until 6.14.10.5218. See bug 919454 and bug 949275 for more info.
981 APPEND_TO_DRIVER_BLOCKLIST_RANGE(DRIVER_OS_WINDOWS_XP,
982 const_cast<nsAString&>(GfxDriverInfo::GetDeviceVendor(VendorIntel)),
983 const_cast<GfxDeviceFamily*>(GfxDriverInfo::GetDeviceFamily(IntelGMAX4500HD)),
984 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
985 DRIVER_BETWEEN_EXCLUSIVE, V(6,14,10,5076), V(6,14,10,5218), "6.14.10.5218");
987 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA500, V(3,0,20,3200));
988 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA900, GfxDriverInfo::allDriverVersions);
989 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA950, V(7,14,10,1504));
990 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA3150, V(7,14,10,1910));
991 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMAX3000, V(7,15,10,1666));
992 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMAX4500HD, V(7,15,10,1666));
994 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA500, V(5,0,0,2026));
995 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA900, GfxDriverInfo::allDriverVersions);
996 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA950, V(8,15,10,1930));
997 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA3150, V(8,14,10,1972));
998 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMAX3000, V(7,15,10,1666));
999 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMAX4500HD, V(7,15,10,1666));
1001 // Bug 1074378
1002 APPEND_TO_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7,
1003 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel),
1004 (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(IntelGMAX4500HD),
1005 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1006 DRIVER_EQUAL, V(8,15,10,1749), "8.15.10.2342");
1008 /* OpenGL on any Intel hardware is discouraged */
1009 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
1010 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), GfxDriverInfo::allDevices,
1011 nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
1012 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
1013 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
1014 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), GfxDriverInfo::allDevices,
1015 nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
1016 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
1019 * Disable acceleration on Intel HD 3000 for graphics drivers <= 8.15.10.2321.
1020 * See bug 1018278 and bug 1060736.
1022 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL,
1023 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(IntelHD3000),
1024 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1025 DRIVER_LESS_THAN_OR_EQUAL, V(8,15,10,2321), "8.15.10.2342" );
1027 /* Disable D2D on Win7 on Intel HD Graphics on driver <= 8.15.10.2302
1028 * See bug 806786
1030 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_WINDOWS_7,
1031 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(IntelMobileHDGraphics),
1032 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1033 DRIVER_LESS_THAN_OR_EQUAL, V(8,15,10,2302) );
1035 /* Disable D2D on Win8 on Intel HD Graphics on driver <= 8.15.10.2302
1036 * See bug 804144 and 863683
1038 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_WINDOWS_8,
1039 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(IntelMobileHDGraphics),
1040 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1041 DRIVER_LESS_THAN_OR_EQUAL, V(8,15,10,2302) );
1043 /* Disable D2D on AMD Catalyst 14.4 until 14.6
1044 * See bug 984488
1046 APPEND_TO_DRIVER_BLOCKLIST_RANGE( DRIVER_OS_ALL,
1047 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
1048 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1049 DRIVER_BETWEEN_INCLUSIVE_START, V(14,1,0,0), V(14,2,0,0), "ATI Catalyst 14.6+");
1050 APPEND_TO_DRIVER_BLOCKLIST_RANGE( DRIVER_OS_ALL,
1051 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices,
1052 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1053 DRIVER_BETWEEN_INCLUSIVE_START, V(14,1,0,0), V(14,2,0,0), "ATI Catalyst 14.6+");
1055 /* Disable D3D9 layers on NVIDIA 6100/6150/6200 series due to glitches
1056 * whilst scrolling. See bugs: 612007, 644787 & 645872.
1058 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
1059 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(NvidiaBlockD3D9Layers),
1060 nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1061 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
1063 /* Microsoft RemoteFX; blocked less than 6.2.0.0 */
1064 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL,
1065 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorMicrosoft), GfxDriverInfo::allDevices,
1066 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1067 DRIVER_LESS_THAN, V(6,2,0,0), "< 6.2.0.0" );
1069 /* Bug 1008759: Optimus (NVidia) crash. Disable D2D on NV 310M. */
1070 APPEND_TO_DRIVER_BLOCKLIST2(DRIVER_OS_ALL,
1071 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(Nvidia310M),
1072 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1073 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions);
1075 APPEND_TO_DRIVER_BLOCKLIST2(DRIVER_OS_ALL,
1076 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI), (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(AMDRadeonHD5800),
1077 nsIGfxInfo::FEATURE_DXVA, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
1078 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions);
1080 /* Bug 1139503: DXVA crashes with ATI cards on windows 10. */
1081 APPEND_TO_DRIVER_BLOCKLIST2(DRIVER_OS_WINDOWS_10,
1082 (nsAString&)GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
1083 nsIGfxInfo::FEATURE_DXVA, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1084 DRIVER_EQUAL, V(15,200,1006,0));
1086 /* Bug 1137716: XXX this should really check for the matching Intel piece as well.
1087 * Unfortunately, we don't have the infrastructure to do that */
1088 APPEND_TO_DRIVER_BLOCKLIST_RANGE_GPU2(DRIVER_OS_WINDOWS_7,
1089 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), (GfxDeviceFamily*)GfxDriverInfo::GetDeviceFamily(Bug1137716),
1090 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
1091 DRIVER_BETWEEN_INCLUSIVE, V(8,7,12,5730), V(8,17,12,6901), "Nvidia driver > 8.17.12.6901");
1094 return *mDriverInfo;
1097 nsresult
1098 GfxInfo::GetFeatureStatusImpl(int32_t aFeature,
1099 int32_t *aStatus,
1100 nsAString & aSuggestedDriverVersion,
1101 const nsTArray<GfxDriverInfo>& aDriverInfo,
1102 OperatingSystem* aOS /* = nullptr */)
1104 NS_ENSURE_ARG_POINTER(aStatus);
1105 aSuggestedDriverVersion.SetIsVoid(true);
1106 OperatingSystem os = WindowsVersionToOperatingSystem(mWindowsVersion);
1107 *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
1108 if (aOS)
1109 *aOS = os;
1111 // Don't evaluate special cases if we're checking the downloaded blocklist.
1112 if (!aDriverInfo.Length()) {
1113 nsAutoString adapterVendorID;
1114 nsAutoString adapterDeviceID;
1115 nsAutoString adapterDriverVersionString;
1116 if (NS_FAILED(GetAdapterVendorID(adapterVendorID)) ||
1117 NS_FAILED(GetAdapterDeviceID(adapterDeviceID)) ||
1118 NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString)))
1120 return NS_ERROR_FAILURE;
1123 if (!adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorIntel), nsCaseInsensitiveStringComparator()) &&
1124 !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), nsCaseInsensitiveStringComparator()) &&
1125 !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorAMD), nsCaseInsensitiveStringComparator()) &&
1126 !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorATI), nsCaseInsensitiveStringComparator()) &&
1127 !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorMicrosoft), nsCaseInsensitiveStringComparator()) &&
1128 // FIXME - these special hex values are currently used in xpcshell tests introduced by
1129 // bug 625160 patch 8/8. Maybe these tests need to be adjusted now that we're only whitelisting
1130 // intel/ati/nvidia.
1131 !adapterVendorID.LowerCaseEqualsLiteral("0xabcd") &&
1132 !adapterVendorID.LowerCaseEqualsLiteral("0xdcba") &&
1133 !adapterVendorID.LowerCaseEqualsLiteral("0xabab") &&
1134 !adapterVendorID.LowerCaseEqualsLiteral("0xdcdc"))
1136 *aStatus = FEATURE_BLOCKED_DEVICE;
1137 return NS_OK;
1140 uint64_t driverVersion;
1141 if (!ParseDriverVersion(adapterDriverVersionString, &driverVersion)) {
1142 return NS_ERROR_FAILURE;
1145 // special-case the WinXP test slaves: they have out-of-date drivers, but we still want to
1146 // whitelist them, actually we do know that this combination of device and driver version
1147 // works well.
1148 if (mWindowsVersion == kWindowsXP &&
1149 adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), nsCaseInsensitiveStringComparator()) &&
1150 adapterDeviceID.LowerCaseEqualsLiteral("0x0861") && // GeForce 9400
1151 driverVersion == V(6,14,11,7756))
1153 *aStatus = FEATURE_STATUS_OK;
1154 return NS_OK;
1157 // Windows Server 2003 should be just like Windows XP for present purpose, but still has a different version number.
1158 // OTOH Windows Server 2008 R1 and R2 already have the same version numbers as Vista and Seven respectively
1159 if (os == DRIVER_OS_WINDOWS_SERVER_2003)
1160 os = DRIVER_OS_WINDOWS_XP;
1162 if (mHasDriverVersionMismatch) {
1163 *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
1164 return NS_OK;
1168 return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, &os);
1171 #ifdef DEBUG
1173 // Implement nsIGfxInfoDebug
1175 /* void spoofVendorID (in DOMString aVendorID); */
1176 NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID)
1178 mAdapterVendorID = aVendorID;
1179 return NS_OK;
1182 /* void spoofDeviceID (in unsigned long aDeviceID); */
1183 NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID)
1185 mAdapterDeviceID = aDeviceID;
1186 return NS_OK;
1189 /* void spoofDriverVersion (in DOMString aDriverVersion); */
1190 NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion)
1192 mDriverVersion = aDriverVersion;
1193 return NS_OK;
1196 /* void spoofOSVersion (in unsigned long aVersion); */
1197 NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion)
1199 mWindowsVersion = aVersion;
1200 return NS_OK;
1203 #endif