OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "gpu/config/gpu_info_collector.h" | 5 #include "gpu/config/gpu_info_collector.h" |
6 | 6 |
7 // This has to be included before windows.h. | 7 // This has to be included before windows.h. |
8 #include "third_party/re2/re2/re2.h" | 8 #include "third_party/re2/re2/re2.h" |
9 | 9 |
10 #include <windows.h> | 10 #include <windows.h> |
11 #include <cfgmgr32.h> | |
11 #include <d3d9.h> | 12 #include <d3d9.h> |
12 #include <d3d11.h> | 13 #include <d3d11.h> |
13 #include <dxgi.h> | 14 #include <dxgi.h> |
14 #include <setupapi.h> | 15 #include <setupapi.h> |
15 | 16 |
16 #include "base/command_line.h" | 17 #include "base/command_line.h" |
17 #include "base/files/file_enumerator.h" | 18 #include "base/files/file_enumerator.h" |
18 #include "base/files/file_path.h" | 19 #include "base/files/file_path.h" |
19 #include "base/files/file_util.h" | 20 #include "base/files/file_util.h" |
20 #include "base/logging.h" | 21 #include "base/logging.h" |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
356 | 357 |
357 // Collects information about the level of D3D11 support and records it in | 358 // Collects information about the level of D3D11 support and records it in |
358 // the UMA stats. Records no stats when D3D11 in not supported at all. | 359 // the UMA stats. Records no stats when D3D11 in not supported at all. |
359 void CollectD3D11Support() { | 360 void CollectD3D11Support() { |
360 // D3D11 takes about 50ms to initialize so do this on a worker thread. | 361 // D3D11 takes about 50ms to initialize so do this on a worker thread. |
361 base::WorkerPool::PostTask( | 362 base::WorkerPool::PostTask( |
362 FROM_HERE, | 363 FROM_HERE, |
363 base::Bind(CollectD3D11SupportOnWorkerThread), | 364 base::Bind(CollectD3D11SupportOnWorkerThread), |
364 false); | 365 false); |
365 } | 366 } |
367 | |
368 void DeviceIDToVendorAndDevice(const std::wstring& id, | |
369 uint32* vendor_id, | |
370 uint32* device_id) { | |
371 *vendor_id = 0; | |
372 *device_id = 0; | |
373 if (id.length() < 21) | |
374 return; | |
375 base::string16 vendor_id_string = id.substr(8, 4); | |
376 base::string16 device_id_string = id.substr(17, 4); | |
377 int vendor = 0; | |
378 int device = 0; | |
379 base::HexStringToInt(base::UTF16ToASCII(vendor_id_string), &vendor); | |
380 base::HexStringToInt(base::UTF16ToASCII(device_id_string), &device); | |
381 *vendor_id = vendor; | |
382 *device_id = device; | |
383 } | |
384 | |
366 } // namespace anonymous | 385 } // namespace anonymous |
367 | 386 |
368 #if defined(GOOGLE_CHROME_BUILD) && defined(OFFICIAL_BUILD) | 387 #if defined(GOOGLE_CHROME_BUILD) && defined(OFFICIAL_BUILD) |
369 // This function has a real implementation for official builds that can | 388 // This function has a real implementation for official builds that can |
370 // be found in src/third_party/amd. | 389 // be found in src/third_party/amd. |
371 void GetAMDVideocardInfo(GPUInfo* gpu_info); | 390 void GetAMDVideocardInfo(GPUInfo* gpu_info); |
372 #else | 391 #else |
373 void GetAMDVideocardInfo(GPUInfo* gpu_info) { | 392 void GetAMDVideocardInfo(GPUInfo* gpu_info) { |
374 DCHECK(gpu_info); | 393 DCHECK(gpu_info); |
375 return; | 394 return; |
376 } | 395 } |
377 #endif | 396 #endif |
378 | 397 |
379 CollectInfoResult CollectDriverInfoD3D(const std::wstring& device_id, | 398 CollectInfoResult CollectDriverInfoD3D(const std::wstring& device_id, |
380 GPUInfo* gpu_info) { | 399 GPUInfo* gpu_info) { |
381 TRACE_EVENT0("gpu", "CollectDriverInfoD3D"); | 400 TRACE_EVENT0("gpu", "CollectDriverInfoD3D"); |
382 | 401 |
402 // Display adapter class GUID from | |
403 // https://msdn.microsoft.com/en-us/library/windows/hardware/ff553426%28v=vs.8 5%29.aspx | |
404 GUID display_class = {0x4d36e968, | |
405 0xe325, | |
406 0x11ce, | |
407 {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}}; | |
408 | |
383 // create device info for the display device | 409 // create device info for the display device |
384 HDEVINFO device_info = SetupDiGetClassDevsW( | 410 HDEVINFO device_info = |
385 NULL, device_id.c_str(), NULL, | 411 SetupDiGetClassDevsW(&display_class, NULL, NULL, DIGCF_PRESENT); |
386 DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES); | |
387 if (device_info == INVALID_HANDLE_VALUE) { | 412 if (device_info == INVALID_HANDLE_VALUE) { |
388 LOG(ERROR) << "Creating device info failed"; | 413 LOG(ERROR) << "Creating device info failed"; |
389 return kCollectInfoNonFatalFailure; | 414 return kCollectInfoNonFatalFailure; |
390 } | 415 } |
391 | 416 |
417 struct GPUDriver { | |
418 GPUInfo::GPUDevice device; | |
419 std::string driver_vendor; | |
420 std::string driver_version; | |
421 std::string driver_date; | |
422 }; | |
423 | |
424 std::vector<GPUDriver> drivers; | |
425 | |
426 int primary_device = -1; | |
427 bool found_amd = false; | |
428 bool found_intel = false; | |
429 | |
392 DWORD index = 0; | 430 DWORD index = 0; |
393 bool found = false; | |
394 SP_DEVINFO_DATA device_info_data; | 431 SP_DEVINFO_DATA device_info_data; |
395 device_info_data.cbSize = sizeof(device_info_data); | 432 device_info_data.cbSize = sizeof(device_info_data); |
396 while (SetupDiEnumDeviceInfo(device_info, index++, &device_info_data)) { | 433 while (SetupDiEnumDeviceInfo(device_info, index++, &device_info_data)) { |
397 WCHAR value[255]; | 434 WCHAR value[255]; |
398 if (SetupDiGetDeviceRegistryPropertyW(device_info, | 435 if (SetupDiGetDeviceRegistryPropertyW(device_info, |
399 &device_info_data, | 436 &device_info_data, |
400 SPDRP_DRIVER, | 437 SPDRP_DRIVER, |
401 NULL, | 438 NULL, |
402 reinterpret_cast<PBYTE>(value), | 439 reinterpret_cast<PBYTE>(value), |
403 sizeof(value), | 440 sizeof(value), |
(...skipping 18 matching lines...) Expand all Loading... | |
422 key, L"DriverDate", NULL, NULL, | 459 key, L"DriverDate", NULL, NULL, |
423 reinterpret_cast<LPBYTE>(value), &dwcb_data); | 460 reinterpret_cast<LPBYTE>(value), &dwcb_data); |
424 if (result == ERROR_SUCCESS) | 461 if (result == ERROR_SUCCESS) |
425 driver_date = base::UTF16ToASCII(std::wstring(value)); | 462 driver_date = base::UTF16ToASCII(std::wstring(value)); |
426 | 463 |
427 std::string driver_vendor; | 464 std::string driver_vendor; |
428 dwcb_data = sizeof(value); | 465 dwcb_data = sizeof(value); |
429 result = RegQueryValueExW( | 466 result = RegQueryValueExW( |
430 key, L"ProviderName", NULL, NULL, | 467 key, L"ProviderName", NULL, NULL, |
431 reinterpret_cast<LPBYTE>(value), &dwcb_data); | 468 reinterpret_cast<LPBYTE>(value), &dwcb_data); |
432 if (result == ERROR_SUCCESS) { | 469 if (result == ERROR_SUCCESS) |
433 driver_vendor = base::UTF16ToASCII(std::wstring(value)); | 470 driver_vendor = base::UTF16ToASCII(std::wstring(value)); |
434 if (driver_vendor == "Advanced Micro Devices, Inc." || | 471 |
435 driver_vendor == "ATI Technologies Inc.") { | 472 wchar_t new_device_id[MAX_DEVICE_ID_LEN]; |
436 // We are conservative and assume that in the absence of a clear | 473 CONFIGRET status = CM_Get_Device_ID( |
437 // signal the videocard is assumed to be switchable. Additionally, | 474 device_info_data.DevInst, new_device_id, MAX_DEVICE_ID_LEN, 0); |
438 // some switchable systems with Intel GPUs aren't correctly | 475 |
439 // detected, so always count them. | 476 if (status == CR_SUCCESS) { |
440 GetAMDVideocardInfo(gpu_info); | 477 GPUDriver driver; |
441 if (!gpu_info->amd_switchable && | 478 |
442 gpu_info->gpu.vendor_id == 0x8086) { | 479 driver.driver_vendor = driver_vendor; |
443 gpu_info->amd_switchable = true; | 480 driver.driver_version = driver_version; |
444 gpu_info->secondary_gpus.push_back(gpu_info->gpu); | 481 driver.driver_date = driver_date; |
445 gpu_info->gpu.vendor_id = 0x1002; | 482 std::wstring id = new_device_id; |
446 gpu_info->gpu.device_id = 0; // Unknown discrete AMD GPU. | 483 |
447 } | 484 if (id.compare(0, device_id.size(), device_id) == 0) |
448 } | 485 primary_device = drivers.size(); |
486 | |
487 uint32 vendor_id = 0, device_id = 0; | |
brucedawson
2015/02/09 18:25:41
This variable declaration of device_id shadows the
| |
488 DeviceIDToVendorAndDevice(id, &vendor_id, &device_id); | |
489 driver.device.vendor_id = vendor_id; | |
490 driver.device.device_id = device_id; | |
491 drivers.push_back(driver); | |
492 | |
493 if (vendor_id == 0x8086) | |
494 found_intel = true; | |
495 if (vendor_id == 0x1002) | |
496 found_amd = true; | |
449 } | 497 } |
450 | 498 |
451 gpu_info->driver_vendor = driver_vendor; | |
452 gpu_info->driver_version = driver_version; | |
453 gpu_info->driver_date = driver_date; | |
454 found = true; | |
455 RegCloseKey(key); | 499 RegCloseKey(key); |
456 break; | |
457 } | 500 } |
458 } | 501 } |
459 } | 502 } |
460 SetupDiDestroyDeviceInfoList(device_info); | 503 SetupDiDestroyDeviceInfoList(device_info); |
504 bool found = false; | |
505 if (found_amd && found_intel) { | |
506 // AMD Switchable system found. | |
507 for (const auto& driver : drivers) { | |
508 if (driver.device.vendor_id == 0x8086) { | |
509 gpu_info->gpu = driver.device; | |
510 } | |
511 | |
512 if (driver.device.vendor_id == 0x1002) { | |
513 gpu_info->driver_vendor = driver.driver_vendor; | |
514 gpu_info->driver_version = driver.driver_version; | |
515 gpu_info->driver_date = driver.driver_date; | |
516 } | |
517 } | |
518 GetAMDVideocardInfo(gpu_info); | |
519 | |
520 if (!gpu_info->amd_switchable) { | |
521 // Some machines aren't properly detected as AMD switchable, but count | |
522 // them anyway. | |
523 gpu_info->amd_switchable = true; | |
524 for (const auto& driver : drivers) { | |
525 if (driver.device.vendor_id == 0x1002) { | |
526 gpu_info->gpu = driver.device; | |
527 } else { | |
528 gpu_info->secondary_gpus.push_back(driver.device); | |
529 } | |
530 } | |
531 } | |
532 found = true; | |
533 } else { | |
534 for (size_t i = 0; i < drivers.size(); ++i) { | |
535 const GPUDriver& driver = drivers[i]; | |
536 if (static_cast<int>(i) == primary_device) { | |
537 found = true; | |
538 gpu_info->gpu = driver.device; | |
539 gpu_info->driver_vendor = driver.driver_vendor; | |
540 gpu_info->driver_version = driver.driver_version; | |
541 gpu_info->driver_date = driver.driver_date; | |
542 } else { | |
543 gpu_info->secondary_gpus.push_back(driver.device); | |
544 } | |
545 } | |
546 } | |
547 | |
461 return found ? kCollectInfoSuccess : kCollectInfoNonFatalFailure; | 548 return found ? kCollectInfoSuccess : kCollectInfoNonFatalFailure; |
462 } | 549 } |
463 | 550 |
464 CollectInfoResult CollectContextGraphicsInfo(GPUInfo* gpu_info) { | 551 CollectInfoResult CollectContextGraphicsInfo(GPUInfo* gpu_info) { |
465 TRACE_EVENT0("gpu", "CollectGraphicsInfo"); | 552 TRACE_EVENT0("gpu", "CollectGraphicsInfo"); |
466 | 553 |
467 DCHECK(gpu_info); | 554 DCHECK(gpu_info); |
468 | 555 |
469 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) { | 556 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) { |
470 std::string requested_implementation_name = | 557 std::string requested_implementation_name = |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
544 dd.cb = sizeof(DISPLAY_DEVICE); | 631 dd.cb = sizeof(DISPLAY_DEVICE); |
545 std::wstring id; | 632 std::wstring id; |
546 for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) { | 633 for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) { |
547 if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { | 634 if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { |
548 id = dd.DeviceID; | 635 id = dd.DeviceID; |
549 break; | 636 break; |
550 } | 637 } |
551 } | 638 } |
552 | 639 |
553 if (id.length() > 20) { | 640 if (id.length() > 20) { |
554 int vendor = 0, device = 0; | 641 DeviceIDToVendorAndDevice(id, vendor_id, device_id); |
555 std::wstring vendor_string = id.substr(8, 4); | |
556 std::wstring device_string = id.substr(17, 4); | |
557 base::HexStringToInt(base::UTF16ToASCII(vendor_string), &vendor); | |
558 base::HexStringToInt(base::UTF16ToASCII(device_string), &device); | |
559 *vendor_id = vendor; | |
560 *device_id = device; | |
561 if (*vendor_id != 0 && *device_id != 0) | 642 if (*vendor_id != 0 && *device_id != 0) |
562 return kCollectInfoSuccess; | 643 return kCollectInfoSuccess; |
563 } | 644 } |
564 return kCollectInfoNonFatalFailure; | 645 return kCollectInfoNonFatalFailure; |
565 } | 646 } |
566 | 647 |
567 CollectInfoResult CollectBasicGraphicsInfo(GPUInfo* gpu_info) { | 648 CollectInfoResult CollectBasicGraphicsInfo(GPUInfo* gpu_info) { |
568 TRACE_EVENT0("gpu", "CollectPreliminaryGraphicsInfo"); | 649 TRACE_EVENT0("gpu", "CollectPreliminaryGraphicsInfo"); |
569 | 650 |
570 DCHECK(gpu_info); | 651 DCHECK(gpu_info); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
602 id = dd.DeviceID; | 683 id = dd.DeviceID; |
603 break; | 684 break; |
604 } | 685 } |
605 } | 686 } |
606 | 687 |
607 if (id.length() <= 20) { | 688 if (id.length() <= 20) { |
608 gpu_info->basic_info_state = kCollectInfoNonFatalFailure; | 689 gpu_info->basic_info_state = kCollectInfoNonFatalFailure; |
609 return kCollectInfoNonFatalFailure; | 690 return kCollectInfoNonFatalFailure; |
610 } | 691 } |
611 | 692 |
612 int vendor_id = 0, device_id = 0; | 693 DeviceIDToVendorAndDevice(id, &gpu_info->gpu.vendor_id, |
613 base::string16 vendor_id_string = id.substr(8, 4); | 694 &gpu_info->gpu.device_id); |
614 base::string16 device_id_string = id.substr(17, 4); | |
615 base::HexStringToInt(base::UTF16ToASCII(vendor_id_string), &vendor_id); | |
616 base::HexStringToInt(base::UTF16ToASCII(device_id_string), &device_id); | |
617 gpu_info->gpu.vendor_id = vendor_id; | |
618 gpu_info->gpu.device_id = device_id; | |
619 // TODO(zmo): we only need to call CollectDriverInfoD3D() if we use ANGLE. | 695 // TODO(zmo): we only need to call CollectDriverInfoD3D() if we use ANGLE. |
620 if (!CollectDriverInfoD3D(id, gpu_info)) { | 696 if (!CollectDriverInfoD3D(id, gpu_info)) { |
621 gpu_info->basic_info_state = kCollectInfoNonFatalFailure; | 697 gpu_info->basic_info_state = kCollectInfoNonFatalFailure; |
622 return kCollectInfoNonFatalFailure; | 698 return kCollectInfoNonFatalFailure; |
623 } | 699 } |
624 | 700 |
625 // Collect basic information about supported D3D11 features. Delay for 45 | 701 // Collect basic information about supported D3D11 features. Delay for 45 |
626 // seconds so as not to regress performance tests. | 702 // seconds so as not to regress performance tests. |
627 if (D3D11ShouldWork(*gpu_info)) { | 703 if (D3D11ShouldWork(*gpu_info)) { |
628 // This is on a field trial so we can turn it off easily if it blows up | 704 // This is on a field trial so we can turn it off easily if it blows up |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
704 shader_model, | 780 shader_model, |
705 NUM_SHADER_MODELS); | 781 NUM_SHADER_MODELS); |
706 } | 782 } |
707 | 783 |
708 MergeGPUInfoGL(basic_gpu_info, context_gpu_info); | 784 MergeGPUInfoGL(basic_gpu_info, context_gpu_info); |
709 | 785 |
710 basic_gpu_info->dx_diagnostics = context_gpu_info.dx_diagnostics; | 786 basic_gpu_info->dx_diagnostics = context_gpu_info.dx_diagnostics; |
711 } | 787 } |
712 | 788 |
713 } // namespace gpu | 789 } // namespace gpu |
OLD | NEW |