michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/ArrayUtils.h" michael@0: michael@0: #include michael@0: #include michael@0: #include "gfxWindowsPlatform.h" michael@0: #include "GfxInfo.h" michael@0: #include "GfxInfoWebGL.h" michael@0: #include "nsUnicharUtils.h" michael@0: #include "prenv.h" michael@0: #include "prprf.h" michael@0: #include "GfxDriverInfo.h" michael@0: #include "mozilla/Preferences.h" michael@0: #include "nsPrintfCString.h" michael@0: michael@0: #if defined(MOZ_CRASHREPORTER) michael@0: #include "nsExceptionHandler.h" michael@0: #include "nsICrashReporter.h" michael@0: #define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1" michael@0: #endif michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::widget; michael@0: michael@0: #ifdef DEBUG michael@0: NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug) michael@0: #endif michael@0: michael@0: static const uint32_t allWindowsVersions = 0xffffffff; michael@0: michael@0: GfxInfo::GfxInfo() michael@0: : mWindowsVersion(0), michael@0: mHasDualGPU(false), michael@0: mIsGPU2Active(false) michael@0: { michael@0: } michael@0: michael@0: /* GetD2DEnabled and GetDwriteEnabled shouldn't be called until after gfxPlatform initialization michael@0: * has occurred because they depend on it for information. (See bug 591561) */ michael@0: nsresult michael@0: GfxInfo::GetD2DEnabled(bool *aEnabled) michael@0: { michael@0: *aEnabled = gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D; michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: GfxInfo::GetDWriteEnabled(bool *aEnabled) michael@0: { michael@0: *aEnabled = gfxWindowsPlatform::GetPlatform()->DWriteEnabled(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute DOMString DWriteVersion; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion) michael@0: { michael@0: gfxWindowsPlatform::GetDLLVersion(L"dwrite.dll", aDwriteVersion); michael@0: return NS_OK; michael@0: } michael@0: michael@0: #define PIXEL_STRUCT_RGB 1 michael@0: #define PIXEL_STRUCT_BGR 2 michael@0: michael@0: /* readonly attribute DOMString cleartypeParameters; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetCleartypeParameters(nsAString & aCleartypeParams) michael@0: { michael@0: nsTArray clearTypeParams; michael@0: michael@0: gfxWindowsPlatform::GetPlatform()->GetCleartypeParams(clearTypeParams); michael@0: uint32_t d, numDisplays = clearTypeParams.Length(); michael@0: bool displayNames = (numDisplays > 1); michael@0: bool foundData = false; michael@0: nsString outStr; michael@0: michael@0: for (d = 0; d < numDisplays; d++) { michael@0: ClearTypeParameterInfo& params = clearTypeParams[d]; michael@0: michael@0: if (displayNames) { michael@0: outStr.AppendPrintf("%s [ ", params.displayName.get()); michael@0: } michael@0: michael@0: if (params.gamma >= 0) { michael@0: foundData = true; michael@0: outStr.AppendPrintf("Gamma: %d ", params.gamma); michael@0: } michael@0: michael@0: if (params.pixelStructure >= 0) { michael@0: foundData = true; michael@0: if (params.pixelStructure == PIXEL_STRUCT_RGB || michael@0: params.pixelStructure == PIXEL_STRUCT_BGR) michael@0: { michael@0: outStr.AppendPrintf("Pixel Structure: %s ", michael@0: (params.pixelStructure == PIXEL_STRUCT_RGB ? michael@0: L"RGB" : L"BGR")); michael@0: } else { michael@0: outStr.AppendPrintf("Pixel Structure: %d ", params.pixelStructure); michael@0: } michael@0: } michael@0: michael@0: if (params.clearTypeLevel >= 0) { michael@0: foundData = true; michael@0: outStr.AppendPrintf("ClearType Level: %d ", params.clearTypeLevel); michael@0: } michael@0: michael@0: if (params.enhancedContrast >= 0) { michael@0: foundData = true; michael@0: outStr.AppendPrintf("Enhanced Contrast: %d ", params.enhancedContrast); michael@0: } michael@0: michael@0: if (displayNames) { michael@0: outStr.Append(MOZ_UTF16("] ")); michael@0: } michael@0: } michael@0: michael@0: if (foundData) { michael@0: aCleartypeParams.Assign(outStr); michael@0: return NS_OK; michael@0: } michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: static nsresult GetKeyValue(const WCHAR* keyLocation, const WCHAR* keyName, nsAString& destString, int type) michael@0: { michael@0: HKEY key; michael@0: DWORD dwcbData; michael@0: DWORD dValue; michael@0: DWORD resultType; michael@0: LONG result; michael@0: nsresult retval = NS_OK; michael@0: michael@0: result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyLocation, 0, KEY_QUERY_VALUE, &key); michael@0: if (result != ERROR_SUCCESS) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: switch (type) { michael@0: case REG_DWORD: { michael@0: // We only use this for vram size michael@0: dwcbData = sizeof(dValue); michael@0: result = RegQueryValueExW(key, keyName, nullptr, &resultType, michael@0: (LPBYTE)&dValue, &dwcbData); michael@0: if (result == ERROR_SUCCESS && resultType == REG_DWORD) { michael@0: dValue = dValue / 1024 / 1024; michael@0: destString.AppendInt(int32_t(dValue)); michael@0: } else { michael@0: retval = NS_ERROR_FAILURE; michael@0: } michael@0: break; michael@0: } michael@0: case REG_MULTI_SZ: { michael@0: // A chain of null-separated strings; we convert the nulls to spaces michael@0: WCHAR wCharValue[1024]; michael@0: dwcbData = sizeof(wCharValue); michael@0: michael@0: result = RegQueryValueExW(key, keyName, nullptr, &resultType, michael@0: (LPBYTE)wCharValue, &dwcbData); michael@0: if (result == ERROR_SUCCESS && resultType == REG_MULTI_SZ) { michael@0: // This bit here could probably be cleaner. michael@0: bool isValid = false; michael@0: michael@0: DWORD strLen = dwcbData/sizeof(wCharValue[0]); michael@0: for (DWORD i = 0; i < strLen; i++) { michael@0: if (wCharValue[i] == '\0') { michael@0: if (i < strLen - 1 && wCharValue[i + 1] == '\0') { michael@0: isValid = true; michael@0: break; michael@0: } else { michael@0: wCharValue[i] = ' '; michael@0: } michael@0: } michael@0: } michael@0: michael@0: // ensure wCharValue is null terminated michael@0: wCharValue[strLen-1] = '\0'; michael@0: michael@0: if (isValid) michael@0: destString = wCharValue; michael@0: michael@0: } else { michael@0: retval = NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: break; michael@0: } michael@0: } michael@0: RegCloseKey(key); michael@0: michael@0: return retval; michael@0: } michael@0: michael@0: // The driver ID is a string like PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD, possibly michael@0: // followed by &REV_XXXX. We uppercase the string, and strip the &REV_ part michael@0: // from it, if found. michael@0: static void normalizeDriverId(nsString& driverid) { michael@0: ToUpperCase(driverid); michael@0: int32_t rev = driverid.Find(NS_LITERAL_CSTRING("&REV_")); michael@0: if (rev != -1) { michael@0: driverid.Cut(rev, driverid.Length()); michael@0: } michael@0: } michael@0: michael@0: // The device ID is a string like PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD michael@0: // this function is used to extract the id's out of it michael@0: uint32_t michael@0: ParseIDFromDeviceID(const nsAString &key, const char *prefix, int length) michael@0: { michael@0: nsAutoString id(key); michael@0: ToUpperCase(id); michael@0: int32_t start = id.Find(prefix); michael@0: if (start != -1) { michael@0: id.Cut(0, start + strlen(prefix)); michael@0: id.Truncate(length); michael@0: } michael@0: nsresult err; michael@0: return id.ToInteger(&err, 16); michael@0: } michael@0: michael@0: // OS version in 16.16 major/minor form michael@0: // based on http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx michael@0: enum { michael@0: kWindowsUnknown = 0, michael@0: kWindowsXP = 0x50001, michael@0: kWindowsServer2003 = 0x50002, michael@0: kWindowsVista = 0x60000, michael@0: kWindows7 = 0x60001, michael@0: kWindows8 = 0x60002, michael@0: kWindows8_1 = 0x60003 michael@0: }; michael@0: michael@0: static int32_t michael@0: WindowsOSVersion() michael@0: { michael@0: static int32_t winVersion = UNINITIALIZED_VALUE; michael@0: michael@0: OSVERSIONINFO vinfo; michael@0: michael@0: if (winVersion == UNINITIALIZED_VALUE) { michael@0: vinfo.dwOSVersionInfoSize = sizeof (vinfo); michael@0: #pragma warning(push) michael@0: #pragma warning(disable:4996) michael@0: if (!GetVersionEx(&vinfo)) { michael@0: #pragma warning(pop) michael@0: winVersion = kWindowsUnknown; michael@0: } else { michael@0: winVersion = int32_t(vinfo.dwMajorVersion << 16) + vinfo.dwMinorVersion; michael@0: } michael@0: } michael@0: michael@0: return winVersion; michael@0: } michael@0: michael@0: /* Other interesting places for info: michael@0: * IDXGIAdapter::GetDesc() michael@0: * IDirectDraw7::GetAvailableVidMem() michael@0: * e->GetAvailableTextureMem() michael@0: * */ michael@0: michael@0: #define DEVICE_KEY_PREFIX L"\\Registry\\Machine\\" michael@0: nsresult michael@0: GfxInfo::Init() michael@0: { michael@0: nsresult rv = GfxInfoBase::Init(); michael@0: michael@0: DISPLAY_DEVICEW displayDevice; michael@0: displayDevice.cb = sizeof(displayDevice); michael@0: int deviceIndex = 0; michael@0: michael@0: const char *spoofedWindowsVersion = PR_GetEnv("MOZ_GFX_SPOOF_WINDOWS_VERSION"); michael@0: if (spoofedWindowsVersion) { michael@0: PR_sscanf(spoofedWindowsVersion, "%x", &mWindowsVersion); michael@0: } else { michael@0: mWindowsVersion = WindowsOSVersion(); michael@0: } michael@0: michael@0: mDeviceKeyDebug = NS_LITERAL_STRING("PrimarySearch"); michael@0: michael@0: while (EnumDisplayDevicesW(nullptr, deviceIndex, &displayDevice, 0)) { michael@0: if (displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { michael@0: mDeviceKeyDebug = NS_LITERAL_STRING("NullSearch"); michael@0: break; michael@0: } michael@0: deviceIndex++; michael@0: } michael@0: michael@0: // make sure the string is nullptr terminated michael@0: if (wcsnlen(displayDevice.DeviceKey, ArrayLength(displayDevice.DeviceKey)) michael@0: == ArrayLength(displayDevice.DeviceKey)) { michael@0: // we did not find a nullptr michael@0: return rv; michael@0: } michael@0: michael@0: mDeviceKeyDebug = displayDevice.DeviceKey; michael@0: michael@0: /* DeviceKey is "reserved" according to MSDN so we'll be careful with it */ michael@0: /* check that DeviceKey begins with DEVICE_KEY_PREFIX */ michael@0: /* some systems have a DeviceKey starting with \REGISTRY\Machine\ so we need to compare case insenstively */ michael@0: if (_wcsnicmp(displayDevice.DeviceKey, DEVICE_KEY_PREFIX, ArrayLength(DEVICE_KEY_PREFIX)-1) != 0) michael@0: return rv; michael@0: michael@0: // chop off DEVICE_KEY_PREFIX michael@0: mDeviceKey = displayDevice.DeviceKey + ArrayLength(DEVICE_KEY_PREFIX)-1; michael@0: michael@0: mDeviceID = displayDevice.DeviceID; michael@0: mDeviceString = displayDevice.DeviceString; michael@0: michael@0: // On Windows 8 and Server 2012 hosts, we want to not block RDP michael@0: // sessions from attempting hardware acceleration. RemoteFX michael@0: // provides features and functionaltiy that can give a good D3D10 + michael@0: // D2D + DirectWrite experience emulated via a software GPU. michael@0: // michael@0: // Unfortunately, the Device ID is nullptr, and we can't enumerate michael@0: // it using the setup infrastructure (SetupDiGetClassDevsW below michael@0: // will return INVALID_HANDLE_VALUE). michael@0: if (mWindowsVersion == kWindows8 && michael@0: mDeviceID.Length() == 0 && michael@0: mDeviceString.EqualsLiteral("RDPUDD Chained DD")) michael@0: { michael@0: WCHAR sysdir[255]; michael@0: UINT len = GetSystemDirectory(sysdir, sizeof(sysdir)); michael@0: if (len < sizeof(sysdir)) { michael@0: nsString rdpudd(sysdir); michael@0: rdpudd.AppendLiteral("\\rdpudd.dll"); michael@0: gfxWindowsPlatform::GetDLLVersion(rdpudd.BeginReading(), mDriverVersion); michael@0: mDriverDate.AssignLiteral("01-01-1970"); michael@0: michael@0: // 0x1414 is Microsoft; 0xfefe is an invented (and unused) code michael@0: mDeviceID.AssignLiteral("PCI\\VEN_1414&DEV_FEFE&SUBSYS_00000000"); michael@0: } michael@0: } michael@0: michael@0: /* create a device information set composed of the current display device */ michael@0: HDEVINFO devinfo = SetupDiGetClassDevsW(nullptr, mDeviceID.get(), nullptr, michael@0: DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES); michael@0: michael@0: if (devinfo != INVALID_HANDLE_VALUE) { michael@0: HKEY key; michael@0: LONG result; michael@0: WCHAR value[255]; michael@0: DWORD dwcbData; michael@0: SP_DEVINFO_DATA devinfoData; michael@0: DWORD memberIndex = 0; michael@0: michael@0: devinfoData.cbSize = sizeof(devinfoData); michael@0: NS_NAMED_LITERAL_STRING(driverKeyPre, "System\\CurrentControlSet\\Control\\Class\\"); michael@0: /* enumerate device information elements in the device information set */ michael@0: while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) { michael@0: /* get a string that identifies the device's driver key */ michael@0: if (SetupDiGetDeviceRegistryPropertyW(devinfo, michael@0: &devinfoData, michael@0: SPDRP_DRIVER, michael@0: nullptr, michael@0: (PBYTE)value, michael@0: sizeof(value), michael@0: nullptr)) { michael@0: nsAutoString driverKey(driverKeyPre); michael@0: driverKey += value; michael@0: result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey.get(), 0, KEY_QUERY_VALUE, &key); michael@0: if (result == ERROR_SUCCESS) { michael@0: /* we've found the driver we're looking for */ michael@0: dwcbData = sizeof(value); michael@0: result = RegQueryValueExW(key, L"DriverVersion", nullptr, nullptr, michael@0: (LPBYTE)value, &dwcbData); michael@0: if (result == ERROR_SUCCESS) { michael@0: mDriverVersion = value; michael@0: } else { michael@0: // If the entry wasn't found, assume the worst (0.0.0.0). michael@0: mDriverVersion.AssignLiteral("0.0.0.0"); michael@0: } michael@0: dwcbData = sizeof(value); michael@0: result = RegQueryValueExW(key, L"DriverDate", nullptr, nullptr, michael@0: (LPBYTE)value, &dwcbData); michael@0: if (result == ERROR_SUCCESS) { michael@0: mDriverDate = value; michael@0: } else { michael@0: // Again, assume the worst michael@0: mDriverDate.AssignLiteral("01-01-1970"); michael@0: } michael@0: RegCloseKey(key); michael@0: break; michael@0: } michael@0: } michael@0: } michael@0: michael@0: SetupDiDestroyDeviceInfoList(devinfo); michael@0: } michael@0: michael@0: mAdapterVendorID.AppendPrintf("0x%04x", ParseIDFromDeviceID(mDeviceID, "VEN_", 4)); michael@0: mAdapterDeviceID.AppendPrintf("0x%04x", ParseIDFromDeviceID(mDeviceID, "&DEV_", 4)); michael@0: mAdapterSubsysID = ParseIDFromDeviceID(mDeviceID, "&SUBSYS_", 8); michael@0: michael@0: // We now check for second display adapter. michael@0: michael@0: // Device interface class for display adapters. michael@0: CLSID GUID_DISPLAY_DEVICE_ARRIVAL; michael@0: HRESULT hresult = CLSIDFromString(L"{1CA05180-A699-450A-9A0C-DE4FBE3DDD89}", michael@0: &GUID_DISPLAY_DEVICE_ARRIVAL); michael@0: if (hresult == NOERROR) { michael@0: devinfo = SetupDiGetClassDevsW(&GUID_DISPLAY_DEVICE_ARRIVAL, michael@0: nullptr, nullptr, michael@0: DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); michael@0: michael@0: if (devinfo != INVALID_HANDLE_VALUE) { michael@0: HKEY key; michael@0: LONG result; michael@0: WCHAR value[255]; michael@0: DWORD dwcbData; michael@0: SP_DEVINFO_DATA devinfoData; michael@0: DWORD memberIndex = 0; michael@0: devinfoData.cbSize = sizeof(devinfoData); michael@0: michael@0: nsAutoString adapterDriver2; michael@0: nsAutoString deviceID2; michael@0: nsAutoString driverVersion2; michael@0: nsAutoString driverDate2; michael@0: uint32_t adapterVendorID2; michael@0: uint32_t adapterDeviceID2; michael@0: michael@0: NS_NAMED_LITERAL_STRING(driverKeyPre, "System\\CurrentControlSet\\Control\\Class\\"); michael@0: /* enumerate device information elements in the device information set */ michael@0: while (SetupDiEnumDeviceInfo(devinfo, memberIndex++, &devinfoData)) { michael@0: /* get a string that identifies the device's driver key */ michael@0: if (SetupDiGetDeviceRegistryPropertyW(devinfo, michael@0: &devinfoData, michael@0: SPDRP_DRIVER, michael@0: nullptr, michael@0: (PBYTE)value, michael@0: sizeof(value), michael@0: nullptr)) { michael@0: nsAutoString driverKey2(driverKeyPre); michael@0: driverKey2 += value; michael@0: result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey2.get(), 0, KEY_QUERY_VALUE, &key); michael@0: if (result == ERROR_SUCCESS) { michael@0: dwcbData = sizeof(value); michael@0: result = RegQueryValueExW(key, L"MatchingDeviceId", nullptr, michael@0: nullptr, (LPBYTE)value, &dwcbData); michael@0: if (result != ERROR_SUCCESS) { michael@0: continue; michael@0: } michael@0: deviceID2 = value; michael@0: nsAutoString adapterVendorID2String; michael@0: nsAutoString adapterDeviceID2String; michael@0: adapterVendorID2 = ParseIDFromDeviceID(deviceID2, "VEN_", 4); michael@0: adapterVendorID2String.AppendPrintf("0x%04x", adapterVendorID2); michael@0: adapterDeviceID2 = ParseIDFromDeviceID(deviceID2, "&DEV_", 4); michael@0: adapterDeviceID2String.AppendPrintf("0x%04x", adapterDeviceID2); michael@0: if (mAdapterVendorID == adapterVendorID2String && michael@0: mAdapterDeviceID == adapterDeviceID2String) { michael@0: RegCloseKey(key); michael@0: continue; michael@0: } michael@0: michael@0: // If this device is missing driver information, it is unlikely to michael@0: // be a real display adapter. michael@0: if (NS_FAILED(GetKeyValue(driverKey2.get(), L"InstalledDisplayDrivers", michael@0: adapterDriver2, REG_MULTI_SZ))) { michael@0: RegCloseKey(key); michael@0: continue; michael@0: } michael@0: dwcbData = sizeof(value); michael@0: result = RegQueryValueExW(key, L"DriverVersion", nullptr, nullptr, michael@0: (LPBYTE)value, &dwcbData); michael@0: if (result != ERROR_SUCCESS) { michael@0: RegCloseKey(key); michael@0: continue; michael@0: } michael@0: driverVersion2 = value; michael@0: dwcbData = sizeof(value); michael@0: result = RegQueryValueExW(key, L"DriverDate", nullptr, nullptr, michael@0: (LPBYTE)value, &dwcbData); michael@0: if (result != ERROR_SUCCESS) { michael@0: RegCloseKey(key); michael@0: continue; michael@0: } michael@0: driverDate2 = value; michael@0: dwcbData = sizeof(value); michael@0: result = RegQueryValueExW(key, L"Device Description", nullptr, michael@0: nullptr, (LPBYTE)value, &dwcbData); michael@0: if (result != ERROR_SUCCESS) { michael@0: dwcbData = sizeof(value); michael@0: result = RegQueryValueExW(key, L"DriverDesc", nullptr, nullptr, michael@0: (LPBYTE)value, &dwcbData); michael@0: } michael@0: RegCloseKey(key); michael@0: if (result == ERROR_SUCCESS) { michael@0: mHasDualGPU = true; michael@0: mDeviceString2 = value; michael@0: mDeviceID2 = deviceID2; michael@0: mDeviceKey2 = driverKey2; michael@0: mDriverVersion2 = driverVersion2; michael@0: mDriverDate2 = driverDate2; michael@0: mAdapterVendorID2.AppendPrintf("0x%04x", adapterVendorID2); michael@0: mAdapterDeviceID2.AppendPrintf("0x%04x", adapterDeviceID2); michael@0: mAdapterSubsysID2 = ParseIDFromDeviceID(mDeviceID2, "&SUBSYS_", 8); michael@0: break; michael@0: } michael@0: } michael@0: } michael@0: } michael@0: michael@0: SetupDiDestroyDeviceInfoList(devinfo); michael@0: } michael@0: } michael@0: michael@0: mHasDriverVersionMismatch = false; michael@0: if (mAdapterVendorID == GfxDriverInfo::GetDeviceVendor(VendorIntel)) { michael@0: // we've had big crashers (bugs 590373 and 595364) apparently correlated michael@0: // with bad Intel driver installations where the DriverVersion reported michael@0: // by the registry was not the version of the DLL. michael@0: bool is64bitApp = sizeof(void*) == 8; michael@0: const char16_t *dllFileName = is64bitApp michael@0: ? MOZ_UTF16("igd10umd64.dll") michael@0: : MOZ_UTF16("igd10umd32.dll"), michael@0: *dllFileName2 = is64bitApp michael@0: ? MOZ_UTF16("igd10iumd64.dll") michael@0: : MOZ_UTF16("igd10iumd32.dll"); michael@0: nsString dllVersion, dllVersion2; michael@0: gfxWindowsPlatform::GetDLLVersion((char16_t*)dllFileName, dllVersion); michael@0: gfxWindowsPlatform::GetDLLVersion((char16_t*)dllFileName2, dllVersion2); michael@0: michael@0: uint64_t dllNumericVersion = 0, dllNumericVersion2 = 0, michael@0: driverNumericVersion = 0, knownSafeMismatchVersion = 0; michael@0: ParseDriverVersion(dllVersion, &dllNumericVersion); michael@0: ParseDriverVersion(dllVersion2, &dllNumericVersion2); michael@0: ParseDriverVersion(mDriverVersion, &driverNumericVersion); michael@0: ParseDriverVersion(NS_LITERAL_STRING("9.17.10.0"), &knownSafeMismatchVersion); michael@0: michael@0: // If there's a driver version mismatch, consider this harmful only when michael@0: // the driver version is less than knownSafeMismatchVersion. See the michael@0: // above comment about crashes with old mismatches. If the GetDllVersion michael@0: // call fails, then they return 0, so that will be considered a mismatch. michael@0: if (dllNumericVersion != driverNumericVersion && michael@0: dllNumericVersion2 != driverNumericVersion && michael@0: (driverNumericVersion < knownSafeMismatchVersion || michael@0: std::max(dllNumericVersion, dllNumericVersion2) < knownSafeMismatchVersion)) { michael@0: mHasDriverVersionMismatch = true; michael@0: } michael@0: } michael@0: michael@0: const char *spoofedDriverVersionString = PR_GetEnv("MOZ_GFX_SPOOF_DRIVER_VERSION"); michael@0: if (spoofedDriverVersionString) { michael@0: mDriverVersion.AssignASCII(spoofedDriverVersionString); michael@0: } michael@0: michael@0: const char *spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_VENDOR_ID"); michael@0: if (spoofedVendor) { michael@0: mAdapterVendorID.AssignASCII(spoofedVendor); michael@0: } michael@0: michael@0: const char *spoofedDevice = PR_GetEnv("MOZ_GFX_SPOOF_DEVICE_ID"); michael@0: if (spoofedDevice) { michael@0: mAdapterDeviceID.AssignASCII(spoofedDevice); michael@0: } michael@0: michael@0: AddCrashReportAnnotations(); michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: /* readonly attribute DOMString adapterDescription; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription) michael@0: { michael@0: aAdapterDescription = mDeviceString; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute DOMString adapterDescription2; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetAdapterDescription2(nsAString & aAdapterDescription) michael@0: { michael@0: aAdapterDescription = mDeviceString2; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute DOMString adapterRAM; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetAdapterRAM(nsAString & aAdapterRAM) michael@0: { michael@0: if (NS_FAILED(GetKeyValue(mDeviceKey.get(), L"HardwareInformation.MemorySize", aAdapterRAM, REG_DWORD))) michael@0: aAdapterRAM = L"Unknown"; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute DOMString adapterRAM2; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetAdapterRAM2(nsAString & aAdapterRAM) michael@0: { michael@0: if (!mHasDualGPU) { michael@0: aAdapterRAM.AssignLiteral(""); michael@0: } else if (NS_FAILED(GetKeyValue(mDeviceKey2.get(), L"HardwareInformation.MemorySize", aAdapterRAM, REG_DWORD))) { michael@0: aAdapterRAM = L"Unknown"; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute DOMString adapterDriver; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetAdapterDriver(nsAString & aAdapterDriver) michael@0: { michael@0: if (NS_FAILED(GetKeyValue(mDeviceKey.get(), L"InstalledDisplayDrivers", aAdapterDriver, REG_MULTI_SZ))) michael@0: aAdapterDriver = L"Unknown"; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute DOMString adapterDriver2; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetAdapterDriver2(nsAString & aAdapterDriver) michael@0: { michael@0: if (!mHasDualGPU) { michael@0: aAdapterDriver.AssignLiteral(""); michael@0: } else if (NS_FAILED(GetKeyValue(mDeviceKey2.get(), L"InstalledDisplayDrivers", aAdapterDriver, REG_MULTI_SZ))) { michael@0: aAdapterDriver = L"Unknown"; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute DOMString adapterDriverVersion; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetAdapterDriverVersion(nsAString & aAdapterDriverVersion) michael@0: { michael@0: aAdapterDriverVersion = mDriverVersion; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute DOMString adapterDriverDate; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetAdapterDriverDate(nsAString & aAdapterDriverDate) michael@0: { michael@0: aAdapterDriverDate = mDriverDate; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute DOMString adapterDriverVersion2; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion) michael@0: { michael@0: aAdapterDriverVersion = mDriverVersion2; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute DOMString adapterDriverDate2; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetAdapterDriverDate2(nsAString & aAdapterDriverDate) michael@0: { michael@0: aAdapterDriverDate = mDriverDate2; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute DOMString adapterVendorID; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetAdapterVendorID(nsAString & aAdapterVendorID) michael@0: { michael@0: aAdapterVendorID = mAdapterVendorID; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute DOMString adapterVendorID2; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetAdapterVendorID2(nsAString & aAdapterVendorID) michael@0: { michael@0: aAdapterVendorID = mAdapterVendorID2; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute DOMString adapterDeviceID; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetAdapterDeviceID(nsAString & aAdapterDeviceID) michael@0: { michael@0: aAdapterDeviceID = mAdapterDeviceID; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute DOMString adapterDeviceID2; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetAdapterDeviceID2(nsAString & aAdapterDeviceID) michael@0: { michael@0: aAdapterDeviceID = mAdapterDeviceID2; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* readonly attribute boolean isGPU2Active; */ michael@0: NS_IMETHODIMP michael@0: GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active) michael@0: { michael@0: *aIsGPU2Active = mIsGPU2Active; michael@0: return NS_OK; michael@0: } michael@0: michael@0: #if defined(MOZ_CRASHREPORTER) michael@0: /* Cisco's VPN software can cause corruption of the floating point state. michael@0: * Make a note of this in our crash reports so that some weird crashes michael@0: * make more sense */ michael@0: static void michael@0: CheckForCiscoVPN() { michael@0: LONG result; michael@0: HKEY key; michael@0: /* This will give false positives, but hopefully no false negatives */ michael@0: result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Cisco Systems\\VPN Client", 0, KEY_QUERY_VALUE, &key); michael@0: if (result == ERROR_SUCCESS) { michael@0: RegCloseKey(key); michael@0: CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("Cisco VPN\n")); michael@0: } michael@0: } michael@0: #endif michael@0: michael@0: void michael@0: GfxInfo::AddCrashReportAnnotations() michael@0: { michael@0: #if defined(MOZ_CRASHREPORTER) michael@0: CheckForCiscoVPN(); michael@0: michael@0: nsString deviceID, vendorID; michael@0: nsCString narrowDeviceID, narrowVendorID; michael@0: nsAutoString adapterDriverVersionString; michael@0: michael@0: GetAdapterDeviceID(deviceID); michael@0: CopyUTF16toUTF8(deviceID, narrowDeviceID); michael@0: GetAdapterVendorID(vendorID); michael@0: CopyUTF16toUTF8(vendorID, narrowVendorID); michael@0: GetAdapterDriverVersion(adapterDriverVersionString); michael@0: michael@0: CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterVendorID"), michael@0: narrowVendorID); michael@0: CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AdapterDeviceID"), michael@0: narrowDeviceID); michael@0: michael@0: /* Add an App Note for now so that we get the data immediately. These michael@0: * can go away after we store the above in the socorro db */ michael@0: nsAutoCString note; michael@0: /* AppendPrintf only supports 32 character strings, mrghh. */ michael@0: note.Append("AdapterVendorID: "); michael@0: note.Append(narrowVendorID); michael@0: note.Append(", AdapterDeviceID: "); michael@0: note.Append(narrowDeviceID); michael@0: note.AppendPrintf(", AdapterSubsysID: %08x, ", mAdapterSubsysID); michael@0: note.Append("AdapterDriverVersion: "); michael@0: note.Append(NS_LossyConvertUTF16toASCII(adapterDriverVersionString)); michael@0: michael@0: if (vendorID == GfxDriverInfo::GetDeviceVendor(VendorAll)) { michael@0: /* if we didn't find a valid vendorID lets append the mDeviceID string to try to find out why */ michael@0: note.Append(", "); michael@0: LossyAppendUTF16toASCII(mDeviceID, note); michael@0: note.Append(", "); michael@0: LossyAppendUTF16toASCII(mDeviceKeyDebug, note); michael@0: LossyAppendUTF16toASCII(mDeviceKeyDebug, note); michael@0: } michael@0: note.Append("\n"); michael@0: michael@0: if (mHasDualGPU) { michael@0: nsString deviceID2, vendorID2; michael@0: nsAutoString adapterDriverVersionString2; michael@0: nsCString narrowDeviceID2, narrowVendorID2; michael@0: michael@0: note.AppendLiteral("Has dual GPUs. GPU #2: "); michael@0: GetAdapterDeviceID2(deviceID2); michael@0: CopyUTF16toUTF8(deviceID2, narrowDeviceID2); michael@0: GetAdapterVendorID2(vendorID2); michael@0: CopyUTF16toUTF8(vendorID2, narrowVendorID2); michael@0: GetAdapterDriverVersion2(adapterDriverVersionString2); michael@0: note.Append("AdapterVendorID2: "); michael@0: note.Append(narrowVendorID2); michael@0: note.Append(", AdapterDeviceID2: "); michael@0: note.Append(narrowDeviceID2); michael@0: note.AppendPrintf(", AdapterSubsysID2: %08x, ", mAdapterSubsysID2); michael@0: note.AppendPrintf("AdapterDriverVersion2: "); michael@0: note.Append(NS_LossyConvertUTF16toASCII(adapterDriverVersionString2)); michael@0: } michael@0: CrashReporter::AppendAppNotesToCrashReport(note); michael@0: michael@0: #endif michael@0: } michael@0: michael@0: static OperatingSystem michael@0: WindowsVersionToOperatingSystem(int32_t aWindowsVersion) michael@0: { michael@0: switch(aWindowsVersion) { michael@0: case kWindowsXP: michael@0: return DRIVER_OS_WINDOWS_XP; michael@0: case kWindowsServer2003: michael@0: return DRIVER_OS_WINDOWS_SERVER_2003; michael@0: case kWindowsVista: michael@0: return DRIVER_OS_WINDOWS_VISTA; michael@0: case kWindows7: michael@0: return DRIVER_OS_WINDOWS_7; michael@0: case kWindows8: michael@0: return DRIVER_OS_WINDOWS_8; michael@0: case kWindows8_1: michael@0: return DRIVER_OS_WINDOWS_8_1; michael@0: case kWindowsUnknown: michael@0: default: michael@0: return DRIVER_OS_UNKNOWN; michael@0: }; michael@0: } michael@0: michael@0: const nsTArray& michael@0: GfxInfo::GetGfxDriverInfo() michael@0: { michael@0: if (!mDriverInfo->Length()) { michael@0: /* michael@0: * It should be noted here that more specialized rules on certain features michael@0: * should be inserted -before- more generalized restriction. As the first michael@0: * match for feature/OS/device found in the list will be used for the final michael@0: * blacklisting call. michael@0: */ michael@0: michael@0: /* michael@0: * NVIDIA entries michael@0: */ michael@0: APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_VISTA, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices, michael@0: nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, michael@0: DRIVER_LESS_THAN, V(8,17,12,5721), "257.21" ); michael@0: APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_7, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices, michael@0: nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, michael@0: DRIVER_LESS_THAN, V(8,17,12,5721), "257.21" ); michael@0: APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_XP, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices, michael@0: GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, michael@0: DRIVER_LESS_THAN, V(6,14,11,8265), "182.65" ); michael@0: APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_VISTA, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices, michael@0: GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, michael@0: DRIVER_LESS_THAN, V(8,17,11,8265), "182.65" ); michael@0: APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_WINDOWS_7, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices, michael@0: GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, michael@0: DRIVER_LESS_THAN, V(8,17,11,8265), "182.65" ); michael@0: michael@0: /* michael@0: * AMD/ATI entries michael@0: */ michael@0: APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices, michael@0: nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, michael@0: DRIVER_LESS_THAN, V(8,741,0,0), "10.6" ); michael@0: APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices, michael@0: nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, michael@0: DRIVER_LESS_THAN, V(8,741,0,0), "10.6" ); michael@0: APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices, michael@0: GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, michael@0: DRIVER_LESS_THAN, V(8,62,0,0), "9.6" ); michael@0: APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices, michael@0: GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, michael@0: DRIVER_LESS_THAN, V(8,62,0,0), "9.6" ); michael@0: michael@0: /* michael@0: * Bug 783517 - crashes in AMD driver on Windows 8 michael@0: */ michael@0: APPEND_TO_DRIVER_BLOCKLIST_RANGE( DRIVER_OS_WINDOWS_8, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices, michael@0: GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, michael@0: DRIVER_BETWEEN_INCLUSIVE_START, V(8,982,0,0), V(8,983,0,0), "!= 8.982.*.*" ); michael@0: APPEND_TO_DRIVER_BLOCKLIST_RANGE( DRIVER_OS_WINDOWS_8, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices, michael@0: GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, michael@0: DRIVER_BETWEEN_INCLUSIVE_START, V(8,982,0,0), V(8,983,0,0), "!= 8.982.*.*" ); michael@0: michael@0: /* OpenGL on any ATI/AMD hardware is discouraged michael@0: * See: michael@0: * bug 619773 - WebGL: Crash with blue screen : "NMI: Parity Check / Memory Parity Error" michael@0: * bugs 584403, 584404, 620924 - crashes in atioglxx michael@0: * + many complaints about incorrect rendering michael@0: */ michael@0: APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices, michael@0: nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED, michael@0: DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ); michael@0: APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices, michael@0: nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED, michael@0: DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ); michael@0: APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices, michael@0: nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED, michael@0: DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ); michael@0: APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorAMD), GfxDriverInfo::allDevices, michael@0: nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED, michael@0: DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ); michael@0: michael@0: /* michael@0: * Intel entries michael@0: */ michael@0: michael@0: /* implement the blocklist from bug 594877 michael@0: * Block all features on any drivers before this, as there's a crash when a MS Hotfix is installed. michael@0: * The crash itself is Direct2D-related, but for safety we block all features. michael@0: */ michael@0: #define IMPLEMENT_INTEL_DRIVER_BLOCKLIST(winVer, devFamily, driverVer) \ michael@0: APPEND_TO_DRIVER_BLOCKLIST2( winVer, \ michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(devFamily), \ michael@0: GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, \ michael@0: DRIVER_LESS_THAN, driverVer ) michael@0: #define IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(winVer, devFamily, driverVer) \ michael@0: APPEND_TO_DRIVER_BLOCKLIST2( winVer, \ michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(devFamily), \ michael@0: nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, \ michael@0: DRIVER_LESS_THAN, driverVer ) michael@0: michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMA500, V(7,14,10,1006)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMA900, GfxDriverInfo::allDriverVersions); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMA950, V(7,14,10,1504)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMA3150, V(7,14,10,2124)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMAX3000, V(7,15,10,1666)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_VISTA, IntelGMAX4500HD, V(8,15,10,2202)); michael@0: michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMA500, V(5,0,0,2026)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMA900, GfxDriverInfo::allDriverVersions); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMA950, V(8,15,10,1930)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMA3150, V(8,14,10,2117)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMAX3000, V(8,15,10,1930)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(DRIVER_OS_WINDOWS_7, IntelGMAX4500HD, V(8,15,10,2202)); michael@0: michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMA500, V(3,0,20,3200)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMA900, V(6,14,10,4764)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMA950, V(6,14,10,4926)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMA3150, V(6,14,10,5134)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMAX3000, V(6,14,10,5218)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_XP, IntelGMAX4500HD, V(6,14,10,4969)); michael@0: michael@0: // StrechRect seems to suffer from precision issues which leads to artifacting michael@0: // during content drawing starting with at least version 6.14.10.5082 michael@0: // and going until 6.14.10.5218. See bug 919454 and bug 949275 for more info. michael@0: APPEND_TO_DRIVER_BLOCKLIST_RANGE(DRIVER_OS_WINDOWS_XP, michael@0: const_cast(GfxDriverInfo::GetDeviceVendor(VendorIntel)), michael@0: const_cast(GfxDriverInfo::GetDeviceFamily(IntelGMAX4500HD)), michael@0: GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, michael@0: DRIVER_BETWEEN_EXCLUSIVE, V(6,14,10,5076), V(6,14,10,5218), "6.14.10.5218"); michael@0: michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA500, V(3,0,20,3200)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA900, GfxDriverInfo::allDriverVersions); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA950, V(7,14,10,1504)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMA3150, V(7,14,10,1910)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMAX3000, V(7,15,10,1666)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_VISTA, IntelGMAX4500HD, V(7,15,10,1666)); michael@0: michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA500, V(5,0,0,2026)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA900, GfxDriverInfo::allDriverVersions); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA950, V(8,15,10,1930)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA3150, V(8,14,10,1972)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMAX3000, V(7,15,10,1666)); michael@0: IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMAX4500HD, V(7,15,10,1666)); michael@0: michael@0: /* OpenGL on any Intel hardware is discouraged */ michael@0: APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), GfxDriverInfo::allDevices, michael@0: nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED, michael@0: DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ); michael@0: APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), GfxDriverInfo::allDevices, michael@0: nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED, michael@0: DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ); michael@0: michael@0: /* Disable D2D on Win7 on Intel HD Graphics on driver <= 8.15.10.2302 michael@0: * See bug 806786 michael@0: */ michael@0: APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_WINDOWS_7, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(IntelMobileHDGraphics), michael@0: nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, michael@0: DRIVER_LESS_THAN_OR_EQUAL, V(8,15,10,2302) ); michael@0: michael@0: /* Disable D2D on Win8 on Intel HD Graphics on driver <= 8.15.10.2302 michael@0: * See bug 804144 and 863683 michael@0: */ michael@0: APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_WINDOWS_8, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(IntelMobileHDGraphics), michael@0: nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, michael@0: DRIVER_LESS_THAN_OR_EQUAL, V(8,15,10,2302) ); michael@0: michael@0: /* Disable D3D9 layers on NVIDIA 6100/6150/6200 series due to glitches michael@0: * whilst scrolling. See bugs: 612007, 644787 & 645872. michael@0: */ michael@0: APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(NvidiaBlockD3D9Layers), michael@0: nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, nsIGfxInfo::FEATURE_BLOCKED_DEVICE, michael@0: DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions ); michael@0: michael@0: /* Microsoft RemoteFX; blocked less than 6.2.0.0 */ michael@0: APPEND_TO_DRIVER_BLOCKLIST( DRIVER_OS_ALL, michael@0: (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorMicrosoft), GfxDriverInfo::allDevices, michael@0: GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, michael@0: DRIVER_LESS_THAN, V(6,2,0,0), "< 6.2.0.0" ); michael@0: } michael@0: return *mDriverInfo; michael@0: } michael@0: michael@0: nsresult michael@0: GfxInfo::GetFeatureStatusImpl(int32_t aFeature, michael@0: int32_t *aStatus, michael@0: nsAString & aSuggestedDriverVersion, michael@0: const nsTArray& aDriverInfo, michael@0: OperatingSystem* aOS /* = nullptr */) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aStatus); michael@0: aSuggestedDriverVersion.SetIsVoid(true); michael@0: OperatingSystem os = WindowsVersionToOperatingSystem(mWindowsVersion); michael@0: *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN; michael@0: if (aOS) michael@0: *aOS = os; michael@0: michael@0: // Don't evaluate special cases if we're checking the downloaded blocklist. michael@0: if (!aDriverInfo.Length()) { michael@0: nsAutoString adapterVendorID; michael@0: nsAutoString adapterDeviceID; michael@0: nsAutoString adapterDriverVersionString; michael@0: if (NS_FAILED(GetAdapterVendorID(adapterVendorID)) || michael@0: NS_FAILED(GetAdapterDeviceID(adapterDeviceID)) || michael@0: NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString))) michael@0: { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: if (!adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorIntel), nsCaseInsensitiveStringComparator()) && michael@0: !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), nsCaseInsensitiveStringComparator()) && michael@0: !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorAMD), nsCaseInsensitiveStringComparator()) && michael@0: !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorATI), nsCaseInsensitiveStringComparator()) && michael@0: !adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorMicrosoft), nsCaseInsensitiveStringComparator()) && michael@0: // FIXME - these special hex values are currently used in xpcshell tests introduced by michael@0: // bug 625160 patch 8/8. Maybe these tests need to be adjusted now that we're only whitelisting michael@0: // intel/ati/nvidia. michael@0: !adapterVendorID.LowerCaseEqualsLiteral("0xabcd") && michael@0: !adapterVendorID.LowerCaseEqualsLiteral("0xdcba") && michael@0: !adapterVendorID.LowerCaseEqualsLiteral("0xabab") && michael@0: !adapterVendorID.LowerCaseEqualsLiteral("0xdcdc")) michael@0: { michael@0: *aStatus = FEATURE_BLOCKED_DEVICE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: uint64_t driverVersion; michael@0: if (!ParseDriverVersion(adapterDriverVersionString, &driverVersion)) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: // special-case the WinXP test slaves: they have out-of-date drivers, but we still want to michael@0: // whitelist them, actually we do know that this combination of device and driver version michael@0: // works well. michael@0: if (mWindowsVersion == kWindowsXP && michael@0: adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), nsCaseInsensitiveStringComparator()) && michael@0: adapterDeviceID.LowerCaseEqualsLiteral("0x0861") && // GeForce 9400 michael@0: driverVersion == V(6,14,11,7756)) michael@0: { michael@0: *aStatus = FEATURE_NO_INFO; michael@0: return NS_OK; michael@0: } michael@0: michael@0: // Windows Server 2003 should be just like Windows XP for present purpose, but still has a different version number. michael@0: // OTOH Windows Server 2008 R1 and R2 already have the same version numbers as Vista and Seven respectively michael@0: if (os == DRIVER_OS_WINDOWS_SERVER_2003) michael@0: os = DRIVER_OS_WINDOWS_XP; michael@0: michael@0: if (mHasDriverVersionMismatch) { michael@0: if (aFeature == nsIGfxInfo::FEATURE_DIRECT3D_10_LAYERS || michael@0: aFeature == nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS || michael@0: aFeature == nsIGfxInfo::FEATURE_DIRECT2D) michael@0: { michael@0: *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION; michael@0: return NS_OK; michael@0: } michael@0: } michael@0: } michael@0: michael@0: return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, &os); michael@0: } michael@0: michael@0: #ifdef DEBUG michael@0: michael@0: // Implement nsIGfxInfoDebug michael@0: michael@0: /* void spoofVendorID (in DOMString aVendorID); */ michael@0: NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID) michael@0: { michael@0: mAdapterVendorID = aVendorID; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void spoofDeviceID (in unsigned long aDeviceID); */ michael@0: NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID) michael@0: { michael@0: mAdapterDeviceID = aDeviceID; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void spoofDriverVersion (in DOMString aDriverVersion); */ michael@0: NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion) michael@0: { michael@0: mDriverVersion = aDriverVersion; michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void spoofOSVersion (in unsigned long aVersion); */ michael@0: NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion) michael@0: { michael@0: mWindowsVersion = aVersion; michael@0: return NS_OK; michael@0: } michael@0: michael@0: #endif