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 "content/gpu/gpu_info_collector.h" | 5 #include "content/gpu/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> |
(...skipping 17 matching lines...) Expand all Loading... |
28 #include "base/threading/thread.h" | 28 #include "base/threading/thread.h" |
29 #include "base/threading/worker_pool.h" | 29 #include "base/threading/worker_pool.h" |
30 #include "base/win/registry.h" | 30 #include "base/win/registry.h" |
31 #include "base/win/scoped_com_initializer.h" | 31 #include "base/win/scoped_com_initializer.h" |
32 #include "base/win/scoped_comptr.h" | 32 #include "base/win/scoped_comptr.h" |
33 #include "base/win/windows_version.h" | 33 #include "base/win/windows_version.h" |
34 #include "third_party/libxml/chromium/libxml_utils.h" | 34 #include "third_party/libxml/chromium/libxml_utils.h" |
35 #include "ui/gl/gl_implementation.h" | 35 #include "ui/gl/gl_implementation.h" |
36 #include "ui/gl/gl_surface_egl.h" | 36 #include "ui/gl/gl_surface_egl.h" |
37 | 37 |
| 38 namespace gpu { |
| 39 |
38 namespace { | 40 namespace { |
39 | 41 |
40 // This must be kept in sync with histograms.xml. | 42 // This must be kept in sync with histograms.xml. |
41 enum DisplayLinkInstallationStatus { | 43 enum DisplayLinkInstallationStatus { |
42 DISPLAY_LINK_NOT_INSTALLED, | 44 DISPLAY_LINK_NOT_INSTALLED, |
43 DISPLAY_LINK_7_1_OR_EARLIER, | 45 DISPLAY_LINK_7_1_OR_EARLIER, |
44 DISPLAY_LINK_7_2_OR_LATER, | 46 DISPLAY_LINK_7_2_OR_LATER, |
45 DISPLAY_LINK_INSTALLATION_STATUS_MAX | 47 DISPLAY_LINK_INSTALLATION_STATUS_MAX |
46 }; | 48 }; |
47 | 49 |
48 float ReadXMLFloatValue(XmlReader* reader) { | 50 float ReadXMLFloatValue(XmlReader* reader) { |
49 std::string score_string; | 51 std::string score_string; |
50 if (!reader->ReadElementContent(&score_string)) | 52 if (!reader->ReadElementContent(&score_string)) |
51 return 0.0; | 53 return 0.0; |
52 | 54 |
53 double score; | 55 double score; |
54 if (!base::StringToDouble(score_string, &score)) | 56 if (!base::StringToDouble(score_string, &score)) |
55 return 0.0; | 57 return 0.0; |
56 | 58 |
57 return static_cast<float>(score); | 59 return static_cast<float>(score); |
58 } | 60 } |
59 | 61 |
60 content::GpuPerformanceStats RetrieveGpuPerformanceStats() { | 62 GpuPerformanceStats RetrieveGpuPerformanceStats() { |
61 TRACE_EVENT0("gpu", "RetrieveGpuPerformanceStats"); | 63 TRACE_EVENT0("gpu", "RetrieveGpuPerformanceStats"); |
62 | 64 |
63 // If the user re-runs the assessment without restarting, the COM API | 65 // If the user re-runs the assessment without restarting, the COM API |
64 // returns WINSAT_ASSESSMENT_STATE_NOT_AVAILABLE. Because of that and | 66 // returns WINSAT_ASSESSMENT_STATE_NOT_AVAILABLE. Because of that and |
65 // http://crbug.com/124325, read the assessment result files directly. | 67 // http://crbug.com/124325, read the assessment result files directly. |
66 content::GpuPerformanceStats stats; | 68 GpuPerformanceStats stats; |
67 | 69 |
68 // Get path to WinSAT results files. | 70 // Get path to WinSAT results files. |
69 wchar_t winsat_results_path[MAX_PATH]; | 71 wchar_t winsat_results_path[MAX_PATH]; |
70 DWORD size = ExpandEnvironmentStrings( | 72 DWORD size = ExpandEnvironmentStrings( |
71 L"%WinDir%\\Performance\\WinSAT\\DataStore\\", | 73 L"%WinDir%\\Performance\\WinSAT\\DataStore\\", |
72 winsat_results_path, MAX_PATH); | 74 winsat_results_path, MAX_PATH); |
73 if (size == 0 || size > MAX_PATH) { | 75 if (size == 0 || size > MAX_PATH) { |
74 LOG(ERROR) << "The path to the WinSAT results is too long: " | 76 LOG(ERROR) << "The path to the WinSAT results is too long: " |
75 << size << " chars."; | 77 << size << " chars."; |
76 return stats; | 78 return stats; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 if (stats.overall == 0.0) | 139 if (stats.overall == 0.0) |
138 LOG(ERROR) << "Could not read overall score from assessment results."; | 140 LOG(ERROR) << "Could not read overall score from assessment results."; |
139 if (stats.graphics == 0.0) | 141 if (stats.graphics == 0.0) |
140 LOG(ERROR) << "Could not read graphics score from assessment results."; | 142 LOG(ERROR) << "Could not read graphics score from assessment results."; |
141 if (stats.gaming == 0.0) | 143 if (stats.gaming == 0.0) |
142 LOG(ERROR) << "Could not read gaming score from assessment results."; | 144 LOG(ERROR) << "Could not read gaming score from assessment results."; |
143 | 145 |
144 return stats; | 146 return stats; |
145 } | 147 } |
146 | 148 |
147 content::GpuPerformanceStats RetrieveGpuPerformanceStatsWithHistograms() { | 149 GpuPerformanceStats RetrieveGpuPerformanceStatsWithHistograms() { |
148 base::TimeTicks start_time = base::TimeTicks::Now(); | 150 base::TimeTicks start_time = base::TimeTicks::Now(); |
149 | 151 |
150 content::GpuPerformanceStats stats = RetrieveGpuPerformanceStats(); | 152 GpuPerformanceStats stats = RetrieveGpuPerformanceStats(); |
151 | 153 |
152 UMA_HISTOGRAM_TIMES("GPU.WinSAT.ReadResultsFileTime", | 154 UMA_HISTOGRAM_TIMES("GPU.WinSAT.ReadResultsFileTime", |
153 base::TimeTicks::Now() - start_time); | 155 base::TimeTicks::Now() - start_time); |
154 UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.OverallScore2", | 156 UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.OverallScore2", |
155 stats.overall * 10, 10, 200, 50); | 157 stats.overall * 10, 10, 200, 50); |
156 UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.GraphicsScore2", | 158 UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.GraphicsScore2", |
157 stats.graphics * 10, 10, 200, 50); | 159 stats.graphics * 10, 10, 200, 50); |
158 UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.GamingScore2", | 160 UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.GamingScore2", |
159 stats.gaming * 10, 10, 200, 50); | 161 stats.gaming * 10, 10, 200, 50); |
160 UMA_HISTOGRAM_BOOLEAN( | 162 UMA_HISTOGRAM_BOOLEAN( |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 return false; | 198 return false; |
197 | 199 |
198 if (key.OpenKey(L"Lenovo dCute", KEY_READ | KEY_WOW64_64KEY)) | 200 if (key.OpenKey(L"Lenovo dCute", KEY_READ | KEY_WOW64_64KEY)) |
199 return false; | 201 return false; |
200 | 202 |
201 return true; | 203 return true; |
202 } | 204 } |
203 | 205 |
204 // Determines whether D3D11 won't work, either because it is not supported on | 206 // Determines whether D3D11 won't work, either because it is not supported on |
205 // the machine or because it is known it is likely to crash. | 207 // the machine or because it is known it is likely to crash. |
206 bool D3D11ShouldWork(const content::GPUInfo& gpu_info) { | 208 bool D3D11ShouldWork(const GPUInfo& gpu_info) { |
207 // Windows XP never supports D3D11. | 209 // Windows XP never supports D3D11. |
208 if (base::win::GetVersion() <= base::win::VERSION_XP) | 210 if (base::win::GetVersion() <= base::win::VERSION_XP) |
209 return false; | 211 return false; |
210 | 212 |
211 // Intel? | 213 // Intel? |
212 if (gpu_info.gpu.vendor_id == 0x8086) { | 214 if (gpu_info.gpu.vendor_id == 0x8086) { |
213 // 2nd Generation Core Processor Family Integrated Graphics Controller | 215 // 2nd Generation Core Processor Family Integrated Graphics Controller |
214 // or Intel Ivy Bridge? | 216 // or Intel Ivy Bridge? |
215 if (gpu_info.gpu.device_id == 0x0102 || | 217 if (gpu_info.gpu.device_id == 0x0102 || |
216 gpu_info.gpu.device_id == 0x0106 || | 218 gpu_info.gpu.device_id == 0x0106 || |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 // the UMA stats. Records no stats when D3D11 in not supported at all. | 364 // the UMA stats. Records no stats when D3D11 in not supported at all. |
363 void CollectD3D11Support() { | 365 void CollectD3D11Support() { |
364 // D3D11 takes about 50ms to initialize so do this on a worker thread. | 366 // D3D11 takes about 50ms to initialize so do this on a worker thread. |
365 base::WorkerPool::PostTask( | 367 base::WorkerPool::PostTask( |
366 FROM_HERE, | 368 FROM_HERE, |
367 base::Bind(CollectD3D11SupportOnWorkerThread), | 369 base::Bind(CollectD3D11SupportOnWorkerThread), |
368 false); | 370 false); |
369 } | 371 } |
370 } // namespace anonymous | 372 } // namespace anonymous |
371 | 373 |
372 namespace gpu_info_collector { | |
373 | |
374 #if !defined(GOOGLE_CHROME_BUILD) | 374 #if !defined(GOOGLE_CHROME_BUILD) |
375 AMDVideoCardType GetAMDVideocardType() { | 375 AMDVideoCardType GetAMDVideocardType() { |
376 return STANDALONE; | 376 return STANDALONE; |
377 } | 377 } |
378 #else | 378 #else |
379 // This function has a real implementation for official builds that can | 379 // This function has a real implementation for official builds that can |
380 // be found in src/third_party/amd. | 380 // be found in src/third_party/amd. |
381 AMDVideoCardType GetAMDVideocardType(); | 381 AMDVideoCardType GetAMDVideocardType(); |
382 #endif | 382 #endif |
383 | 383 |
384 bool CollectDriverInfoD3D(const std::wstring& device_id, | 384 bool CollectDriverInfoD3D(const std::wstring& device_id, |
385 content::GPUInfo* gpu_info) { | 385 GPUInfo* gpu_info) { |
386 TRACE_EVENT0("gpu", "CollectDriverInfoD3D"); | 386 TRACE_EVENT0("gpu", "CollectDriverInfoD3D"); |
387 | 387 |
388 // create device info for the display device | 388 // create device info for the display device |
389 HDEVINFO device_info = SetupDiGetClassDevsW( | 389 HDEVINFO device_info = SetupDiGetClassDevsW( |
390 NULL, device_id.c_str(), NULL, | 390 NULL, device_id.c_str(), NULL, |
391 DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES); | 391 DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES); |
392 if (device_info == INVALID_HANDLE_VALUE) { | 392 if (device_info == INVALID_HANDLE_VALUE) { |
393 LOG(ERROR) << "Creating device info failed"; | 393 LOG(ERROR) << "Creating device info failed"; |
394 return false; | 394 return false; |
395 } | 395 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 found = true; | 454 found = true; |
455 RegCloseKey(key); | 455 RegCloseKey(key); |
456 break; | 456 break; |
457 } | 457 } |
458 } | 458 } |
459 } | 459 } |
460 SetupDiDestroyDeviceInfoList(device_info); | 460 SetupDiDestroyDeviceInfoList(device_info); |
461 return found; | 461 return found; |
462 } | 462 } |
463 | 463 |
464 bool CollectContextGraphicsInfo(content::GPUInfo* gpu_info) { | 464 bool CollectContextGraphicsInfo(GPUInfo* gpu_info) { |
465 TRACE_EVENT0("gpu", "CollectGraphicsInfo"); | 465 TRACE_EVENT0("gpu", "CollectGraphicsInfo"); |
466 | 466 |
467 DCHECK(gpu_info); | 467 DCHECK(gpu_info); |
468 | 468 |
469 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) { | 469 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) { |
470 std::string requested_implementation_name = | 470 std::string requested_implementation_name = |
471 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL); | 471 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL); |
472 if (requested_implementation_name == "swiftshader") { | 472 if (requested_implementation_name == "swiftshader") { |
473 gpu_info->software_rendering = true; | 473 gpu_info->software_rendering = true; |
474 return false; | 474 return false; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 std::wstring device_string = id.substr(17, 4); | 540 std::wstring device_string = id.substr(17, 4); |
541 base::HexStringToInt(WideToASCII(vendor_string), &vendor); | 541 base::HexStringToInt(WideToASCII(vendor_string), &vendor); |
542 base::HexStringToInt(WideToASCII(device_string), &device); | 542 base::HexStringToInt(WideToASCII(device_string), &device); |
543 *vendor_id = vendor; | 543 *vendor_id = vendor; |
544 *device_id = device; | 544 *device_id = device; |
545 return kGpuIDSuccess; | 545 return kGpuIDSuccess; |
546 } | 546 } |
547 return kGpuIDFailure; | 547 return kGpuIDFailure; |
548 } | 548 } |
549 | 549 |
550 bool CollectBasicGraphicsInfo(content::GPUInfo* gpu_info) { | 550 bool CollectBasicGraphicsInfo(GPUInfo* gpu_info) { |
551 TRACE_EVENT0("gpu", "CollectPreliminaryGraphicsInfo"); | 551 TRACE_EVENT0("gpu", "CollectPreliminaryGraphicsInfo"); |
552 | 552 |
553 DCHECK(gpu_info); | 553 DCHECK(gpu_info); |
554 | 554 |
555 gpu_info->performance_stats = RetrieveGpuPerformanceStatsWithHistograms(); | 555 gpu_info->performance_stats = RetrieveGpuPerformanceStatsWithHistograms(); |
556 | 556 |
557 // nvd3d9wrap.dll is loaded into all processes when Optimus is enabled. | 557 // nvd3d9wrap.dll is loaded into all processes when Optimus is enabled. |
558 HMODULE nvd3d9wrap = GetModuleHandleW(L"nvd3d9wrap.dll"); | 558 HMODULE nvd3d9wrap = GetModuleHandleW(L"nvd3d9wrap.dll"); |
559 gpu_info->optimus = nvd3d9wrap != NULL; | 559 gpu_info->optimus = nvd3d9wrap != NULL; |
560 | 560 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 if (D3D11ShouldWork(*gpu_info)) { | 606 if (D3D11ShouldWork(*gpu_info)) { |
607 base::MessageLoop::current()->PostDelayedTask( | 607 base::MessageLoop::current()->PostDelayedTask( |
608 FROM_HERE, | 608 FROM_HERE, |
609 base::Bind(&CollectD3D11Support), | 609 base::Bind(&CollectD3D11Support), |
610 base::TimeDelta::FromSeconds(45)); | 610 base::TimeDelta::FromSeconds(45)); |
611 } | 611 } |
612 | 612 |
613 return true; | 613 return true; |
614 } | 614 } |
615 | 615 |
616 bool CollectDriverInfoGL(content::GPUInfo* gpu_info) { | 616 bool CollectDriverInfoGL(GPUInfo* gpu_info) { |
617 TRACE_EVENT0("gpu", "CollectDriverInfoGL"); | 617 TRACE_EVENT0("gpu", "CollectDriverInfoGL"); |
618 | 618 |
619 if (!gpu_info->driver_version.empty()) | 619 if (!gpu_info->driver_version.empty()) |
620 return true; | 620 return true; |
621 | 621 |
622 std::string gl_version_string = gpu_info->gl_version_string; | 622 std::string gl_version_string = gpu_info->gl_version_string; |
623 | 623 |
624 return RE2::PartialMatch(gl_version_string, | 624 return RE2::PartialMatch(gl_version_string, |
625 "([\\d\\.]+)$", | 625 "([\\d\\.]+)$", |
626 &gpu_info->driver_version); | 626 &gpu_info->driver_version); |
627 } | 627 } |
628 | 628 |
629 void MergeGPUInfo(content::GPUInfo* basic_gpu_info, | 629 void MergeGPUInfo(GPUInfo* basic_gpu_info, |
630 const content::GPUInfo& context_gpu_info) { | 630 const GPUInfo& context_gpu_info) { |
631 DCHECK(basic_gpu_info); | 631 DCHECK(basic_gpu_info); |
632 | 632 |
633 if (context_gpu_info.software_rendering) { | 633 if (context_gpu_info.software_rendering) { |
634 basic_gpu_info->software_rendering = true; | 634 basic_gpu_info->software_rendering = true; |
635 return; | 635 return; |
636 } | 636 } |
637 | 637 |
638 MergeGPUInfoGL(basic_gpu_info, context_gpu_info); | 638 MergeGPUInfoGL(basic_gpu_info, context_gpu_info); |
639 | 639 |
640 basic_gpu_info->dx_diagnostics = context_gpu_info.dx_diagnostics; | 640 basic_gpu_info->dx_diagnostics = context_gpu_info.dx_diagnostics; |
641 } | 641 } |
642 | 642 |
643 } // namespace gpu_info_collector | 643 } // namespace gpu |
OLD | NEW |