widget/windows/GfxInfo.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "mozilla/ArrayUtils.h"
michael@0 7
michael@0 8 #include <windows.h>
michael@0 9 #include <setupapi.h>
michael@0 10 #include "gfxWindowsPlatform.h"
michael@0 11 #include "GfxInfo.h"
michael@0 12 #include "GfxInfoWebGL.h"
michael@0 13 #include "nsUnicharUtils.h"
michael@0 14 #include "prenv.h"
michael@0 15 #include "prprf.h"
michael@0 16 #include "GfxDriverInfo.h"
michael@0 17 #include "mozilla/Preferences.h"
michael@0 18 #include "nsPrintfCString.h"
michael@0 19
michael@0 20 #if defined(MOZ_CRASHREPORTER)
michael@0 21 #include "nsExceptionHandler.h"
michael@0 22 #include "nsICrashReporter.h"
michael@0 23 #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"
michael@0 24 #endif
michael@0 25
michael@0 26 using namespace mozilla;
michael@0 27 using namespace mozilla::widget;
michael@0 28
michael@0 29 #ifdef DEBUG
michael@0 30 NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug)
michael@0 31 #endif
michael@0 32
michael@0 33 static const uint32_t allWindowsVersions = 0xffffffff;
michael@0 34
michael@0 35 GfxInfo::GfxInfo()
michael@0 36 : mWindowsVersion(0),
michael@0 37 mHasDualGPU(false),
michael@0 38 mIsGPU2Active(false)
michael@0 39 {
michael@0 40 }
michael@0 41
michael@0 42 /* GetD2DEnabled and GetDwriteEnabled shouldn't be called until after gfxPlatform initialization
michael@0 43 * has occurred because they depend on it for information. (See bug 591561) */
michael@0 44 nsresult
michael@0 45 GfxInfo::GetD2DEnabled(bool *aEnabled)
michael@0 46 {
michael@0 47 *aEnabled = gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D;
michael@0 48 return NS_OK;
michael@0 49 }
michael@0 50
michael@0 51 nsresult
michael@0 52 GfxInfo::GetDWriteEnabled(bool *aEnabled)
michael@0 53 {
michael@0 54 *aEnabled = gfxWindowsPlatform::GetPlatform()->DWriteEnabled();
michael@0 55 return NS_OK;
michael@0 56 }
michael@0 57
michael@0 58 /* readonly attribute DOMString DWriteVersion; */
michael@0 59 NS_IMETHODIMP
michael@0 60 GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
michael@0 61 {
michael@0 62 gfxWindowsPlatform::GetDLLVersion(L"dwrite.dll", aDwriteVersion);
michael@0 63 return NS_OK;
michael@0 64 }
michael@0 65
michael@0 66 #define PIXEL_STRUCT_RGB 1
michael@0 67 #define PIXEL_STRUCT_BGR 2
michael@0 68
michael@0 69 /* readonly attribute DOMString cleartypeParameters; */
michael@0 70 NS_IMETHODIMP
michael@0 71 GfxInfo::GetCleartypeParameters(nsAString & aCleartypeParams)
michael@0 72 {
michael@0 73 nsTArray<ClearTypeParameterInfo> clearTypeParams;
michael@0 74
michael@0 75 gfxWindowsPlatform::GetPlatform()->GetCleartypeParams(clearTypeParams);
michael@0 76 uint32_t d, numDisplays = clearTypeParams.Length();
michael@0 77 bool displayNames = (numDisplays > 1);
michael@0 78 bool foundData = false;
michael@0 79 nsString outStr;
michael@0 80
michael@0 81 for (d = 0; d < numDisplays; d++) {
michael@0 82 ClearTypeParameterInfo& params = clearTypeParams[d];
michael@0 83
michael@0 84 if (displayNames) {
michael@0 85 outStr.AppendPrintf("%s [ ", params.displayName.get());
michael@0 86 }
michael@0 87
michael@0 88 if (params.gamma >= 0) {
michael@0 89 foundData = true;
michael@0 90 outStr.AppendPrintf("Gamma: %d ", params.gamma);
michael@0 91 }
michael@0 92
michael@0 93 if (params.pixelStructure >= 0) {
michael@0 94 foundData = true;
michael@0 95 if (params.pixelStructure == PIXEL_STRUCT_RGB ||
michael@0 96 params.pixelStructure == PIXEL_STRUCT_BGR)
michael@0 97 {
michael@0 98 outStr.AppendPrintf("Pixel Structure: %s ",
michael@0 99 (params.pixelStructure == PIXEL_STRUCT_RGB ?
michael@0 100 L"RGB" : L"BGR"));
michael@0 101 } else {
michael@0 102 outStr.AppendPrintf("Pixel Structure: %d ", params.pixelStructure);
michael@0 103 }
michael@0 104 }
michael@0 105
michael@0 106 if (params.clearTypeLevel >= 0) {
michael@0 107 foundData = true;
michael@0 108 outStr.AppendPrintf("ClearType Level: %d ", params.clearTypeLevel);
michael@0 109 }
michael@0 110
michael@0 111 if (params.enhancedContrast >= 0) {
michael@0 112 foundData = true;
michael@0 113 outStr.AppendPrintf("Enhanced Contrast: %d ", params.enhancedContrast);
michael@0 114 }
michael@0 115
michael@0 116 if (displayNames) {
michael@0 117 outStr.Append(MOZ_UTF16("] "));
michael@0 118 }
michael@0 119 }
michael@0 120
michael@0 121 if (foundData) {
michael@0 122 aCleartypeParams.Assign(outStr);
michael@0 123 return NS_OK;
michael@0 124 }
michael@0 125 return NS_ERROR_FAILURE;
michael@0 126 }
michael@0 127
michael@0 128 static nsresult GetKeyValue(const WCHAR* keyLocation, const WCHAR* keyName, nsAString& destString, int type)
michael@0 129 {
michael@0 130 HKEY key;
michael@0 131 DWORD dwcbData;
michael@0 132 DWORD dValue;
michael@0 133 DWORD resultType;
michael@0 134 LONG result;
michael@0 135 nsresult retval = NS_OK;
michael@0 136
michael@0 137 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyLocation, 0, KEY_QUERY_VALUE, &key);
michael@0 138 if (result != ERROR_SUCCESS) {
michael@0 139 return NS_ERROR_FAILURE;
michael@0 140 }
michael@0 141
michael@0 142 switch (type) {
michael@0 143 case REG_DWORD: {
michael@0 144 // We only use this for vram size
michael@0 145 dwcbData = sizeof(dValue);
michael@0 146 result = RegQueryValueExW(key, keyName, nullptr, &resultType,
michael@0 147 (LPBYTE)&dValue, &dwcbData);
michael@0 148 if (result == ERROR_SUCCESS && resultType == REG_DWORD) {
michael@0 149 dValue = dValue / 1024 / 1024;
michael@0 150 destString.AppendInt(int32_t(dValue));
michael@0 151 } else {
michael@0 152 retval = NS_ERROR_FAILURE;
michael@0 153 }
michael@0 154 break;
michael@0 155 }
michael@0 156 case REG_MULTI_SZ: {
michael@0 157 // A chain of null-separated strings; we convert the nulls to spaces
michael@0 158 WCHAR wCharValue[1024];
michael@0 159 dwcbData = sizeof(wCharValue);
michael@0 160
michael@0 161 result = RegQueryValueExW(key, keyName, nullptr, &resultType,
michael@0 162 (LPBYTE)wCharValue, &dwcbData);
michael@0 163 if (result == ERROR_SUCCESS && resultType == REG_MULTI_SZ) {
michael@0 164 // This bit here could probably be cleaner.
michael@0 165 bool isValid = false;
michael@0 166
michael@0 167 DWORD strLen = dwcbData/sizeof(wCharValue[0]);
michael@0 168 for (DWORD i = 0; i < strLen; i++) {
michael@0 169 if (wCharValue[i] == '\0') {
michael@0 170 if (i < strLen - 1 && wCharValue[i + 1] == '\0') {
michael@0 171 isValid = true;
michael@0 172 break;
michael@0 173 } else {
michael@0 174 wCharValue[i] = ' ';
michael@0 175 }
michael@0 176 }
michael@0 177 }
michael@0 178
michael@0 179 // ensure wCharValue is null terminated
michael@0 180 wCharValue[strLen-1] = '\0';
michael@0 181
michael@0 182 if (isValid)
michael@0 183 destString = wCharValue;
michael@0 184
michael@0 185 } else {
michael@0 186 retval = NS_ERROR_FAILURE;
michael@0 187 }
michael@0 188
michael@0 189 break;
michael@0 190 }
michael@0 191 }
michael@0 192 RegCloseKey(key);
michael@0 193
michael@0 194 return retval;
michael@0 195 }
michael@0 196
michael@0 197 // The driver ID is a string like PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD, possibly
michael@0 198 // followed by &REV_XXXX. We uppercase the string, and strip the &REV_ part
michael@0 199 // from it, if found.
michael@0 200 static void normalizeDriverId(nsString& driverid) {
michael@0 201 ToUpperCase(driverid);
michael@0 202 int32_t rev = driverid.Find(NS_LITERAL_CSTRING("&REV_"));
michael@0 203 if (rev != -1) {
michael@0 204 driverid.Cut(rev, driverid.Length());
michael@0 205 }
michael@0 206 }
michael@0 207
michael@0 208 // The device ID is a string like PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD
michael@0 209 // this function is used to extract the id's out of it
michael@0 210 uint32_t
michael@0 211 ParseIDFromDeviceID(const nsAString &key, const char *prefix, int length)
michael@0 212 {
michael@0 213 nsAutoString id(key);
michael@0 214 ToUpperCase(id);
michael@0 215 int32_t start = id.Find(prefix);
michael@0 216 if (start != -1) {
michael@0 217 id.Cut(0, start + strlen(prefix));
michael@0 218 id.Truncate(length);
michael@0 219 }
michael@0 220 nsresult err;
michael@0 221 return id.ToInteger(&err, 16);
michael@0 222 }
michael@0 223
michael@0 224 // OS version in 16.16 major/minor form
michael@0 225 // based on http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
michael@0 226 enum {
michael@0 227 kWindowsUnknown = 0,
michael@0 228 kWindowsXP = 0x50001,
michael@0 229 kWindowsServer2003 = 0x50002,
michael@0 230 kWindowsVista = 0x60000,
michael@0 231 kWindows7 = 0x60001,
michael@0 232 kWindows8 = 0x60002,
michael@0 233 kWindows8_1 = 0x60003
michael@0 234 };
michael@0 235
michael@0 236 static int32_t
michael@0 237 WindowsOSVersion()
michael@0 238 {
michael@0 239 static int32_t winVersion = UNINITIALIZED_VALUE;
michael@0 240
michael@0 241 OSVERSIONINFO vinfo;
michael@0 242
michael@0 243 if (winVersion == UNINITIALIZED_VALUE) {
michael@0 244 vinfo.dwOSVersionInfoSize = sizeof (vinfo);
michael@0 245 #pragma warning(push)
michael@0 246 #pragma warning(disable:4996)
michael@0 247 if (!GetVersionEx(&vinfo)) {
michael@0 248 #pragma warning(pop)
michael@0 249 winVersion = kWindowsUnknown;
michael@0 250 } else {
michael@0 251 winVersion = int32_t(vinfo.dwMajorVersion << 16) + vinfo.dwMinorVersion;
michael@0 252 }
michael@0 253 }
michael@0 254
michael@0 255 return winVersion;
michael@0 256 }
michael@0 257
michael@0 258 /* Other interesting places for info:
michael@0 259 * IDXGIAdapter::GetDesc()
michael@0 260 * IDirectDraw7::GetAvailableVidMem()
michael@0 261 * e->GetAvailableTextureMem()
michael@0 262 * */
michael@0 263
michael@0 264 #define DEVICE_KEY_PREFIX L"\\Registry\\Machine\\"
michael@0 265 nsresult
michael@0 266 GfxInfo::Init()
michael@0 267 {
michael@0 268 nsresult rv = GfxInfoBase::Init();
michael@0 269
michael@0 270 DISPLAY_DEVICEW displayDevice;
michael@0 271 displayDevice.cb = sizeof(displayDevice);
michael@0 272 int deviceIndex = 0;
michael@0 273
michael@0 274 const char *spoofedWindowsVersion = PR_GetEnv("MOZ_GFX_SPOOF_WINDOWS_VERSION");
michael@0 275 if (spoofedWindowsVersion) {
michael@0 276 PR_sscanf(spoofedWindowsVersion, "%x", &mWindowsVersion);
michael@0 277 } else {
michael@0 278 mWindowsVersion = WindowsOSVersion();
michael@0 279 }
michael@0 280
michael@0 281 mDeviceKeyDebug = NS_LITERAL_STRING("PrimarySearch");
michael@0 282
michael@0 283 while (EnumDisplayDevicesW(nullptr, deviceIndex, &displayDevice, 0)) {
michael@0 284 if (displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
michael@0 285 mDeviceKeyDebug = NS_LITERAL_STRING("NullSearch");
michael@0 286 break;
michael@0 287 }
michael@0 288 deviceIndex++;
michael@0 289 }
michael@0 290
michael@0 291 // make sure the string is nullptr terminated
michael@0 292 if (wcsnlen(displayDevice.DeviceKey, ArrayLength(displayDevice.DeviceKey))
michael@0 293 == ArrayLength(displayDevice.DeviceKey)) {
michael@0 294 // we did not find a nullptr
michael@0 295 return rv;
michael@0 296 }
michael@0 297
michael@0 298 mDeviceKeyDebug = displayDevice.DeviceKey;
michael@0 299
michael@0 300 /* DeviceKey is "reserved" according to MSDN so we'll be careful with it */
michael@0 301 /* check that DeviceKey begins with DEVICE_KEY_PREFIX */
michael@0 302 /* some systems have a DeviceKey starting with \REGISTRY\Machine\ so we need to compare case insenstively */
michael@0 303 if (_wcsnicmp(displayDevice.DeviceKey, DEVICE_KEY_PREFIX, ArrayLength(DEVICE_KEY_PREFIX)-1) != 0)
michael@0 304 return rv;
michael@0 305
michael@0 306 // chop off DEVICE_KEY_PREFIX
michael@0 307 mDeviceKey = displayDevice.DeviceKey + ArrayLength(DEVICE_KEY_PREFIX)-1;
michael@0 308
michael@0 309 mDeviceID = displayDevice.DeviceID;
michael@0 310 mDeviceString = displayDevice.DeviceString;
michael@0 311
michael@0 312 // On Windows 8 and Server 2012 hosts, we want to not block RDP
michael@0 313 // sessions from attempting hardware acceleration. RemoteFX
michael@0 314 // provides features and functionaltiy that can give a good D3D10 +
michael@0 315 // D2D + DirectWrite experience emulated via a software GPU.
michael@0 316 //
michael@0 317 // Unfortunately, the Device ID is nullptr, and we can't enumerate
michael@0 318 // it using the setup infrastructure (SetupDiGetClassDevsW below
michael@0 319 // will return INVALID_HANDLE_VALUE).
michael@0 320 if (mWindowsVersion == kWindows8 &&
michael@0 321 mDeviceID.Length() == 0 &&
michael@0 322 mDeviceString.EqualsLiteral("RDPUDD Chained DD"))
michael@0 323 {
michael@0 324 WCHAR sysdir[255];
michael@0 325 UINT len = GetSystemDirectory(sysdir, sizeof(sysdir));
michael@0 326 if (len < sizeof(sysdir)) {
michael@0 327 nsString rdpudd(sysdir);
michael@0 328 rdpudd.AppendLiteral("\\rdpudd.dll");
michael@0 329 gfxWindowsPlatform::GetDLLVersion(rdpudd.BeginReading(), mDriverVersion);
michael@0 330 mDriverDate.AssignLiteral("01-01-1970");
michael@0 331
michael@0 332 // 0x1414 is Microsoft; 0xfefe is an invented (and unused) code
michael@0 333 mDeviceID.AssignLiteral("PCI\\VEN_1414&DEV_FEFE&SUBSYS_00000000");
michael@0 334 }
michael@0 335 }
michael@0 336
michael@0 337 /* create a device information set composed of the current display device */
michael@0 338 HDEVINFO devinfo = SetupDiGetClassDevsW(nullptr, mDeviceID.get(), nullptr,
michael@0 339 DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
michael@0 340
michael@0 341 if (devinfo != INVALID_HANDLE_VALUE) {
michael@0 342 HKEY key;
michael@0 343 LONG result;
michael@0 344 WCHAR value[255];
michael@0 345 DWORD dwcbData;
michael@0 346 SP_DEVINFO_DATA devinfoData;
michael@0 347 DWORD memberIndex = 0;
michael@0 348
michael@0 349 devinfoData.cbSize = sizeof(devinfoData);
michael@0 350 NS_NAMED_LITERAL_STRING(driverKeyPre, "System\\CurrentControlSet\\Control\\Class\\");
michael@0 351 /* enumerate device information elements in the device information set */
michael@0 352 while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) {
michael@0 353 /* get a string that identifies the device's driver key */
michael@0 354 if (SetupDiGetDeviceRegistryPropertyW(devinfo,
michael@0 355 &devinfoData,
michael@0 356 SPDRP_DRIVER,
michael@0 357 nullptr,
michael@0 358 (PBYTE)value,
michael@0 359 sizeof(value),
michael@0 360 nullptr)) {
michael@0 361 nsAutoString driverKey(driverKeyPre);
michael@0 362 driverKey += value;
michael@0 363 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey.get(), 0, KEY_QUERY_VALUE, &key);
michael@0 364 if (result == ERROR_SUCCESS) {
michael@0 365 /* we've found the driver we're looking for */
michael@0 366 dwcbData = sizeof(value);
michael@0 367 result = RegQueryValueExW(key, L"DriverVersion", nullptr, nullptr,
michael@0 368 (LPBYTE)value, &dwcbData);
michael@0 369 if (result == ERROR_SUCCESS) {
michael@0 370 mDriverVersion = value;
michael@0 371 } else {
michael@0 372 // If the entry wasn't found, assume the worst (0.0.0.0).
michael@0 373 mDriverVersion.AssignLiteral("0.0.0.0");
michael@0 374 }
michael@0 375 dwcbData = sizeof(value);
michael@0 376 result = RegQueryValueExW(key, L"DriverDate", nullptr, nullptr,
michael@0 377 (LPBYTE)value, &dwcbData);
michael@0 378 if (result == ERROR_SUCCESS) {
michael@0 379 mDriverDate = value;
michael@0 380 } else {
michael@0 381 // Again, assume the worst
michael@0 382 mDriverDate.AssignLiteral("01-01-1970");
michael@0 383 }
michael@0 384 RegCloseKey(key);
michael@0 385 break;
michael@0 386 }
michael@0 387 }
michael@0 388 }
michael@0 389
michael@0 390 SetupDiDestroyDeviceInfoList(devinfo);
michael@0 391 }
michael@0 392
michael@0 393 mAdapterVendorID.AppendPrintf("0x%04x", ParseIDFromDeviceID(mDeviceID, "VEN_", 4));
michael@0 394 mAdapterDeviceID.AppendPrintf("0x%04x", ParseIDFromDeviceID(mDeviceID, "&DEV_", 4));
michael@0 395 mAdapterSubsysID = ParseIDFromDeviceID(mDeviceID, "&SUBSYS_", 8);
michael@0 396
michael@0 397 // We now check for second display adapter.
michael@0 398
michael@0 399 // Device interface class for display adapters.
michael@0 400 CLSID GUID_DISPLAY_DEVICE_ARRIVAL;
michael@0 401 HRESULT hresult = CLSIDFromString(L"{1CA05180-A699-450A-9A0C-DE4FBE3DDD89}",
michael@0 402 &GUID_DISPLAY_DEVICE_ARRIVAL);
michael@0 403 if (hresult == NOERROR) {
michael@0 404 devinfo = SetupDiGetClassDevsW(&GUID_DISPLAY_DEVICE_ARRIVAL,
michael@0 405 nullptr, nullptr,
michael@0 406 DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
michael@0 407
michael@0 408 if (devinfo != INVALID_HANDLE_VALUE) {
michael@0 409 HKEY key;
michael@0 410 LONG result;
michael@0 411 WCHAR value[255];
michael@0 412 DWORD dwcbData;
michael@0 413 SP_DEVINFO_DATA devinfoData;
michael@0 414 DWORD memberIndex = 0;
michael@0 415 devinfoData.cbSize = sizeof(devinfoData);
michael@0 416
michael@0 417 nsAutoString adapterDriver2;
michael@0 418 nsAutoString deviceID2;
michael@0 419 nsAutoString driverVersion2;
michael@0 420 nsAutoString driverDate2;
michael@0 421 uint32_t adapterVendorID2;
michael@0 422 uint32_t adapterDeviceID2;
michael@0 423
michael@0 424 NS_NAMED_LITERAL_STRING(driverKeyPre, "System\\CurrentControlSet\\Control\\Class\\");
michael@0 425 /* enumerate device information elements in the device information set */
michael@0 426 while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) {
michael@0 427 /* get a string that identifies the device's driver key */
michael@0 428 if (SetupDiGetDeviceRegistryPropertyW(devinfo,
michael@0 429 &devinfoData,
michael@0 430 SPDRP_DRIVER,
michael@0 431 nullptr,
michael@0 432 (PBYTE)value,
michael@0 433 sizeof(value),
michael@0 434 nullptr)) {
michael@0 435 nsAutoString driverKey2(driverKeyPre);
michael@0 436 driverKey2 += value;
michael@0 437 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey2.get(), 0, KEY_QUERY_VALUE, &key);
michael@0 438 if (result == ERROR_SUCCESS) {
michael@0 439 dwcbData = sizeof(value);
michael@0 440 result = RegQueryValueExW(key, L"MatchingDeviceId", nullptr,
michael@0 441 nullptr, (LPBYTE)value, &dwcbData);
michael@0 442 if (result != ERROR_SUCCESS) {
michael@0 443 continue;
michael@0 444 }
michael@0 445 deviceID2 = value;
michael@0 446 nsAutoString adapterVendorID2String;
michael@0 447 nsAutoString adapterDeviceID2String;
michael@0 448 adapterVendorID2 = ParseIDFromDeviceID(deviceID2, "VEN_", 4);
michael@0 449 adapterVendorID2String.AppendPrintf("0x%04x", adapterVendorID2);
michael@0 450 adapterDeviceID2 = ParseIDFromDeviceID(deviceID2, "&DEV_", 4);
michael@0 451 adapterDeviceID2String.AppendPrintf("0x%04x", adapterDeviceID2);
michael@0 452 if (mAdapterVendorID == adapterVendorID2String &&
michael@0 453 mAdapterDeviceID == adapterDeviceID2String) {
michael@0 454 RegCloseKey(key);
michael@0 455 continue;
michael@0 456 }
michael@0 457
michael@0 458 // If this device is missing driver information, it is unlikely to
michael@0 459 // be a real display adapter.
michael@0 460 if (NS_FAILED(GetKeyValue(driverKey2.get(), L"InstalledDisplayDrivers",
michael@0 461 adapterDriver2, REG_MULTI_SZ))) {
michael@0 462 RegCloseKey(key);
michael@0 463 continue;
michael@0 464 }
michael@0 465 dwcbData = sizeof(value);
michael@0 466 result = RegQueryValueExW(key, L"DriverVersion", nullptr, nullptr,
michael@0 467 (LPBYTE)value, &dwcbData);
michael@0 468 if (result != ERROR_SUCCESS) {
michael@0 469 RegCloseKey(key);
michael@0 470 continue;
michael@0 471 }
michael@0 472 driverVersion2 = value;
michael@0 473 dwcbData = sizeof(value);
michael@0 474 result = RegQueryValueExW(key, L"DriverDate", nullptr, nullptr,
michael@0 475 (LPBYTE)value, &dwcbData);
michael@0 476 if (result != ERROR_SUCCESS) {
michael@0 477 RegCloseKey(key);
michael@0 478 continue;
michael@0 479 }
michael@0 480 driverDate2 = value;
michael@0 481 dwcbData = sizeof(value);
michael@0 482 result = RegQueryValueExW(key, L"Device Description", nullptr,
michael@0 483 nullptr, (LPBYTE)value, &dwcbData);
michael@0 484 if (result != ERROR_SUCCESS) {
michael@0 485 dwcbData = sizeof(value);
michael@0 486 result = RegQueryValueExW(key, L"DriverDesc", nullptr, nullptr,
michael@0 487 (LPBYTE)value, &dwcbData);
michael@0 488 }
michael@0 489 RegCloseKey(key);
michael@0 490 if (result == ERROR_SUCCESS) {
michael@0 491 mHasDualGPU = true;
michael@0 492 mDeviceString2 = value;
michael@0 493 mDeviceID2 = deviceID2;
michael@0 494 mDeviceKey2 = driverKey2;
michael@0 495 mDriverVersion2 = driverVersion2;
michael@0 496 mDriverDate2 = driverDate2;
michael@0 497 mAdapterVendorID2.AppendPrintf("0x%04x", adapterVendorID2);
michael@0 498 mAdapterDeviceID2.AppendPrintf("0x%04x", adapterDeviceID2);
michael@0 499 mAdapterSubsysID2 = ParseIDFromDeviceID(mDeviceID2, "&SUBSYS_", 8);
michael@0 500 break;
michael@0 501 }
michael@0 502 }
michael@0 503 }
michael@0 504 }
michael@0 505
michael@0 506 SetupDiDestroyDeviceInfoList(devinfo);
michael@0 507 }
michael@0 508 }
michael@0 509
michael@0 510 mHasDriverVersionMismatch = false;
michael@0 511 if (mAdapterVendorID == GfxDriverInfo::GetDeviceVendor(VendorIntel)) {
michael@0 512 // we've had big crashers (bugs 590373 and 595364) apparently correlated
michael@0 513 // with bad Intel driver installations where the DriverVersion reported
michael@0 514 // by the registry was not the version of the DLL.
michael@0 515 bool is64bitApp = sizeof(void*) == 8;
michael@0 516 const char16_t *dllFileName = is64bitApp
michael@0 517 ? MOZ_UTF16("igd10umd64.dll")
michael@0 518 : MOZ_UTF16("igd10umd32.dll"),
michael@0 519 *dllFileName2 = is64bitApp
michael@0 520 ? MOZ_UTF16("igd10iumd64.dll")
michael@0 521 : MOZ_UTF16("igd10iumd32.dll");
michael@0 522 nsString dllVersion, dllVersion2;
michael@0 523 gfxWindowsPlatform::GetDLLVersion((char16_t*)dllFileName, dllVersion);
michael@0 524 gfxWindowsPlatform::GetDLLVersion((char16_t*)dllFileName2, dllVersion2);
michael@0 525
michael@0 526 uint64_t dllNumericVersion = 0, dllNumericVersion2 = 0,
michael@0 527 driverNumericVersion = 0, knownSafeMismatchVersion = 0;
michael@0 528 ParseDriverVersion(dllVersion, &dllNumericVersion);
michael@0 529 ParseDriverVersion(dllVersion2, &dllNumericVersion2);
michael@0 530 ParseDriverVersion(mDriverVersion, &driverNumericVersion);
michael@0 531 ParseDriverVersion(NS_LITERAL_STRING("9.17.10.0"), &knownSafeMismatchVersion);
michael@0 532
michael@0 533 // If there's a driver version mismatch, consider this harmful only when
michael@0 534 // the driver version is less than knownSafeMismatchVersion. See the
michael@0 535 // above comment about crashes with old mismatches. If the GetDllVersion
michael@0 536 // call fails, then they return 0, so that will be considered a mismatch.
michael@0 537 if (dllNumericVersion != driverNumericVersion &&
michael@0 538 dllNumericVersion2 != driverNumericVersion &&
michael@0 539 (driverNumericVersion < knownSafeMismatchVersion ||
michael@0 540 std::max(dllNumericVersion, dllNumericVersion2) < knownSafeMismatchVersion)) {
michael@0 541 mHasDriverVersionMismatch = true;
michael@0 542 }
michael@0 543 }
michael@0 544
michael@0 545 const char *spoofedDriverVersionString = PR_GetEnv("MOZ_GFX_SPOOF_DRIVER_VERSION");
michael@0 546 if (spoofedDriverVersionString) {
michael@0 547 mDriverVersion.AssignASCII(spoofedDriverVersionString);
michael@0 548 }
michael@0 549
michael@0 550 const char *spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_VENDOR_ID");
michael@0 551 if (spoofedVendor) {
michael@0 552 mAdapterVendorID.AssignASCII(spoofedVendor);
michael@0 553 }
michael@0 554
michael@0 555 const char *spoofedDevice = PR_GetEnv("MOZ_GFX_SPOOF_DEVICE_ID");
michael@0 556 if (spoofedDevice) {
michael@0 557 mAdapterDeviceID.AssignASCII(spoofedDevice);
michael@0 558 }
michael@0 559
michael@0 560 AddCrashReportAnnotations();
michael@0 561
michael@0 562 return rv;
michael@0 563 }
michael@0 564
michael@0 565 /* readonly attribute DOMString adapterDescription; */
michael@0 566 NS_IMETHODIMP
michael@0 567 GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription)
michael@0 568 {
michael@0 569 aAdapterDescription = mDeviceString;
michael@0 570 return NS_OK;
michael@0 571 }
michael@0 572
michael@0 573 /* readonly attribute DOMString adapterDescription2; */
michael@0 574 NS_IMETHODIMP
michael@0 575 GfxInfo::GetAdapterDescription2(nsAString & aAdapterDescription)
michael@0 576 {
michael@0 577 aAdapterDescription = mDeviceString2;
michael@0 578 return NS_OK;
michael@0 579 }
michael@0 580
michael@0 581 /* readonly attribute DOMString adapterRAM; */
michael@0 582 NS_IMETHODIMP
michael@0 583 GfxInfo::GetAdapterRAM(nsAString & aAdapterRAM)
michael@0 584 {
michael@0 585 if (NS_FAILED(GetKeyValue(mDeviceKey.get(), L"HardwareInformation.MemorySize", aAdapterRAM, REG_DWORD)))
michael@0 586 aAdapterRAM = L"Unknown";
michael@0 587 return NS_OK;
michael@0 588 }
michael@0 589
michael@0 590 /* readonly attribute DOMString adapterRAM2; */
michael@0 591 NS_IMETHODIMP
michael@0 592 GfxInfo::GetAdapterRAM2(nsAString & aAdapterRAM)
michael@0 593 {
michael@0 594 if (!mHasDualGPU) {
michael@0 595 aAdapterRAM.AssignLiteral("");
michael@0 596 } else if (NS_FAILED(GetKeyValue(mDeviceKey2.get(), L"HardwareInformation.MemorySize", aAdapterRAM, REG_DWORD))) {
michael@0 597 aAdapterRAM = L"Unknown";
michael@0 598 }
michael@0 599 return NS_OK;
michael@0 600 }
michael@0 601
michael@0 602 /* readonly attribute DOMString adapterDriver; */
michael@0 603 NS_IMETHODIMP
michael@0 604 GfxInfo::GetAdapterDriver(nsAString & aAdapterDriver)
michael@0 605 {
michael@0 606 if (NS_FAILED(GetKeyValue(mDeviceKey.get(), L"InstalledDisplayDrivers", aAdapterDriver, REG_MULTI_SZ)))
michael@0 607 aAdapterDriver = L"Unknown";
michael@0 608 return NS_OK;
michael@0 609 }
michael@0 610
michael@0 611 /* readonly attribute DOMString adapterDriver2; */
michael@0 612 NS_IMETHODIMP
michael@0 613 GfxInfo::GetAdapterDriver2(nsAString & aAdapterDriver)
michael@0 614 {
michael@0 615 if (!mHasDualGPU) {
michael@0 616 aAdapterDriver.AssignLiteral("");
michael@0 617 } else if (NS_FAILED(GetKeyValue(mDeviceKey2.get(), L"InstalledDisplayDrivers", aAdapterDriver, REG_MULTI_SZ))) {
michael@0 618 aAdapterDriver = L"Unknown";
michael@0 619 }
michael@0 620 return NS_OK;
michael@0 621 }
michael@0 622
michael@0 623 /* readonly attribute DOMString adapterDriverVersion; */
michael@0 624 NS_IMETHODIMP
michael@0 625 GfxInfo::GetAdapterDriverVersion(nsAString & aAdapterDriverVersion)
michael@0 626 {
michael@0 627 aAdapterDriverVersion = mDriverVersion;
michael@0 628 return NS_OK;
michael@0 629 }
michael@0 630
michael@0 631 /* readonly attribute DOMString adapterDriverDate; */
michael@0 632 NS_IMETHODIMP
michael@0 633 GfxInfo::GetAdapterDriverDate(nsAString & aAdapterDriverDate)
michael@0 634 {
michael@0 635 aAdapterDriverDate = mDriverDate;
michael@0 636 return NS_OK;
michael@0 637 }
michael@0 638
michael@0 639 /* readonly attribute DOMString adapterDriverVersion2; */
michael@0 640 NS_IMETHODIMP
michael@0 641 GfxInfo::GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion)
michael@0 642 {
michael@0 643 aAdapterDriverVersion = mDriverVersion2;
michael@0 644 return NS_OK;
michael@0 645 }
michael@0 646
michael@0 647 /* readonly attribute DOMString adapterDriverDate2; */
michael@0 648 NS_IMETHODIMP
michael@0 649 GfxInfo::GetAdapterDriverDate2(nsAString & aAdapterDriverDate)
michael@0 650 {
michael@0 651 aAdapterDriverDate = mDriverDate2;
michael@0 652 return NS_OK;
michael@0 653 }
michael@0 654
michael@0 655 /* readonly attribute DOMString adapterVendorID; */
michael@0 656 NS_IMETHODIMP
michael@0 657 GfxInfo::GetAdapterVendorID(nsAString & aAdapterVendorID)
michael@0 658 {
michael@0 659 aAdapterVendorID = mAdapterVendorID;
michael@0 660 return NS_OK;
michael@0 661 }
michael@0 662
michael@0 663 /* readonly attribute DOMString adapterVendorID2; */
michael@0 664 NS_IMETHODIMP
michael@0 665 GfxInfo::GetAdapterVendorID2(nsAString & aAdapterVendorID)
michael@0 666 {
michael@0 667 aAdapterVendorID = mAdapterVendorID2;
michael@0 668 return NS_OK;
michael@0 669 }
michael@0 670
michael@0 671 /* readonly attribute DOMString adapterDeviceID; */
michael@0 672 NS_IMETHODIMP
michael@0 673 GfxInfo::GetAdapterDeviceID(nsAString & aAdapterDeviceID)
michael@0 674 {
michael@0 675 aAdapterDeviceID = mAdapterDeviceID;
michael@0 676 return NS_OK;
michael@0 677 }
michael@0 678
michael@0 679 /* readonly attribute DOMString adapterDeviceID2; */
michael@0 680 NS_IMETHODIMP
michael@0 681 GfxInfo::GetAdapterDeviceID2(nsAString & aAdapterDeviceID)
michael@0 682 {
michael@0 683 aAdapterDeviceID = mAdapterDeviceID2;
michael@0 684 return NS_OK;
michael@0 685 }
michael@0 686
michael@0 687 /* readonly attribute boolean isGPU2Active; */
michael@0 688 NS_IMETHODIMP
michael@0 689 GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active)
michael@0 690 {
michael@0 691 *aIsGPU2Active = mIsGPU2Active;
michael@0 692 return NS_OK;
michael@0 693 }
michael@0 694
michael@0 695 #if defined(MOZ_CRASHREPORTER)
michael@0 696 /* Cisco's VPN software can cause corruption of the floating point state.
michael@0 697 * Make a note of this in our crash reports so that some weird crashes
michael@0 698 * make more sense */
michael@0 699 static void
michael@0 700 CheckForCiscoVPN() {
michael@0 701 LONG result;
michael@0 702 HKEY key;
michael@0 703 /* This will give false positives, but hopefully no false negatives */
michael@0 704 result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Cisco Systems\\VPN Client", 0, KEY_QUERY_VALUE, &key);
michael@0 705 if (result == ERROR_SUCCESS) {
michael@0 706 RegCloseKey(key);
michael@0 707 CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("Cisco VPN\n"));
michael@0 708 }
michael@0 709 }
michael@0 710 #endif
michael@0 711
michael@0 712 void
michael@0 713 GfxInfo::AddCrashReportAnnotations()
michael@0 714 {
michael@0 715 #if defined(MOZ_CRASHREPORTER)
michael@0 716 CheckForCiscoVPN();
michael@0 717
michael@0 718 nsString deviceID, vendorID;
michael@0 719 nsCString narrowDeviceID, narrowVendorID;
michael@0 720 nsAutoString adapterDriverVersionString;
michael@0 721
michael@0 722 GetAdapterDeviceID(deviceID);
michael@0 723 CopyUTF16toUTF8(deviceID, narrowDeviceID);
michael@0 724 GetAdapterVendorID(vendorID);
michael@0 725 CopyUTF16toUTF8(vendorID, narrowVendorID);
michael@0 726 GetAdapterDriverVersion(adapterDriverVersionString);
michael@0 727
michael@0 728 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterVendorID"),
michael@0 729 narrowVendorID);
michael@0 730 CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterDeviceID"),
michael@0 731 narrowDeviceID);
michael@0 732
michael@0 733 /* Add an App Note for now so that we get the data immediately. These
michael@0 734 * can go away after we store the above in the socorro db */
michael@0 735 nsAutoCString note;
michael@0 736 /* AppendPrintf only supports 32 character strings, mrghh. */
michael@0 737 note.Append("AdapterVendorID: ");
michael@0 738 note.Append(narrowVendorID);
michael@0 739 note.Append(", AdapterDeviceID: ");
michael@0 740 note.Append(narrowDeviceID);
michael@0 741 note.AppendPrintf(", AdapterSubsysID: %08x, ", mAdapterSubsysID);
michael@0 742 note.Append("AdapterDriverVersion: ");
michael@0 743 note.Append(NS_LossyConvertUTF16toASCII(adapterDriverVersionString));
michael@0 744
michael@0 745 if (vendorID == GfxDriverInfo::GetDeviceVendor(VendorAll)) {
michael@0 746 /* if we didn't find a valid vendorID lets append the mDeviceID string to try to find out why */
michael@0 747 note.Append(", ");
michael@0 748 LossyAppendUTF16toASCII(mDeviceID, note);
michael@0 749 note.Append(", ");
michael@0 750 LossyAppendUTF16toASCII(mDeviceKeyDebug, note);
michael@0 751 LossyAppendUTF16toASCII(mDeviceKeyDebug, note);
michael@0 752 }
michael@0 753 note.Append("\n");
michael@0 754
michael@0 755 if (mHasDualGPU) {
michael@0 756 nsString deviceID2, vendorID2;
michael@0 757 nsAutoString adapterDriverVersionString2;
michael@0 758 nsCString narrowDeviceID2, narrowVendorID2;
michael@0 759
michael@0 760 note.AppendLiteral("Has dual GPUs. GPU #2: ");
michael@0 761 GetAdapterDeviceID2(deviceID2);
michael@0 762 CopyUTF16toUTF8(deviceID2, narrowDeviceID2);
michael@0 763 GetAdapterVendorID2(vendorID2);
michael@0 764 CopyUTF16toUTF8(vendorID2, narrowVendorID2);
michael@0 765 GetAdapterDriverVersion2(adapterDriverVersionString2);
michael@0 766 note.Append("AdapterVendorID2: ");
michael@0 767 note.Append(narrowVendorID2);
michael@0 768 note.Append(", AdapterDeviceID2: ");
michael@0 769 note.Append(narrowDeviceID2);
michael@0 770 note.AppendPrintf(", AdapterSubsysID2: %08x, ", mAdapterSubsysID2);
michael@0 771 note.AppendPrintf("AdapterDriverVersion2: ");
michael@0 772 note.Append(NS_LossyConvertUTF16toASCII(adapterDriverVersionString2));
michael@0 773 }
michael@0 774 CrashReporter::AppendAppNotesToCrashReport(note);
michael@0 775
michael@0 776 #endif
michael@0 777 }
michael@0 778
michael@0 779 static OperatingSystem
michael@0 780 WindowsVersionToOperatingSystem(int32_t aWindowsVersion)
michael@0 781 {
michael@0 782 switch(aWindowsVersion) {
michael@0 783 case kWindowsXP:
michael@0 784 return DRIVER_OS_WINDOWS_XP;
michael@0 785 case kWindowsServer2003:
michael@0 786 return DRIVER_OS_WINDOWS_SERVER_2003;
michael@0 787 case kWindowsVista:
michael@0 788 return DRIVER_OS_WINDOWS_VISTA;
michael@0 789 case kWindows7:
michael@0 790 return DRIVER_OS_WINDOWS_7;
michael@0 791 case kWindows8:
michael@0 792 return DRIVER_OS_WINDOWS_8;
michael@0 793 case kWindows8_1:
michael@0 794 return DRIVER_OS_WINDOWS_8_1;
michael@0 795 case kWindowsUnknown:
michael@0 796 default:
michael@0 797 return DRIVER_OS_UNKNOWN;
michael@0 798 };
michael@0 799 }
michael@0 800
michael@0 801 const nsTArray<GfxDriverInfo>&
michael@0 802 GfxInfo::GetGfxDriverInfo()
michael@0 803 {
michael@0 804 if (!mDriverInfo->Length()) {
michael@0 805 /*
michael@0 806 * It should be noted here that more specialized rules on certain features
michael@0 807 * should be inserted -before- more generalized restriction. As the first
michael@0 808 * match for feature/OS/device found in the list will be used for the final
michael@0 809 * blacklisting call.
michael@0 810 */
michael@0 811
michael@0 812 /*
michael@0 813 * NVIDIA entries
michael@0 814 */
michael@0 815 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_VISTA,
michael@0 816 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
michael@0 817 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
michael@0 818 DRIVER_LESS_THAN, V(8,17,12,5721), "257.21" );
michael@0 819 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_7,
michael@0 820 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
michael@0 821 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
michael@0 822 DRIVER_LESS_THAN, V(8,17,12,5721), "257.21" );
michael@0 823 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_XP,
michael@0 824 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
michael@0 825 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
michael@0 826 DRIVER_LESS_THAN, V(6,14,11,8265), "182.65" );
michael@0 827 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_VISTA,
michael@0 828 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
michael@0 829 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
michael@0 830 DRIVER_LESS_THAN, V(8,17,11,8265), "182.65" );
michael@0 831 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_7,
michael@0 832 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
michael@0 833 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
michael@0 834 DRIVER_LESS_THAN, V(8,17,11,8265), "182.65" );
michael@0 835
michael@0 836 /*
michael@0 837 * AMD/ATI entries
michael@0 838 */
michael@0 839 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL,
michael@0 840 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
michael@0 841 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
michael@0 842 DRIVER_LESS_THAN, V(8,741,0,0), "10.6" );
michael@0 843 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL,
michael@0 844 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices,
michael@0 845 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
michael@0 846 DRIVER_LESS_THAN, V(8,741,0,0), "10.6" );
michael@0 847 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL,
michael@0 848 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
michael@0 849 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
michael@0 850 DRIVER_LESS_THAN, V(8,62,0,0), "9.6" );
michael@0 851 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL,
michael@0 852 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices,
michael@0 853 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
michael@0 854 DRIVER_LESS_THAN, V(8,62,0,0), "9.6" );
michael@0 855
michael@0 856 /*
michael@0 857 * Bug 783517 - crashes in AMD driver on Windows 8
michael@0 858 */
michael@0 859 APPEND_TO_DRIVER_BLOCKLIST_RANGE( DRIVER_OS_WINDOWS_8,
michael@0 860 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
michael@0 861 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
michael@0 862 DRIVER_BETWEEN_INCLUSIVE_START, V(8,982,0,0), V(8,983,0,0), "!= 8.982.*.*" );
michael@0 863 APPEND_TO_DRIVER_BLOCKLIST_RANGE( DRIVER_OS_WINDOWS_8,
michael@0 864 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices,
michael@0 865 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
michael@0 866 DRIVER_BETWEEN_INCLUSIVE_START, V(8,982,0,0), V(8,983,0,0), "!= 8.982.*.*" );
michael@0 867
michael@0 868 /* OpenGL on any ATI/AMD hardware is discouraged
michael@0 869 * See:
michael@0 870 * bug 619773 - WebGL: Crash with blue screen : "NMI: Parity Check / Memory Parity Error"
michael@0 871 * bugs 584403, 584404, 620924 - crashes in atioglxx
michael@0 872 * + many complaints about incorrect rendering
michael@0 873 */
michael@0 874 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
michael@0 875 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
michael@0 876 nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
michael@0 877 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
michael@0 878 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
michael@0 879 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices,
michael@0 880 nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
michael@0 881 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
michael@0 882 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
michael@0 883 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices,
michael@0 884 nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
michael@0 885 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
michael@0 886 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
michael@0 887 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices,
michael@0 888 nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
michael@0 889 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
michael@0 890
michael@0 891 /*
michael@0 892 * Intel entries
michael@0 893 */
michael@0 894
michael@0 895 /* implement the blocklist from bug 594877
michael@0 896 * Block all features on any drivers before this, as there's a crash when a MS Hotfix is installed.
michael@0 897 * The crash itself is Direct2D-related, but for safety we block all features.
michael@0 898 */
michael@0 899 #define IMPLEMENT_INTEL_DRIVER_BLOCKLIST(winVer, devFamily, driverVer) \
michael@0 900 APPEND_TO_DRIVER_BLOCKLIST2( winVer, \
michael@0 901 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(devFamily), \
michael@0 902 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, \
michael@0 903 DRIVER_LESS_THAN, driverVer )
michael@0 904 #define IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(winVer, devFamily, driverVer) \
michael@0 905 APPEND_TO_DRIVER_BLOCKLIST2( winVer, \
michael@0 906 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(devFamily), \
michael@0 907 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, \
michael@0 908 DRIVER_LESS_THAN, driverVer )
michael@0 909
michael@0 910 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMA500, V(7,14,10,1006));
michael@0 911 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMA900, GfxDriverInfo::allDriverVersions);
michael@0 912 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMA950, V(7,14,10,1504));
michael@0 913 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMA3150, V(7,14,10,2124));
michael@0 914 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMAX3000, V(7,15,10,1666));
michael@0 915 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMAX4500HD, V(8,15,10,2202));
michael@0 916
michael@0 917 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMA500, V(5,0,0,2026));
michael@0 918 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMA900, GfxDriverInfo::allDriverVersions);
michael@0 919 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMA950, V(8,15,10,1930));
michael@0 920 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMA3150, V(8,14,10,2117));
michael@0 921 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMAX3000, V(8,15,10,1930));
michael@0 922 IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMAX4500HD, V(8,15,10,2202));
michael@0 923
michael@0 924 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMA500, V(3,0,20,3200));
michael@0 925 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMA900, V(6,14,10,4764));
michael@0 926 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMA950, V(6,14,10,4926));
michael@0 927 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMA3150, V(6,14,10,5134));
michael@0 928 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMAX3000, V(6,14,10,5218));
michael@0 929 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMAX4500HD, V(6,14,10,4969));
michael@0 930
michael@0 931 // StrechRect seems to suffer from precision issues which leads to artifacting
michael@0 932 // during content drawing starting with at least version 6.14.10.5082
michael@0 933 // and going until 6.14.10.5218. See bug 919454 and bug 949275 for more info.
michael@0 934 APPEND_TO_DRIVER_BLOCKLIST_RANGE(DRIVER_OS_WINDOWS_XP,
michael@0 935 const_cast<nsAString&>(GfxDriverInfo::GetDeviceVendor(VendorIntel)),
michael@0 936 const_cast<GfxDeviceFamily*>(GfxDriverInfo::GetDeviceFamily(IntelGMAX4500HD)),
michael@0 937 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
michael@0 938 DRIVER_BETWEEN_EXCLUSIVE, V(6,14,10,5076), V(6,14,10,5218), "6.14.10.5218");
michael@0 939
michael@0 940 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA500, V(3,0,20,3200));
michael@0 941 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA900, GfxDriverInfo::allDriverVersions);
michael@0 942 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA950, V(7,14,10,1504));
michael@0 943 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA3150, V(7,14,10,1910));
michael@0 944 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMAX3000, V(7,15,10,1666));
michael@0 945 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMAX4500HD, V(7,15,10,1666));
michael@0 946
michael@0 947 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA500, V(5,0,0,2026));
michael@0 948 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA900, GfxDriverInfo::allDriverVersions);
michael@0 949 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA950, V(8,15,10,1930));
michael@0 950 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA3150, V(8,14,10,1972));
michael@0 951 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMAX3000, V(7,15,10,1666));
michael@0 952 IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMAX4500HD, V(7,15,10,1666));
michael@0 953
michael@0 954 /* OpenGL on any Intel hardware is discouraged */
michael@0 955 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
michael@0 956 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), GfxDriverInfo::allDevices,
michael@0 957 nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
michael@0 958 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
michael@0 959 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
michael@0 960 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), GfxDriverInfo::allDevices,
michael@0 961 nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
michael@0 962 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
michael@0 963
michael@0 964 /* Disable D2D on Win7 on Intel HD Graphics on driver <= 8.15.10.2302
michael@0 965 * See bug 806786
michael@0 966 */
michael@0 967 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_WINDOWS_7,
michael@0 968 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(IntelMobileHDGraphics),
michael@0 969 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
michael@0 970 DRIVER_LESS_THAN_OR_EQUAL, V(8,15,10,2302) );
michael@0 971
michael@0 972 /* Disable D2D on Win8 on Intel HD Graphics on driver <= 8.15.10.2302
michael@0 973 * See bug 804144 and 863683
michael@0 974 */
michael@0 975 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_WINDOWS_8,
michael@0 976 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(IntelMobileHDGraphics),
michael@0 977 nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
michael@0 978 DRIVER_LESS_THAN_OR_EQUAL, V(8,15,10,2302) );
michael@0 979
michael@0 980 /* Disable D3D9 layers on NVIDIA 6100/6150/6200 series due to glitches
michael@0 981 * whilst scrolling. See bugs: 612007, 644787 & 645872.
michael@0 982 */
michael@0 983 APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
michael@0 984 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(NvidiaBlockD3D9Layers),
michael@0 985 nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
michael@0 986 DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
michael@0 987
michael@0 988 /* Microsoft RemoteFX; blocked less than 6.2.0.0 */
michael@0 989 APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL,
michael@0 990 (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorMicrosoft), GfxDriverInfo::allDevices,
michael@0 991 GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
michael@0 992 DRIVER_LESS_THAN, V(6,2,0,0), "< 6.2.0.0" );
michael@0 993 }
michael@0 994 return *mDriverInfo;
michael@0 995 }
michael@0 996
michael@0 997 nsresult
michael@0 998 GfxInfo::GetFeatureStatusImpl(int32_t aFeature,
michael@0 999 int32_t *aStatus,
michael@0 1000 nsAString & aSuggestedDriverVersion,
michael@0 1001 const nsTArray<GfxDriverInfo>& aDriverInfo,
michael@0 1002 OperatingSystem* aOS /* = nullptr */)
michael@0 1003 {
michael@0 1004 NS_ENSURE_ARG_POINTER(aStatus);
michael@0 1005 aSuggestedDriverVersion.SetIsVoid(true);
michael@0 1006 OperatingSystem os = WindowsVersionToOperatingSystem(mWindowsVersion);
michael@0 1007 *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN;
michael@0 1008 if (aOS)
michael@0 1009 *aOS = os;
michael@0 1010
michael@0 1011 // Don't evaluate special cases if we're checking the downloaded blocklist.
michael@0 1012 if (!aDriverInfo.Length()) {
michael@0 1013 nsAutoString adapterVendorID;
michael@0 1014 nsAutoString adapterDeviceID;
michael@0 1015 nsAutoString adapterDriverVersionString;
michael@0 1016 if (NS_FAILED(GetAdapterVendorID(adapterVendorID)) ||
michael@0 1017 NS_FAILED(GetAdapterDeviceID(adapterDeviceID)) ||
michael@0 1018 NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString)))
michael@0 1019 {
michael@0 1020 return NS_ERROR_FAILURE;
michael@0 1021 }
michael@0 1022
michael@0 1023 if (!adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorIntel), nsCaseInsensitiveStringComparator()) &&
michael@0 1024 !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), nsCaseInsensitiveStringComparator()) &&
michael@0 1025 !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorAMD), nsCaseInsensitiveStringComparator()) &&
michael@0 1026 !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorATI), nsCaseInsensitiveStringComparator()) &&
michael@0 1027 !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorMicrosoft), nsCaseInsensitiveStringComparator()) &&
michael@0 1028 // FIXME - these special hex values are currently used in xpcshell tests introduced by
michael@0 1029 // bug 625160 patch 8/8. Maybe these tests need to be adjusted now that we're only whitelisting
michael@0 1030 // intel/ati/nvidia.
michael@0 1031 !adapterVendorID.LowerCaseEqualsLiteral("0xabcd") &&
michael@0 1032 !adapterVendorID.LowerCaseEqualsLiteral("0xdcba") &&
michael@0 1033 !adapterVendorID.LowerCaseEqualsLiteral("0xabab") &&
michael@0 1034 !adapterVendorID.LowerCaseEqualsLiteral("0xdcdc"))
michael@0 1035 {
michael@0 1036 *aStatus = FEATURE_BLOCKED_DEVICE;
michael@0 1037 return NS_OK;
michael@0 1038 }
michael@0 1039
michael@0 1040 uint64_t driverVersion;
michael@0 1041 if (!ParseDriverVersion(adapterDriverVersionString, &driverVersion)) {
michael@0 1042 return NS_ERROR_FAILURE;
michael@0 1043 }
michael@0 1044
michael@0 1045 // special-case the WinXP test slaves: they have out-of-date drivers, but we still want to
michael@0 1046 // whitelist them, actually we do know that this combination of device and driver version
michael@0 1047 // works well.
michael@0 1048 if (mWindowsVersion == kWindowsXP &&
michael@0 1049 adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), nsCaseInsensitiveStringComparator()) &&
michael@0 1050 adapterDeviceID.LowerCaseEqualsLiteral("0x0861") && // GeForce 9400
michael@0 1051 driverVersion == V(6,14,11,7756))
michael@0 1052 {
michael@0 1053 *aStatus = FEATURE_NO_INFO;
michael@0 1054 return NS_OK;
michael@0 1055 }
michael@0 1056
michael@0 1057 // Windows Server 2003 should be just like Windows XP for present purpose, but still has a different version number.
michael@0 1058 // OTOH Windows Server 2008 R1 and R2 already have the same version numbers as Vista and Seven respectively
michael@0 1059 if (os == DRIVER_OS_WINDOWS_SERVER_2003)
michael@0 1060 os = DRIVER_OS_WINDOWS_XP;
michael@0 1061
michael@0 1062 if (mHasDriverVersionMismatch) {
michael@0 1063 if (aFeature == nsIGfxInfo::FEATURE_DIRECT3D_10_LAYERS ||
michael@0 1064 aFeature == nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS ||
michael@0 1065 aFeature == nsIGfxInfo::FEATURE_DIRECT2D)
michael@0 1066 {
michael@0 1067 *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION;
michael@0 1068 return NS_OK;
michael@0 1069 }
michael@0 1070 }
michael@0 1071 }
michael@0 1072
michael@0 1073 return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, &os);
michael@0 1074 }
michael@0 1075
michael@0 1076 #ifdef DEBUG
michael@0 1077
michael@0 1078 // Implement nsIGfxInfoDebug
michael@0 1079
michael@0 1080 /* void spoofVendorID (in DOMString aVendorID); */
michael@0 1081 NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID)
michael@0 1082 {
michael@0 1083 mAdapterVendorID = aVendorID;
michael@0 1084 return NS_OK;
michael@0 1085 }
michael@0 1086
michael@0 1087 /* void spoofDeviceID (in unsigned long aDeviceID); */
michael@0 1088 NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID)
michael@0 1089 {
michael@0 1090 mAdapterDeviceID = aDeviceID;
michael@0 1091 return NS_OK;
michael@0 1092 }
michael@0 1093
michael@0 1094 /* void spoofDriverVersion (in DOMString aDriverVersion); */
michael@0 1095 NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion)
michael@0 1096 {
michael@0 1097 mDriverVersion = aDriverVersion;
michael@0 1098 return NS_OK;
michael@0 1099 }
michael@0 1100
michael@0 1101 /* void spoofOSVersion (in unsigned long aVersion); */
michael@0 1102 NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion)
michael@0 1103 {
michael@0 1104 mWindowsVersion = aVersion;
michael@0 1105 return NS_OK;
michael@0 1106 }
michael@0 1107
michael@0 1108 #endif

mercurial