Thu, 22 Jan 2015 13:21:57 +0100
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 |