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

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

Issue 10128002: Retrieve Windows performance assessment information from results files. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add histograms. Created 8 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « content/gpu/DEPS ('k') | 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 "content/gpu/gpu_info_collector.h" 5 #include "content/gpu/gpu_info_collector.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <d3d9.h> 8 #include <d3d9.h>
9 #include <setupapi.h> 9 #include <setupapi.h>
10 #include <winsatcominterfacei.h>
11 10
12 #include "base/command_line.h" 11 #include "base/command_line.h"
13 #include "base/file_path.h" 12 #include "base/file_path.h"
13 #include "base/file_util.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/metrics/histogram.h"
15 #include "base/scoped_native_library.h" 16 #include "base/scoped_native_library.h"
16 #include "base/string_number_conversions.h" 17 #include "base/string_number_conversions.h"
17 #include "base/string_util.h" 18 #include "base/string_util.h"
18 #include "base/win/scoped_com_initializer.h" 19 #include "base/win/scoped_com_initializer.h"
19 #include "base/win/scoped_comptr.h" 20 #include "base/win/scoped_comptr.h"
21 #include "third_party/libxml/chromium/libxml_utils.h"
20 #include "ui/gl/gl_implementation.h" 22 #include "ui/gl/gl_implementation.h"
21 #include "ui/gl/gl_surface_egl.h" 23 #include "ui/gl/gl_surface_egl.h"
22 24
23 // ANGLE seems to require that main.h be included before any other ANGLE header. 25 // ANGLE seems to require that main.h be included before any other ANGLE header.
24 #include "libEGL/Display.h" 26 #include "libEGL/Display.h"
25 #include "libEGL/main.h" 27 #include "libEGL/main.h"
26 28
27 namespace { 29 namespace {
28 30
29 // The version number stores the major and minor version in the least 16 bits; 31 // The version number stores the major and minor version in the least 16 bits;
30 // for example, 2.5 is 0x00000205. 32 // for example, 2.5 is 0x00000205.
31 // Returned string is in the format of "major.minor". 33 // Returned string is in the format of "major.minor".
32 std::string VersionNumberToString(uint32 version_number) { 34 std::string VersionNumberToString(uint32 version_number) {
33 int hi = (version_number >> 8) & 0xff; 35 int hi = (version_number >> 8) & 0xff;
34 int low = version_number & 0xff; 36 int low = version_number & 0xff;
35 return base::IntToString(hi) + "." + base::IntToString(low); 37 return base::IntToString(hi) + "." + base::IntToString(low);
36 } 38 }
37 39
38 float GetAssessmentScore(IProvideWinSATResultsInfo* results, 40 float ReadXMLFloatValue(XmlReader* reader) {
39 WINSAT_ASSESSMENT_TYPE type) { 41 std::string score_string;
40 base::win::ScopedComPtr<IProvideWinSATAssessmentInfo> subcomponent; 42 if (!reader->ReadElementContent(&score_string))
41 if (FAILED(results->GetAssessmentInfo(type, subcomponent.Receive())))
42 return 0.0; 43 return 0.0;
43 44
44 float score = 0.0; 45 double score;
45 if (FAILED(subcomponent->get_Score(&score))) 46 if (!base::StringToDouble(score_string, &score))
46 score = 0.0; 47 return 0.0;
47 return score; 48
49 return static_cast<float>(score);
48 } 50 }
49 51
50 content::GpuPerformanceStats RetrieveGpuPerformanceStats() { 52 content::GpuPerformanceStats RetrieveGpuPerformanceStats() {
53 // If the user re-runs the assessment without restarting, the COM API
54 // returns WINSAT_ASSESSMENT_STATE_NOT_AVAILABLE. Because of that and
55 // http://crbug.com/124325, read the assessment result files directly.
51 content::GpuPerformanceStats stats; 56 content::GpuPerformanceStats stats;
52 57
53 base::win::ScopedCOMInitializer com_initializer; 58 base::TimeTicks start_time = base::TimeTicks::Now();
54 if (!com_initializer.succeeded()) { 59
55 LOG(ERROR) << "CoInitializeEx() failed"; 60 // Get path to WinSAT results files.
61 wchar_t winsat_results_path[MAX_PATH];
62 DWORD size = ExpandEnvironmentStrings(
63 L"%WinDir%\\Performance\\WinSAT\\DataStore\\",
64 winsat_results_path, MAX_PATH);
65 if (size == 0 || size > MAX_PATH) {
66 LOG(ERROR) << "The path to the WinSAT results is too long: "
67 << size << " chars.";
56 return stats; 68 return stats;
57 } 69 }
58 70
59 base::win::ScopedComPtr<IQueryRecentWinSATAssessment> assessment; 71 // Find most recent formal assessment results.
60 HRESULT hr = assessment.CreateInstance(__uuidof(CQueryWinSAT), NULL, 72 file_util::FileEnumerator file_enumerator(
61 CLSCTX_INPROC_SERVER); 73 FilePath(winsat_results_path),
62 if (FAILED(hr)) { 74 false, // not recursive
63 LOG(ERROR) << "CoCreateInstance() failed"; 75 file_util::FileEnumerator::FILES,
76 FILE_PATH_LITERAL("* * Formal.Assessment (*).WinSAT.xml"));
77
78 FilePath current_results;
79 for (FilePath results = file_enumerator.Next(); !results.empty();
80 results = file_enumerator.Next()) {
81 // The filenames start with the date and time as yyyy-mm-dd hh.mm.ss.xxx,
82 // so the greatest file lexicographically is also the most recent file.
83 if (FilePath::CompareLessIgnoreCase(current_results.value(),
84 results.value()))
85 current_results = results;
86 }
87
88 std::string current_results_string = current_results.MaybeAsASCII();
89 if (current_results_string.empty()) {
90 LOG(ERROR) << "Can't retrieve a valid WinSAT assessment.";
64 return stats; 91 return stats;
65 } 92 }
66 93
67 base::win::ScopedComPtr<IProvideWinSATResultsInfo> results; 94 // Get relevant scores from results file. XML schema at:
68 hr = assessment->get_Info(results.Receive()); 95 // http://msdn.microsoft.com/en-us/library/windows/desktop/aa969210.aspx
69 if (FAILED(hr)) { 96 XmlReader reader;
70 LOG(ERROR) << "get_Info() failed"; 97 if (!reader.LoadFile(current_results_string)) {
98 LOG(ERROR) << "Could not open WinSAT results file.";
99 return stats;
100 }
101 // Descend into <WinSAT> root element.
102 if (!reader.SkipToElement() || !reader.Read()) {
103 LOG(ERROR) << "Could not read WinSAT results file.";
71 return stats; 104 return stats;
72 } 105 }
73 106
74 WINSAT_ASSESSMENT_STATE state = WINSAT_ASSESSMENT_STATE_UNKNOWN; 107 // Search for <WinSPR> element containing the results.
75 hr = results->get_AssessmentState(&state); 108 do {
76 if (FAILED(hr)) { 109 if (reader.NodeName() == "WinSPR")
77 LOG(ERROR) << "get_AssessmentState() failed"; 110 break;
111 } while (reader.Next());
112 // Descend into <WinSPR> element.
113 if (!reader.Read()) {
114 LOG(ERROR) << "Could not find WinSPR element in results file.";
78 return stats; 115 return stats;
79 } 116 }
80 117
81 if (state != WINSAT_ASSESSMENT_STATE_VALID && 118 // Read scores.
82 state != WINSAT_ASSESSMENT_STATE_INCOHERENT_WITH_HARDWARE) { 119 for (int depth = reader.Depth(); reader.Depth() == depth; reader.Next()) {
83 LOG(ERROR) << "Can't retrieve a valid assessment"; 120 std::string node_name = reader.NodeName();
84 return stats; 121 if (node_name == "SystemScore")
122 stats.overall = ReadXMLFloatValue(&reader);
123 else if (node_name == "GraphicsScore")
124 stats.graphics = ReadXMLFloatValue(&reader);
125 else if (node_name == "GamingScore")
126 stats.gaming = ReadXMLFloatValue(&reader);
85 } 127 }
86 128
87 hr = results->get_SystemRating(&stats.overall); 129 if (stats.overall == 0.0)
88 if (FAILED(hr)) 130 LOG(ERROR) << "Could not read overall score from assessment results.";
89 LOG(ERROR) << "Get overall score failed"; 131 if (stats.graphics == 0.0)
132 LOG(ERROR) << "Could not read graphics score from assessment results.";
133 if (stats.gaming == 0.0)
134 LOG(ERROR) << "Could not read gaming score from assessment results.";
90 135
91 stats.gaming = GetAssessmentScore(results, WINSAT_ASSESSMENT_D3D); 136 UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.OverallScore",
92 if (stats.gaming == 0.0) 137 stats.overall, 0.0, 50.0, 50);
93 LOG(ERROR) << "Get gaming score failed"; 138 UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.GraphicsScore",
139 stats.graphics, 0.0, 50.0, 50);
140 UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.GamingScore",
141 stats.gaming, 0.0, 50.0, 50);
94 142
95 stats.graphics = GetAssessmentScore(results, WINSAT_ASSESSMENT_GRAPHICS); 143 UMA_HISTOGRAM_TIMES("GPU.WinSAT.ReadResultsFileTime",
96 if (stats.graphics == 0.0) 144 base::TimeTicks::Now() - start_time);
97 LOG(ERROR) << "Get graphics score failed";
98 145
99 return stats; 146 return stats;
100 } 147 }
101 148
102 } // namespace anonymous 149 } // namespace anonymous
103 150
104 namespace gpu_info_collector { 151 namespace gpu_info_collector {
105 152
106 bool CollectGraphicsInfo(content::GPUInfo* gpu_info) { 153 bool CollectGraphicsInfo(content::GPUInfo* gpu_info) {
107 DCHECK(gpu_info); 154 DCHECK(gpu_info);
108 155
109 gpu_info->performance_stats = RetrieveGpuPerformanceStats(); 156 content::GpuPerformanceStats stats = RetrieveGpuPerformanceStats();
157 UMA_HISTOGRAM_BOOLEAN(
158 "GPU.WinSAT.HasResults",
159 stats.overall != 0.0 && stats.graphics != 0.0 && stats.gaming != 0.0);
160 gpu_info->performance_stats = stats;
110 161
111 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) { 162 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) {
112 std::string requested_implementation_name = 163 std::string requested_implementation_name =
113 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL); 164 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL);
114 if (requested_implementation_name == "swiftshader") { 165 if (requested_implementation_name == "swiftshader") {
115 gpu_info->software_rendering = true; 166 gpu_info->software_rendering = true;
116 return false; 167 return false;
117 } 168 }
118 } 169 }
119 170
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 362
312 size_t pos = gl_version_string.find_last_not_of("0123456789."); 363 size_t pos = gl_version_string.find_last_not_of("0123456789.");
313 if (pos != std::string::npos && pos < gl_version_string.length() - 1) { 364 if (pos != std::string::npos && pos < gl_version_string.length() - 1) {
314 gpu_info->driver_version = gl_version_string.substr(pos + 1); 365 gpu_info->driver_version = gl_version_string.substr(pos + 1);
315 return true; 366 return true;
316 } 367 }
317 return false; 368 return false;
318 } 369 }
319 370
320 } // namespace gpu_info_collector 371 } // namespace gpu_info_collector
OLDNEW
« no previous file with comments | « content/gpu/DEPS ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698