James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "gpu/config/gpu_info_collector.h" |
| 6 | |
| 7 | // This has to be included before windows.h. |
| 8 | #include "third_party/re2/re2/re2.h" |
| 9 | |
| 10 | #include <windows.h> |
James Robinson | 7b766f4 | 2015-02-06 15:14:04 -0800 | [diff] [blame] | 11 | #include <cfgmgr32.h> |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 12 | #include <d3d9.h> |
| 13 | #include <d3d11.h> |
| 14 | #include <dxgi.h> |
| 15 | #include <setupapi.h> |
| 16 | |
| 17 | #include "base/command_line.h" |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 18 | #include "base/files/file_enumerator.h" |
| 19 | #include "base/files/file_path.h" |
| 20 | #include "base/files/file_util.h" |
| 21 | #include "base/logging.h" |
| 22 | #include "base/message_loop/message_loop.h" |
| 23 | #include "base/metrics/field_trial.h" |
| 24 | #include "base/metrics/histogram.h" |
| 25 | #include "base/scoped_native_library.h" |
| 26 | #include "base/strings/string16.h" |
| 27 | #include "base/strings/string_number_conversions.h" |
| 28 | #include "base/strings/string_util.h" |
| 29 | #include "base/strings/stringprintf.h" |
| 30 | #include "base/strings/utf_string_conversions.h" |
| 31 | #include "base/threading/thread.h" |
| 32 | #include "base/threading/worker_pool.h" |
Benjamin Lerman | cdfc88d | 2015-02-03 14:35:12 +0100 | [diff] [blame] | 33 | #include "base/trace_event/trace_event.h" |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 34 | #include "base/win/registry.h" |
| 35 | #include "base/win/scoped_com_initializer.h" |
| 36 | #include "base/win/scoped_comptr.h" |
| 37 | #include "base/win/windows_version.h" |
| 38 | #include "third_party/libxml/chromium/libxml_utils.h" |
| 39 | #include "ui/gl/gl_implementation.h" |
| 40 | #include "ui/gl/gl_surface_egl.h" |
| 41 | |
| 42 | namespace gpu { |
| 43 | |
| 44 | namespace { |
| 45 | |
| 46 | // This must be kept in sync with histograms.xml. |
| 47 | enum DisplayLinkInstallationStatus { |
| 48 | DISPLAY_LINK_NOT_INSTALLED, |
| 49 | DISPLAY_LINK_7_1_OR_EARLIER, |
| 50 | DISPLAY_LINK_7_2_OR_LATER, |
| 51 | DISPLAY_LINK_INSTALLATION_STATUS_MAX |
| 52 | }; |
| 53 | |
| 54 | float ReadXMLFloatValue(XmlReader* reader) { |
| 55 | std::string score_string; |
| 56 | if (!reader->ReadElementContent(&score_string)) |
| 57 | return 0.0; |
| 58 | |
| 59 | double score; |
| 60 | if (!base::StringToDouble(score_string, &score)) |
| 61 | return 0.0; |
| 62 | |
| 63 | return static_cast<float>(score); |
| 64 | } |
| 65 | |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 66 | // Returns the display link driver version or an invalid version if it is |
| 67 | // not installed. |
| 68 | Version DisplayLinkVersion() { |
| 69 | base::win::RegKey key; |
| 70 | |
| 71 | if (key.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE", KEY_READ | KEY_WOW64_64KEY)) |
| 72 | return Version(); |
| 73 | |
| 74 | if (key.OpenKey(L"DisplayLink", KEY_READ | KEY_WOW64_64KEY)) |
| 75 | return Version(); |
| 76 | |
| 77 | if (key.OpenKey(L"Core", KEY_READ | KEY_WOW64_64KEY)) |
| 78 | return Version(); |
| 79 | |
| 80 | base::string16 version; |
| 81 | if (key.ReadValue(L"Version", &version)) |
| 82 | return Version(); |
| 83 | |
| 84 | return Version(base::UTF16ToASCII(version)); |
| 85 | } |
| 86 | |
| 87 | // Returns whether Lenovo dCute is installed. |
| 88 | bool IsLenovoDCuteInstalled() { |
| 89 | base::win::RegKey key; |
| 90 | |
| 91 | if (key.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE", KEY_READ | KEY_WOW64_64KEY)) |
| 92 | return false; |
| 93 | |
| 94 | if (key.OpenKey(L"Lenovo", KEY_READ | KEY_WOW64_64KEY)) |
| 95 | return false; |
| 96 | |
| 97 | if (key.OpenKey(L"Lenovo dCute", KEY_READ | KEY_WOW64_64KEY)) |
| 98 | return false; |
| 99 | |
| 100 | return true; |
| 101 | } |
| 102 | |
James Robinson | 7b766f4 | 2015-02-06 15:14:04 -0800 | [diff] [blame] | 103 | void DeviceIDToVendorAndDevice(const std::wstring& id, |
| 104 | uint32* vendor_id, |
| 105 | uint32* device_id) { |
| 106 | *vendor_id = 0; |
| 107 | *device_id = 0; |
| 108 | if (id.length() < 21) |
| 109 | return; |
| 110 | base::string16 vendor_id_string = id.substr(8, 4); |
| 111 | base::string16 device_id_string = id.substr(17, 4); |
| 112 | int vendor = 0; |
| 113 | int device = 0; |
| 114 | base::HexStringToInt(base::UTF16ToASCII(vendor_id_string), &vendor); |
| 115 | base::HexStringToInt(base::UTF16ToASCII(device_id_string), &device); |
| 116 | *vendor_id = vendor; |
| 117 | *device_id = device; |
| 118 | } |
| 119 | |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 120 | } // namespace anonymous |
| 121 | |
| 122 | #if defined(GOOGLE_CHROME_BUILD) && defined(OFFICIAL_BUILD) |
| 123 | // This function has a real implementation for official builds that can |
| 124 | // be found in src/third_party/amd. |
| 125 | void GetAMDVideocardInfo(GPUInfo* gpu_info); |
| 126 | #else |
| 127 | void GetAMDVideocardInfo(GPUInfo* gpu_info) { |
| 128 | DCHECK(gpu_info); |
| 129 | return; |
| 130 | } |
| 131 | #endif |
| 132 | |
| 133 | CollectInfoResult CollectDriverInfoD3D(const std::wstring& device_id, |
| 134 | GPUInfo* gpu_info) { |
| 135 | TRACE_EVENT0("gpu", "CollectDriverInfoD3D"); |
| 136 | |
James Robinson | 7b766f4 | 2015-02-06 15:14:04 -0800 | [diff] [blame] | 137 | // Display adapter class GUID from |
| 138 | // https://msdn.microsoft.com/en-us/library/windows/hardware/ff553426%28v=vs.85%29.aspx |
| 139 | GUID display_class = {0x4d36e968, |
| 140 | 0xe325, |
| 141 | 0x11ce, |
| 142 | {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}}; |
| 143 | |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 144 | // create device info for the display device |
Etienne Membrives | 386015a | 2015-02-19 17:27:12 +0100 | [diff] [blame] | 145 | HDEVINFO device_info; |
| 146 | if (base::win::GetVersion() <= base::win::VERSION_XP) { |
| 147 | // Collection of information on all adapters is much slower on XP (almost |
| 148 | // 100ms), and not very useful (as it's not going to use the GPU anyway), so |
| 149 | // just collect information on the current device. http://crbug.com/456178 |
| 150 | device_info = |
| 151 | SetupDiGetClassDevsW(NULL, device_id.c_str(), NULL, |
| 152 | DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES); |
| 153 | } else { |
| 154 | device_info = |
| 155 | SetupDiGetClassDevsW(&display_class, NULL, NULL, DIGCF_PRESENT); |
| 156 | } |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 157 | if (device_info == INVALID_HANDLE_VALUE) { |
| 158 | LOG(ERROR) << "Creating device info failed"; |
| 159 | return kCollectInfoNonFatalFailure; |
| 160 | } |
| 161 | |
James Robinson | 7b766f4 | 2015-02-06 15:14:04 -0800 | [diff] [blame] | 162 | struct GPUDriver { |
| 163 | GPUInfo::GPUDevice device; |
| 164 | std::string driver_vendor; |
| 165 | std::string driver_version; |
| 166 | std::string driver_date; |
| 167 | }; |
| 168 | |
| 169 | std::vector<GPUDriver> drivers; |
| 170 | |
| 171 | int primary_device = -1; |
| 172 | bool found_amd = false; |
| 173 | bool found_intel = false; |
| 174 | |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 175 | DWORD index = 0; |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 176 | SP_DEVINFO_DATA device_info_data; |
| 177 | device_info_data.cbSize = sizeof(device_info_data); |
| 178 | while (SetupDiEnumDeviceInfo(device_info, index++, &device_info_data)) { |
| 179 | WCHAR value[255]; |
| 180 | if (SetupDiGetDeviceRegistryPropertyW(device_info, |
| 181 | &device_info_data, |
| 182 | SPDRP_DRIVER, |
| 183 | NULL, |
| 184 | reinterpret_cast<PBYTE>(value), |
| 185 | sizeof(value), |
| 186 | NULL)) { |
| 187 | HKEY key; |
| 188 | std::wstring driver_key = L"System\\CurrentControlSet\\Control\\Class\\"; |
| 189 | driver_key += value; |
| 190 | LONG result = RegOpenKeyExW( |
| 191 | HKEY_LOCAL_MACHINE, driver_key.c_str(), 0, KEY_QUERY_VALUE, &key); |
| 192 | if (result == ERROR_SUCCESS) { |
| 193 | DWORD dwcb_data = sizeof(value); |
| 194 | std::string driver_version; |
| 195 | result = RegQueryValueExW( |
| 196 | key, L"DriverVersion", NULL, NULL, |
| 197 | reinterpret_cast<LPBYTE>(value), &dwcb_data); |
| 198 | if (result == ERROR_SUCCESS) |
| 199 | driver_version = base::UTF16ToASCII(std::wstring(value)); |
| 200 | |
| 201 | std::string driver_date; |
| 202 | dwcb_data = sizeof(value); |
| 203 | result = RegQueryValueExW( |
| 204 | key, L"DriverDate", NULL, NULL, |
| 205 | reinterpret_cast<LPBYTE>(value), &dwcb_data); |
| 206 | if (result == ERROR_SUCCESS) |
| 207 | driver_date = base::UTF16ToASCII(std::wstring(value)); |
| 208 | |
| 209 | std::string driver_vendor; |
| 210 | dwcb_data = sizeof(value); |
| 211 | result = RegQueryValueExW( |
| 212 | key, L"ProviderName", NULL, NULL, |
| 213 | reinterpret_cast<LPBYTE>(value), &dwcb_data); |
James Robinson | 7b766f4 | 2015-02-06 15:14:04 -0800 | [diff] [blame] | 214 | if (result == ERROR_SUCCESS) |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 215 | driver_vendor = base::UTF16ToASCII(std::wstring(value)); |
James Robinson | 7b766f4 | 2015-02-06 15:14:04 -0800 | [diff] [blame] | 216 | |
| 217 | wchar_t new_device_id[MAX_DEVICE_ID_LEN]; |
| 218 | CONFIGRET status = CM_Get_Device_ID( |
| 219 | device_info_data.DevInst, new_device_id, MAX_DEVICE_ID_LEN, 0); |
| 220 | |
| 221 | if (status == CR_SUCCESS) { |
| 222 | GPUDriver driver; |
| 223 | |
| 224 | driver.driver_vendor = driver_vendor; |
| 225 | driver.driver_version = driver_version; |
| 226 | driver.driver_date = driver_date; |
| 227 | std::wstring id = new_device_id; |
| 228 | |
| 229 | if (id.compare(0, device_id.size(), device_id) == 0) |
| 230 | primary_device = drivers.size(); |
| 231 | |
| 232 | uint32 vendor_id = 0, device_id = 0; |
| 233 | DeviceIDToVendorAndDevice(id, &vendor_id, &device_id); |
| 234 | driver.device.vendor_id = vendor_id; |
| 235 | driver.device.device_id = device_id; |
| 236 | drivers.push_back(driver); |
| 237 | |
| 238 | if (vendor_id == 0x8086) |
| 239 | found_intel = true; |
| 240 | if (vendor_id == 0x1002) |
| 241 | found_amd = true; |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 242 | } |
| 243 | |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 244 | RegCloseKey(key); |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 245 | } |
| 246 | } |
| 247 | } |
| 248 | SetupDiDestroyDeviceInfoList(device_info); |
James Robinson | 7b766f4 | 2015-02-06 15:14:04 -0800 | [diff] [blame] | 249 | bool found = false; |
| 250 | if (found_amd && found_intel) { |
| 251 | // AMD Switchable system found. |
| 252 | for (const auto& driver : drivers) { |
| 253 | if (driver.device.vendor_id == 0x8086) { |
| 254 | gpu_info->gpu = driver.device; |
| 255 | } |
| 256 | |
| 257 | if (driver.device.vendor_id == 0x1002) { |
| 258 | gpu_info->driver_vendor = driver.driver_vendor; |
| 259 | gpu_info->driver_version = driver.driver_version; |
| 260 | gpu_info->driver_date = driver.driver_date; |
| 261 | } |
| 262 | } |
| 263 | GetAMDVideocardInfo(gpu_info); |
| 264 | |
| 265 | if (!gpu_info->amd_switchable) { |
| 266 | // Some machines aren't properly detected as AMD switchable, but count |
| 267 | // them anyway. |
| 268 | gpu_info->amd_switchable = true; |
| 269 | for (const auto& driver : drivers) { |
| 270 | if (driver.device.vendor_id == 0x1002) { |
| 271 | gpu_info->gpu = driver.device; |
| 272 | } else { |
| 273 | gpu_info->secondary_gpus.push_back(driver.device); |
| 274 | } |
| 275 | } |
| 276 | } |
| 277 | found = true; |
| 278 | } else { |
| 279 | for (size_t i = 0; i < drivers.size(); ++i) { |
| 280 | const GPUDriver& driver = drivers[i]; |
| 281 | if (static_cast<int>(i) == primary_device) { |
| 282 | found = true; |
| 283 | gpu_info->gpu = driver.device; |
| 284 | gpu_info->driver_vendor = driver.driver_vendor; |
| 285 | gpu_info->driver_version = driver.driver_version; |
| 286 | gpu_info->driver_date = driver.driver_date; |
| 287 | } else { |
| 288 | gpu_info->secondary_gpus.push_back(driver.device); |
| 289 | } |
| 290 | } |
| 291 | } |
| 292 | |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 293 | return found ? kCollectInfoSuccess : kCollectInfoNonFatalFailure; |
| 294 | } |
| 295 | |
| 296 | CollectInfoResult CollectContextGraphicsInfo(GPUInfo* gpu_info) { |
| 297 | TRACE_EVENT0("gpu", "CollectGraphicsInfo"); |
| 298 | |
| 299 | DCHECK(gpu_info); |
| 300 | |
James Robinson | 9127e72 | 2014-12-29 14:41:55 -0800 | [diff] [blame] | 301 | if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) { |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 302 | std::string requested_implementation_name = |
James Robinson | 9127e72 | 2014-12-29 14:41:55 -0800 | [diff] [blame] | 303 | base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 304 | switches::kUseGL); |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 305 | if (requested_implementation_name == "swiftshader") { |
| 306 | gpu_info->software_rendering = true; |
| 307 | gpu_info->context_info_state = kCollectInfoNonFatalFailure; |
| 308 | return kCollectInfoNonFatalFailure; |
| 309 | } |
| 310 | } |
| 311 | |
| 312 | CollectInfoResult result = CollectGraphicsInfoGL(gpu_info); |
| 313 | if (result != kCollectInfoSuccess) { |
| 314 | gpu_info->context_info_state = result; |
| 315 | return result; |
| 316 | } |
| 317 | |
| 318 | // ANGLE's renderer strings are of the form: |
| 319 | // ANGLE (<adapter_identifier> Direct3D<version> vs_x_x ps_x_x) |
| 320 | std::string direct3d_version; |
| 321 | int vertex_shader_major_version = 0; |
| 322 | int vertex_shader_minor_version = 0; |
| 323 | int pixel_shader_major_version = 0; |
| 324 | int pixel_shader_minor_version = 0; |
| 325 | gpu_info->adapter_luid = 0; |
| 326 | if (RE2::FullMatch(gpu_info->gl_renderer, |
| 327 | "ANGLE \\(.*\\)") && |
| 328 | RE2::PartialMatch(gpu_info->gl_renderer, |
| 329 | " Direct3D(\\w+)", |
| 330 | &direct3d_version) && |
| 331 | RE2::PartialMatch(gpu_info->gl_renderer, |
| 332 | " vs_(\\d+)_(\\d+)", |
| 333 | &vertex_shader_major_version, |
| 334 | &vertex_shader_minor_version) && |
| 335 | RE2::PartialMatch(gpu_info->gl_renderer, |
| 336 | " ps_(\\d+)_(\\d+)", |
| 337 | &pixel_shader_major_version, |
| 338 | &pixel_shader_minor_version)) { |
| 339 | gpu_info->can_lose_context = direct3d_version == "9"; |
| 340 | gpu_info->vertex_shader_version = |
| 341 | base::StringPrintf("%d.%d", |
| 342 | vertex_shader_major_version, |
| 343 | vertex_shader_minor_version); |
| 344 | gpu_info->pixel_shader_version = |
| 345 | base::StringPrintf("%d.%d", |
| 346 | pixel_shader_major_version, |
| 347 | pixel_shader_minor_version); |
| 348 | |
| 349 | // ANGLE's EGL vendor strings are of the form: |
| 350 | // Google, Inc. (adapter LUID: 0123456789ABCDEF) |
| 351 | // The LUID is optional and identifies the GPU adapter ANGLE is using. |
| 352 | const char* egl_vendor = eglQueryString( |
| 353 | gfx::GLSurfaceEGL::GetHardwareDisplay(), |
| 354 | EGL_VENDOR); |
| 355 | RE2::PartialMatch(egl_vendor, |
| 356 | " \\(adapter LUID: ([0-9A-Fa-f]{16})\\)", |
| 357 | RE2::Hex(&gpu_info->adapter_luid)); |
| 358 | |
| 359 | // DirectX diagnostics are collected asynchronously because it takes a |
| 360 | // couple of seconds. |
| 361 | } else { |
| 362 | gpu_info->dx_diagnostics_info_state = kCollectInfoNonFatalFailure; |
| 363 | } |
| 364 | |
| 365 | gpu_info->context_info_state = kCollectInfoSuccess; |
| 366 | return kCollectInfoSuccess; |
| 367 | } |
| 368 | |
| 369 | CollectInfoResult CollectGpuID(uint32* vendor_id, uint32* device_id) { |
| 370 | DCHECK(vendor_id && device_id); |
| 371 | *vendor_id = 0; |
| 372 | *device_id = 0; |
| 373 | |
| 374 | // Taken from http://developer.nvidia.com/object/device_ids.html |
| 375 | DISPLAY_DEVICE dd; |
| 376 | dd.cb = sizeof(DISPLAY_DEVICE); |
| 377 | std::wstring id; |
| 378 | for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) { |
| 379 | if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { |
| 380 | id = dd.DeviceID; |
| 381 | break; |
| 382 | } |
| 383 | } |
| 384 | |
| 385 | if (id.length() > 20) { |
James Robinson | 7b766f4 | 2015-02-06 15:14:04 -0800 | [diff] [blame] | 386 | DeviceIDToVendorAndDevice(id, vendor_id, device_id); |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 387 | if (*vendor_id != 0 && *device_id != 0) |
| 388 | return kCollectInfoSuccess; |
| 389 | } |
| 390 | return kCollectInfoNonFatalFailure; |
| 391 | } |
| 392 | |
| 393 | CollectInfoResult CollectBasicGraphicsInfo(GPUInfo* gpu_info) { |
| 394 | TRACE_EVENT0("gpu", "CollectPreliminaryGraphicsInfo"); |
| 395 | |
| 396 | DCHECK(gpu_info); |
| 397 | |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 398 | // nvd3d9wrap.dll is loaded into all processes when Optimus is enabled. |
| 399 | HMODULE nvd3d9wrap = GetModuleHandleW(L"nvd3d9wrap.dll"); |
| 400 | gpu_info->optimus = nvd3d9wrap != NULL; |
| 401 | |
| 402 | gpu_info->lenovo_dcute = IsLenovoDCuteInstalled(); |
| 403 | |
| 404 | gpu_info->display_link_version = DisplayLinkVersion(); |
| 405 | |
| 406 | if (!gpu_info->display_link_version .IsValid()) { |
| 407 | UMA_HISTOGRAM_ENUMERATION("GPU.DisplayLinkInstallationStatus", |
| 408 | DISPLAY_LINK_NOT_INSTALLED, |
| 409 | DISPLAY_LINK_INSTALLATION_STATUS_MAX); |
| 410 | } else if (gpu_info->display_link_version.IsOlderThan("7.2")) { |
| 411 | UMA_HISTOGRAM_ENUMERATION("GPU.DisplayLinkInstallationStatus", |
| 412 | DISPLAY_LINK_7_1_OR_EARLIER, |
| 413 | DISPLAY_LINK_INSTALLATION_STATUS_MAX); |
| 414 | } else { |
| 415 | UMA_HISTOGRAM_ENUMERATION("GPU.DisplayLinkInstallationStatus", |
| 416 | DISPLAY_LINK_7_2_OR_LATER, |
| 417 | DISPLAY_LINK_INSTALLATION_STATUS_MAX); |
| 418 | } |
| 419 | |
| 420 | // Taken from http://developer.nvidia.com/object/device_ids.html |
| 421 | DISPLAY_DEVICE dd; |
| 422 | dd.cb = sizeof(DISPLAY_DEVICE); |
| 423 | std::wstring id; |
| 424 | for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) { |
| 425 | if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { |
| 426 | id = dd.DeviceID; |
| 427 | break; |
| 428 | } |
| 429 | } |
| 430 | |
| 431 | if (id.length() <= 20) { |
| 432 | gpu_info->basic_info_state = kCollectInfoNonFatalFailure; |
| 433 | return kCollectInfoNonFatalFailure; |
| 434 | } |
| 435 | |
James Robinson | 7b766f4 | 2015-02-06 15:14:04 -0800 | [diff] [blame] | 436 | DeviceIDToVendorAndDevice(id, &gpu_info->gpu.vendor_id, |
| 437 | &gpu_info->gpu.device_id); |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 438 | // TODO(zmo): we only need to call CollectDriverInfoD3D() if we use ANGLE. |
| 439 | if (!CollectDriverInfoD3D(id, gpu_info)) { |
| 440 | gpu_info->basic_info_state = kCollectInfoNonFatalFailure; |
| 441 | return kCollectInfoNonFatalFailure; |
| 442 | } |
| 443 | |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 444 | gpu_info->basic_info_state = kCollectInfoSuccess; |
| 445 | return kCollectInfoSuccess; |
| 446 | } |
| 447 | |
| 448 | CollectInfoResult CollectDriverInfoGL(GPUInfo* gpu_info) { |
| 449 | TRACE_EVENT0("gpu", "CollectDriverInfoGL"); |
| 450 | |
| 451 | if (!gpu_info->driver_version.empty()) |
| 452 | return kCollectInfoSuccess; |
| 453 | |
| 454 | bool parsed = RE2::PartialMatch( |
| 455 | gpu_info->gl_version, "([\\d\\.]+)$", &gpu_info->driver_version); |
| 456 | return parsed ? kCollectInfoSuccess : kCollectInfoNonFatalFailure; |
| 457 | } |
| 458 | |
| 459 | void MergeGPUInfo(GPUInfo* basic_gpu_info, |
| 460 | const GPUInfo& context_gpu_info) { |
| 461 | DCHECK(basic_gpu_info); |
| 462 | |
| 463 | if (context_gpu_info.software_rendering) { |
| 464 | basic_gpu_info->software_rendering = true; |
| 465 | return; |
| 466 | } |
| 467 | |
James Robinson | 6e9a1c9 | 2014-11-13 17:05:42 -0800 | [diff] [blame] | 468 | // Track D3D Shader Model (if available) |
| 469 | const std::string& shader_version = |
| 470 | context_gpu_info.vertex_shader_version; |
| 471 | |
| 472 | // Only gather if this is the first time we're seeing |
| 473 | // a non-empty shader version string. |
| 474 | if (!shader_version.empty() && |
| 475 | basic_gpu_info->vertex_shader_version.empty()) { |
| 476 | |
| 477 | // Note: do not reorder, used by UMA_HISTOGRAM below |
| 478 | enum ShaderModel { |
| 479 | SHADER_MODEL_UNKNOWN, |
| 480 | SHADER_MODEL_2_0, |
| 481 | SHADER_MODEL_3_0, |
| 482 | SHADER_MODEL_4_0, |
| 483 | SHADER_MODEL_4_1, |
| 484 | SHADER_MODEL_5_0, |
| 485 | NUM_SHADER_MODELS |
| 486 | }; |
| 487 | |
| 488 | ShaderModel shader_model = SHADER_MODEL_UNKNOWN; |
| 489 | |
| 490 | if (shader_version == "5.0") { |
| 491 | shader_model = SHADER_MODEL_5_0; |
| 492 | } else if (shader_version == "4.1") { |
| 493 | shader_model = SHADER_MODEL_4_1; |
| 494 | } else if (shader_version == "4.0") { |
| 495 | shader_model = SHADER_MODEL_4_0; |
| 496 | } else if (shader_version == "3.0") { |
| 497 | shader_model = SHADER_MODEL_3_0; |
| 498 | } else if (shader_version == "2.0") { |
| 499 | shader_model = SHADER_MODEL_2_0; |
| 500 | } |
| 501 | |
| 502 | UMA_HISTOGRAM_ENUMERATION("GPU.D3DShaderModel", |
| 503 | shader_model, |
| 504 | NUM_SHADER_MODELS); |
| 505 | } |
| 506 | |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 507 | MergeGPUInfoGL(basic_gpu_info, context_gpu_info); |
| 508 | |
Alhaad Gokhale | 4f51307 | 2015-03-24 10:49:34 -0700 | [diff] [blame] | 509 | basic_gpu_info->dx_diagnostics_info_state = |
| 510 | context_gpu_info.dx_diagnostics_info_state; |
James Robinson | 646469d | 2014-10-03 15:33:28 -0700 | [diff] [blame] | 511 | basic_gpu_info->dx_diagnostics = context_gpu_info.dx_diagnostics; |
| 512 | } |
| 513 | |
| 514 | } // namespace gpu |