Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: gpu/config/gpu_info_collector_win.cc

Issue 893993006: Enumerate all display adapters to detect AMD switchable graphics. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698