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