Chromium Code Reviews| 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; |
|
brucedawson
2015/02/09 18:25:41
This variable declaration of device_id shadows the
|
| + 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; |