Index: gpu/config/gpu_info_collector_win.cc |
diff --git a/gpu/config/gpu_info_collector_win.cc b/gpu/config/gpu_info_collector_win.cc |
index 04f66fad6afc76fbf5f0e4e54082b4cb8ad7635f..a5686a9de6ad8b2a53087aef5ed719fc7b86c50a 100644 |
--- a/gpu/config/gpu_info_collector_win.cc |
+++ b/gpu/config/gpu_info_collector_win.cc |
@@ -8,6 +8,7 @@ |
#include "third_party/re2/re2/re2.h" |
#include <windows.h> |
+#include <cfgmgr32.h> |
#include <d3d9.h> |
#include <d3d11.h> |
#include <dxgi.h> |
@@ -363,6 +364,24 @@ void CollectD3D11Support() { |
base::Bind(CollectD3D11SupportOnWorkerThread), |
false); |
} |
+ |
+void DeviceIDToVendorAndDevice(const std::wstring& id, |
+ uint32* vendor_id, |
+ uint32* device_id) { |
+ *vendor_id = 0; |
+ *device_id = 0; |
+ if (id.length() < 21) |
+ return; |
+ base::string16 vendor_id_string = id.substr(8, 4); |
+ base::string16 device_id_string = id.substr(17, 4); |
+ int vendor = 0; |
+ int device = 0; |
+ base::HexStringToInt(base::UTF16ToASCII(vendor_id_string), &vendor); |
+ base::HexStringToInt(base::UTF16ToASCII(device_id_string), &device); |
+ *vendor_id = vendor; |
+ *device_id = device; |
+} |
+ |
} // namespace anonymous |
#if defined(GOOGLE_CHROME_BUILD) && defined(OFFICIAL_BUILD) |
@@ -380,17 +399,35 @@ CollectInfoResult CollectDriverInfoD3D(const std::wstring& device_id, |
GPUInfo* gpu_info) { |
TRACE_EVENT0("gpu", "CollectDriverInfoD3D"); |
+ // Display adapter class GUID from |
+ // https://msdn.microsoft.com/en-us/library/windows/hardware/ff553426%28v=vs.85%29.aspx |
+ GUID display_class = {0x4d36e968, |
+ 0xe325, |
+ 0x11ce, |
+ {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}}; |
+ |
// create device info for the display device |
- HDEVINFO device_info = SetupDiGetClassDevsW( |
- NULL, device_id.c_str(), NULL, |
- DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES); |
+ HDEVINFO device_info = |
+ SetupDiGetClassDevsW(&display_class, NULL, NULL, DIGCF_PRESENT); |
if (device_info == INVALID_HANDLE_VALUE) { |
LOG(ERROR) << "Creating device info failed"; |
return kCollectInfoNonFatalFailure; |
} |
+ struct GPUDriver { |
+ GPUInfo::GPUDevice device; |
+ std::string driver_vendor; |
+ std::string driver_version; |
+ std::string driver_date; |
+ }; |
+ |
+ std::vector<GPUDriver> drivers; |
+ |
+ int primary_device = -1; |
+ bool found_amd = false; |
+ bool found_intel = false; |
+ |
DWORD index = 0; |
- bool found = false; |
SP_DEVINFO_DATA device_info_data; |
device_info_data.cbSize = sizeof(device_info_data); |
while (SetupDiEnumDeviceInfo(device_info, index++, &device_info_data)) { |
@@ -429,35 +466,85 @@ CollectInfoResult CollectDriverInfoD3D(const std::wstring& device_id, |
result = RegQueryValueExW( |
key, L"ProviderName", NULL, NULL, |
reinterpret_cast<LPBYTE>(value), &dwcb_data); |
- if (result == ERROR_SUCCESS) { |
+ if (result == ERROR_SUCCESS) |
driver_vendor = base::UTF16ToASCII(std::wstring(value)); |
- if (driver_vendor == "Advanced Micro Devices, Inc." || |
- driver_vendor == "ATI Technologies Inc.") { |
- // We are conservative and assume that in the absence of a clear |
- // signal the videocard is assumed to be switchable. Additionally, |
- // some switchable systems with Intel GPUs aren't correctly |
- // detected, so always count them. |
- GetAMDVideocardInfo(gpu_info); |
- if (!gpu_info->amd_switchable && |
- gpu_info->gpu.vendor_id == 0x8086) { |
- gpu_info->amd_switchable = true; |
- gpu_info->secondary_gpus.push_back(gpu_info->gpu); |
- gpu_info->gpu.vendor_id = 0x1002; |
- gpu_info->gpu.device_id = 0; // Unknown discrete AMD GPU. |
- } |
- } |
+ |
+ wchar_t new_device_id[MAX_DEVICE_ID_LEN]; |
+ CONFIGRET status = CM_Get_Device_ID( |
+ device_info_data.DevInst, new_device_id, MAX_DEVICE_ID_LEN, 0); |
+ |
+ if (status == CR_SUCCESS) { |
+ GPUDriver driver; |
+ |
+ driver.driver_vendor = driver_vendor; |
+ driver.driver_version = driver_version; |
+ driver.driver_date = driver_date; |
+ std::wstring id = new_device_id; |
+ |
+ if (id.compare(0, device_id.size(), device_id) == 0) |
+ primary_device = drivers.size(); |
+ |
+ uint32 vendor_id = 0, device_id = 0; |
+ DeviceIDToVendorAndDevice(id, &vendor_id, &device_id); |
+ driver.device.vendor_id = vendor_id; |
+ driver.device.device_id = device_id; |
+ drivers.push_back(driver); |
+ |
+ if (vendor_id == 0x8086) |
+ found_intel = true; |
+ if (vendor_id == 0x1002) |
+ found_amd = true; |
} |
- gpu_info->driver_vendor = driver_vendor; |
- gpu_info->driver_version = driver_version; |
- gpu_info->driver_date = driver_date; |
- found = true; |
RegCloseKey(key); |
- break; |
} |
} |
} |
SetupDiDestroyDeviceInfoList(device_info); |
+ bool found = false; |
+ if (found_amd && found_intel) { |
+ // AMD Switchable system found. |
+ for (const auto& driver : drivers) { |
+ if (driver.device.vendor_id == 0x8086) { |
+ gpu_info->gpu = driver.device; |
+ } |
+ |
+ if (driver.device.vendor_id == 0x1002) { |
+ gpu_info->driver_vendor = driver.driver_vendor; |
+ gpu_info->driver_version = driver.driver_version; |
+ gpu_info->driver_date = driver.driver_date; |
+ } |
+ } |
+ GetAMDVideocardInfo(gpu_info); |
+ |
+ if (!gpu_info->amd_switchable) { |
+ // Some machines aren't properly detected as AMD switchable, but count |
+ // them anyway. |
+ gpu_info->amd_switchable = true; |
+ for (const auto& driver : drivers) { |
+ if (driver.device.vendor_id == 0x1002) { |
+ gpu_info->gpu = driver.device; |
+ } else { |
+ gpu_info->secondary_gpus.push_back(driver.device); |
+ } |
+ } |
+ } |
+ found = true; |
+ } else { |
+ for (size_t i = 0; i < drivers.size(); ++i) { |
+ const GPUDriver& driver = drivers[i]; |
+ if (static_cast<int>(i) == primary_device) { |
+ found = true; |
+ gpu_info->gpu = driver.device; |
+ gpu_info->driver_vendor = driver.driver_vendor; |
+ gpu_info->driver_version = driver.driver_version; |
+ gpu_info->driver_date = driver.driver_date; |
+ } else { |
+ gpu_info->secondary_gpus.push_back(driver.device); |
+ } |
+ } |
+ } |
+ |
return found ? kCollectInfoSuccess : kCollectInfoNonFatalFailure; |
} |
@@ -551,13 +638,7 @@ CollectInfoResult CollectGpuID(uint32* vendor_id, uint32* device_id) { |
} |
if (id.length() > 20) { |
- int vendor = 0, device = 0; |
- std::wstring vendor_string = id.substr(8, 4); |
- std::wstring device_string = id.substr(17, 4); |
- base::HexStringToInt(base::UTF16ToASCII(vendor_string), &vendor); |
- base::HexStringToInt(base::UTF16ToASCII(device_string), &device); |
- *vendor_id = vendor; |
- *device_id = device; |
+ DeviceIDToVendorAndDevice(id, vendor_id, device_id); |
if (*vendor_id != 0 && *device_id != 0) |
return kCollectInfoSuccess; |
} |
@@ -609,13 +690,8 @@ CollectInfoResult CollectBasicGraphicsInfo(GPUInfo* gpu_info) { |
return kCollectInfoNonFatalFailure; |
} |
- int vendor_id = 0, device_id = 0; |
- base::string16 vendor_id_string = id.substr(8, 4); |
- base::string16 device_id_string = id.substr(17, 4); |
- base::HexStringToInt(base::UTF16ToASCII(vendor_id_string), &vendor_id); |
- base::HexStringToInt(base::UTF16ToASCII(device_id_string), &device_id); |
- gpu_info->gpu.vendor_id = vendor_id; |
- gpu_info->gpu.device_id = device_id; |
+ DeviceIDToVendorAndDevice(id, &gpu_info->gpu.vendor_id, |
+ &gpu_info->gpu.device_id); |
// TODO(zmo): we only need to call CollectDriverInfoD3D() if we use ANGLE. |
if (!CollectDriverInfoD3D(id, gpu_info)) { |
gpu_info->basic_info_state = kCollectInfoNonFatalFailure; |