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

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

Issue 15745014: Move GPU device/driver info related code from content to gpu. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: rebase Created 7 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/gpu_info_collector_unittest.cc ('k') | content/gpu/gpu_info_collector_x11.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 "content/gpu/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>
11 #include <d3d9.h>
12 #include <d3d11.h>
13 #include <dxgi.h>
14 #include <setupapi.h>
15
16 #include "base/command_line.h"
17 #include "base/debug/trace_event.h"
18 #include "base/file_util.h"
19 #include "base/files/file_path.h"
20 #include "base/logging.h"
21 #include "base/message_loop.h"
22 #include "base/metrics/histogram.h"
23 #include "base/scoped_native_library.h"
24 #include "base/string_number_conversions.h"
25 #include "base/string_util.h"
26 #include "base/string16.h"
27 #include "base/stringprintf.h"
28 #include "base/threading/thread.h"
29 #include "base/threading/worker_pool.h"
30 #include "base/win/registry.h"
31 #include "base/win/scoped_com_initializer.h"
32 #include "base/win/scoped_comptr.h"
33 #include "base/win/windows_version.h"
34 #include "third_party/libxml/chromium/libxml_utils.h"
35 #include "ui/gl/gl_implementation.h"
36 #include "ui/gl/gl_surface_egl.h"
37
38 namespace {
39
40 // This must be kept in sync with histograms.xml.
41 enum DisplayLinkInstallationStatus {
42 DISPLAY_LINK_NOT_INSTALLED,
43 DISPLAY_LINK_7_1_OR_EARLIER,
44 DISPLAY_LINK_7_2_OR_LATER,
45 DISPLAY_LINK_INSTALLATION_STATUS_MAX
46 };
47
48 float ReadXMLFloatValue(XmlReader* reader) {
49 std::string score_string;
50 if (!reader->ReadElementContent(&score_string))
51 return 0.0;
52
53 double score;
54 if (!base::StringToDouble(score_string, &score))
55 return 0.0;
56
57 return static_cast<float>(score);
58 }
59
60 content::GpuPerformanceStats RetrieveGpuPerformanceStats() {
61 TRACE_EVENT0("gpu", "RetrieveGpuPerformanceStats");
62
63 // If the user re-runs the assessment without restarting, the COM API
64 // returns WINSAT_ASSESSMENT_STATE_NOT_AVAILABLE. Because of that and
65 // http://crbug.com/124325, read the assessment result files directly.
66 content::GpuPerformanceStats stats;
67
68 // Get path to WinSAT results files.
69 wchar_t winsat_results_path[MAX_PATH];
70 DWORD size = ExpandEnvironmentStrings(
71 L"%WinDir%\\Performance\\WinSAT\\DataStore\\",
72 winsat_results_path, MAX_PATH);
73 if (size == 0 || size > MAX_PATH) {
74 LOG(ERROR) << "The path to the WinSAT results is too long: "
75 << size << " chars.";
76 return stats;
77 }
78
79 // Find most recent formal assessment results.
80 file_util::FileEnumerator file_enumerator(
81 base::FilePath(winsat_results_path),
82 false, // not recursive
83 file_util::FileEnumerator::FILES,
84 FILE_PATH_LITERAL("* * Formal.Assessment (*).WinSAT.xml"));
85
86 base::FilePath current_results;
87 for (base::FilePath results = file_enumerator.Next(); !results.empty();
88 results = file_enumerator.Next()) {
89 // The filenames start with the date and time as yyyy-mm-dd hh.mm.ss.xxx,
90 // so the greatest file lexicographically is also the most recent file.
91 if (base::FilePath::CompareLessIgnoreCase(current_results.value(),
92 results.value()))
93 current_results = results;
94 }
95
96 std::string current_results_string = current_results.MaybeAsASCII();
97 if (current_results_string.empty()) {
98 LOG(ERROR) << "Can't retrieve a valid WinSAT assessment.";
99 return stats;
100 }
101
102 // Get relevant scores from results file. XML schema at:
103 // http://msdn.microsoft.com/en-us/library/windows/desktop/aa969210.aspx
104 XmlReader reader;
105 if (!reader.LoadFile(current_results_string)) {
106 LOG(ERROR) << "Could not open WinSAT results file.";
107 return stats;
108 }
109 // Descend into <WinSAT> root element.
110 if (!reader.SkipToElement() || !reader.Read()) {
111 LOG(ERROR) << "Could not read WinSAT results file.";
112 return stats;
113 }
114
115 // Search for <WinSPR> element containing the results.
116 do {
117 if (reader.NodeName() == "WinSPR")
118 break;
119 } while (reader.Next());
120 // Descend into <WinSPR> element.
121 if (!reader.Read()) {
122 LOG(ERROR) << "Could not find WinSPR element in results file.";
123 return stats;
124 }
125
126 // Read scores.
127 for (int depth = reader.Depth(); reader.Depth() == depth; reader.Next()) {
128 std::string node_name = reader.NodeName();
129 if (node_name == "SystemScore")
130 stats.overall = ReadXMLFloatValue(&reader);
131 else if (node_name == "GraphicsScore")
132 stats.graphics = ReadXMLFloatValue(&reader);
133 else if (node_name == "GamingScore")
134 stats.gaming = ReadXMLFloatValue(&reader);
135 }
136
137 if (stats.overall == 0.0)
138 LOG(ERROR) << "Could not read overall score from assessment results.";
139 if (stats.graphics == 0.0)
140 LOG(ERROR) << "Could not read graphics score from assessment results.";
141 if (stats.gaming == 0.0)
142 LOG(ERROR) << "Could not read gaming score from assessment results.";
143
144 return stats;
145 }
146
147 content::GpuPerformanceStats RetrieveGpuPerformanceStatsWithHistograms() {
148 base::TimeTicks start_time = base::TimeTicks::Now();
149
150 content::GpuPerformanceStats stats = RetrieveGpuPerformanceStats();
151
152 UMA_HISTOGRAM_TIMES("GPU.WinSAT.ReadResultsFileTime",
153 base::TimeTicks::Now() - start_time);
154 UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.OverallScore2",
155 stats.overall * 10, 10, 200, 50);
156 UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.GraphicsScore2",
157 stats.graphics * 10, 10, 200, 50);
158 UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.GamingScore2",
159 stats.gaming * 10, 10, 200, 50);
160 UMA_HISTOGRAM_BOOLEAN(
161 "GPU.WinSAT.HasResults",
162 stats.overall != 0.0 && stats.graphics != 0.0 && stats.gaming != 0.0);
163
164 return stats;
165 }
166
167 // Returns the display link driver version or an invalid version if it is
168 // not installed.
169 Version DisplayLinkVersion() {
170 base::win::RegKey key;
171
172 if (key.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE", KEY_READ | KEY_WOW64_64KEY))
173 return Version();
174
175 if (key.OpenKey(L"DisplayLink", KEY_READ | KEY_WOW64_64KEY))
176 return Version();
177
178 if (key.OpenKey(L"Core", KEY_READ | KEY_WOW64_64KEY))
179 return Version();
180
181 string16 version;
182 if (key.ReadValue(L"Version", &version))
183 return Version();
184
185 return Version(WideToASCII(version));
186 }
187
188 // Returns whether Lenovo dCute is installed.
189 bool IsLenovoDCuteInstalled() {
190 base::win::RegKey key;
191
192 if (key.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE", KEY_READ | KEY_WOW64_64KEY))
193 return false;
194
195 if (key.OpenKey(L"Lenovo", KEY_READ | KEY_WOW64_64KEY))
196 return false;
197
198 if (key.OpenKey(L"Lenovo dCute", KEY_READ | KEY_WOW64_64KEY))
199 return false;
200
201 return true;
202 }
203
204 // 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.
206 bool D3D11ShouldWork(const content::GPUInfo& gpu_info) {
207 // Windows XP never supports D3D11.
208 if (base::win::GetVersion() <= base::win::VERSION_XP)
209 return false;
210
211 // Intel?
212 if (gpu_info.gpu.vendor_id == 0x8086) {
213 // 2nd Generation Core Processor Family Integrated Graphics Controller
214 // or Intel Ivy Bridge?
215 if (gpu_info.gpu.device_id == 0x0102 ||
216 gpu_info.gpu.device_id == 0x0106 ||
217 gpu_info.gpu.device_id == 0x0116 ||
218 gpu_info.gpu.device_id == 0x0126 ||
219 gpu_info.gpu.device_id == 0x0152 ||
220 gpu_info.gpu.device_id == 0x0156 ||
221 gpu_info.gpu.device_id == 0x015a ||
222 gpu_info.gpu.device_id == 0x0162 ||
223 gpu_info.gpu.device_id == 0x0166) {
224 // http://crbug.com/196373.
225 if (base::win::GetVersion() == base::win::VERSION_VISTA)
226 return false;
227
228 // http://crbug.com/175525.
229 if (gpu_info.display_link_version.IsValid())
230 return false;
231 }
232 }
233
234 return true;
235 }
236
237 // Collects information about the level of D3D11 support and records it in
238 // the UMA stats. Records no stats when D3D11 in not supported at all.
239 void CollectD3D11SupportOnWorkerThread() {
240 TRACE_EVENT0("gpu", "CollectD3D11Support");
241
242 typedef HRESULT (WINAPI *D3D11CreateDeviceFunc)(
243 IDXGIAdapter* adapter,
244 D3D_DRIVER_TYPE driver_type,
245 HMODULE software,
246 UINT flags,
247 const D3D_FEATURE_LEVEL* feature_levels,
248 UINT num_feature_levels,
249 UINT sdk_version,
250 ID3D11Device** device,
251 D3D_FEATURE_LEVEL* feature_level,
252 ID3D11DeviceContext** immediate_context);
253
254 // This enumeration must be kept in sync with histograms.xml. Do not reorder
255 // the members; always add to the end.
256 enum FeatureLevel {
257 FEATURE_LEVEL_UNKNOWN,
258 FEATURE_LEVEL_NO_D3D11_DLL,
259 FEATURE_LEVEL_NO_CREATE_DEVICE_ENTRY_POINT,
260 FEATURE_LEVEL_DEVICE_CREATION_FAILED,
261 FEATURE_LEVEL_9_1,
262 FEATURE_LEVEL_9_2,
263 FEATURE_LEVEL_9_3,
264 FEATURE_LEVEL_10_0,
265 FEATURE_LEVEL_10_1,
266 FEATURE_LEVEL_11_0,
267 NUM_FEATURE_LEVELS
268 };
269
270 FeatureLevel feature_level = FEATURE_LEVEL_UNKNOWN;
271 UINT bgra_support = 0;
272
273 // This module is leaked in case it is hooked by third party software.
274 base::NativeLibrary d3d11_module = base::LoadNativeLibrary(
275 base::FilePath(L"d3d11.dll"),
276 NULL);
277
278 if (!d3d11_module) {
279 feature_level = FEATURE_LEVEL_NO_D3D11_DLL;
280 } else {
281 D3D11CreateDeviceFunc create_func =
282 reinterpret_cast<D3D11CreateDeviceFunc>(
283 base::GetFunctionPointerFromNativeLibrary(d3d11_module,
284 "D3D11CreateDevice"));
285 if (!create_func) {
286 feature_level = FEATURE_LEVEL_NO_CREATE_DEVICE_ENTRY_POINT;
287 } else {
288 static const D3D_FEATURE_LEVEL d3d_feature_levels[] = {
289 D3D_FEATURE_LEVEL_11_0,
290 D3D_FEATURE_LEVEL_10_1,
291 D3D_FEATURE_LEVEL_10_0,
292 D3D_FEATURE_LEVEL_9_3,
293 D3D_FEATURE_LEVEL_9_2,
294 D3D_FEATURE_LEVEL_9_1
295 };
296
297 base::win::ScopedComPtr<ID3D11Device> device;
298 D3D_FEATURE_LEVEL d3d_feature_level;
299 base::win::ScopedComPtr<ID3D11DeviceContext> device_context;
300 HRESULT hr = create_func(NULL,
301 D3D_DRIVER_TYPE_HARDWARE,
302 NULL,
303 0,
304 d3d_feature_levels,
305 arraysize(d3d_feature_levels),
306 D3D11_SDK_VERSION,
307 device.Receive(),
308 &d3d_feature_level,
309 device_context.Receive());
310 if (FAILED(hr)) {
311 feature_level = FEATURE_LEVEL_DEVICE_CREATION_FAILED;
312 } else {
313 switch (d3d_feature_level) {
314 case D3D_FEATURE_LEVEL_11_0:
315 feature_level = FEATURE_LEVEL_11_0;
316 break;
317 case D3D_FEATURE_LEVEL_10_1:
318 feature_level = FEATURE_LEVEL_10_1;
319 break;
320 case D3D_FEATURE_LEVEL_10_0:
321 feature_level = FEATURE_LEVEL_10_0;
322 break;
323 case D3D_FEATURE_LEVEL_9_3:
324 feature_level = FEATURE_LEVEL_9_3;
325 break;
326 case D3D_FEATURE_LEVEL_9_2:
327 feature_level = FEATURE_LEVEL_9_2;
328 break;
329 case D3D_FEATURE_LEVEL_9_1:
330 feature_level = FEATURE_LEVEL_9_1;
331 break;
332 default:
333 NOTREACHED();
334 break;
335 }
336
337 hr = device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM,
338 &bgra_support);
339 DCHECK(SUCCEEDED(hr));
340 }
341 }
342 }
343
344 UMA_HISTOGRAM_ENUMERATION("GPU.D3D11_FeatureLevel",
345 feature_level,
346 NUM_FEATURE_LEVELS);
347
348 // ANGLE requires at least feature level 10.0. Do not record any further
349 // stats if ANGLE would not work anyway.
350 if (feature_level < FEATURE_LEVEL_10_0)
351 return;
352
353 UMA_HISTOGRAM_BOOLEAN(
354 "GPU.D3D11_B8G8R8A8_Texture2DSupport",
355 (bgra_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0);
356 UMA_HISTOGRAM_BOOLEAN(
357 "GPU.D3D11_B8G8R8A8_RenderTargetSupport",
358 (bgra_support & D3D11_FORMAT_SUPPORT_RENDER_TARGET) != 0);
359 }
360
361 // Collects information about the level of D3D11 support and records it in
362 // the UMA stats. Records no stats when D3D11 in not supported at all.
363 void CollectD3D11Support() {
364 // D3D11 takes about 50ms to initialize so do this on a worker thread.
365 base::WorkerPool::PostTask(
366 FROM_HERE,
367 base::Bind(CollectD3D11SupportOnWorkerThread),
368 false);
369 }
370 } // namespace anonymous
371
372 namespace gpu_info_collector {
373
374 #if !defined(GOOGLE_CHROME_BUILD)
375 AMDVideoCardType GetAMDVideocardType() {
376 return STANDALONE;
377 }
378 #else
379 // This function has a real implementation for official builds that can
380 // be found in src/third_party/amd.
381 AMDVideoCardType GetAMDVideocardType();
382 #endif
383
384 bool CollectDriverInfoD3D(const std::wstring& device_id,
385 content::GPUInfo* gpu_info) {
386 TRACE_EVENT0("gpu", "CollectDriverInfoD3D");
387
388 // create device info for the display device
389 HDEVINFO device_info = SetupDiGetClassDevsW(
390 NULL, device_id.c_str(), NULL,
391 DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
392 if (device_info == INVALID_HANDLE_VALUE) {
393 LOG(ERROR) << "Creating device info failed";
394 return false;
395 }
396
397 DWORD index = 0;
398 bool found = false;
399 SP_DEVINFO_DATA device_info_data;
400 device_info_data.cbSize = sizeof(device_info_data);
401 while (SetupDiEnumDeviceInfo(device_info, index++, &device_info_data)) {
402 WCHAR value[255];
403 if (SetupDiGetDeviceRegistryPropertyW(device_info,
404 &device_info_data,
405 SPDRP_DRIVER,
406 NULL,
407 reinterpret_cast<PBYTE>(value),
408 sizeof(value),
409 NULL)) {
410 HKEY key;
411 std::wstring driver_key = L"System\\CurrentControlSet\\Control\\Class\\";
412 driver_key += value;
413 LONG result = RegOpenKeyExW(
414 HKEY_LOCAL_MACHINE, driver_key.c_str(), 0, KEY_QUERY_VALUE, &key);
415 if (result == ERROR_SUCCESS) {
416 DWORD dwcb_data = sizeof(value);
417 std::string driver_version;
418 result = RegQueryValueExW(
419 key, L"DriverVersion", NULL, NULL,
420 reinterpret_cast<LPBYTE>(value), &dwcb_data);
421 if (result == ERROR_SUCCESS)
422 driver_version = WideToASCII(std::wstring(value));
423
424 std::string driver_date;
425 dwcb_data = sizeof(value);
426 result = RegQueryValueExW(
427 key, L"DriverDate", NULL, NULL,
428 reinterpret_cast<LPBYTE>(value), &dwcb_data);
429 if (result == ERROR_SUCCESS)
430 driver_date = WideToASCII(std::wstring(value));
431
432 std::string driver_vendor;
433 dwcb_data = sizeof(value);
434 result = RegQueryValueExW(
435 key, L"ProviderName", NULL, NULL,
436 reinterpret_cast<LPBYTE>(value), &dwcb_data);
437 if (result == ERROR_SUCCESS) {
438 driver_vendor = WideToASCII(std::wstring(value));
439 if (driver_vendor == "Advanced Micro Devices, Inc." ||
440 driver_vendor == "ATI Technologies Inc.") {
441 // We are conservative and assume that in the absence of a clear
442 // signal the videocard is assumed to be switchable. Additionally,
443 // some switchable systems with Intel GPUs aren't correctly
444 // detected, so always count them.
445 AMDVideoCardType amd_card_type = GetAMDVideocardType();
446 gpu_info->amd_switchable = (gpu_info->gpu.vendor_id == 0x8086) ||
447 (amd_card_type != STANDALONE);
448 }
449 }
450
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);
456 break;
457 }
458 }
459 }
460 SetupDiDestroyDeviceInfoList(device_info);
461 return found;
462 }
463
464 bool CollectContextGraphicsInfo(content::GPUInfo* gpu_info) {
465 TRACE_EVENT0("gpu", "CollectGraphicsInfo");
466
467 DCHECK(gpu_info);
468
469 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) {
470 std::string requested_implementation_name =
471 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL);
472 if (requested_implementation_name == "swiftshader") {
473 gpu_info->software_rendering = true;
474 return false;
475 }
476 }
477
478 if (!CollectGraphicsInfoGL(gpu_info))
479 return false;
480
481 // ANGLE's renderer strings are of the form:
482 // ANGLE (<adapter_identifier> Direct3D<version> vs_x_x ps_x_x)
483 std::string direct3d_version;
484 int vertex_shader_major_version = 0;
485 int vertex_shader_minor_version = 0;
486 int pixel_shader_major_version = 0;
487 int pixel_shader_minor_version = 0;
488 if (RE2::FullMatch(gpu_info->gl_renderer,
489 "ANGLE \\(.*\\)") &&
490 RE2::PartialMatch(gpu_info->gl_renderer,
491 " Direct3D(\\w+)",
492 &direct3d_version) &&
493 RE2::PartialMatch(gpu_info->gl_renderer,
494 " vs_(\\d+)_(\\d+)",
495 &vertex_shader_major_version,
496 &vertex_shader_minor_version) &&
497 RE2::PartialMatch(gpu_info->gl_renderer,
498 " ps_(\\d+)_(\\d+)",
499 &pixel_shader_major_version,
500 &pixel_shader_minor_version)) {
501 gpu_info->can_lose_context = direct3d_version == "9";
502 gpu_info->vertex_shader_version =
503 base::StringPrintf("%d.%d",
504 vertex_shader_major_version,
505 vertex_shader_minor_version);
506 gpu_info->pixel_shader_version =
507 base::StringPrintf("%d.%d",
508 pixel_shader_major_version,
509 pixel_shader_minor_version);
510
511 // DirectX diagnostics are collected asynchronously because it takes a
512 // couple of seconds. Do not mark gpu_info as complete until that is done.
513 gpu_info->finalized = false;
514 } else {
515 gpu_info->finalized = true;
516 }
517
518 return true;
519 }
520
521 GpuIDResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
522 DCHECK(vendor_id && device_id);
523 *vendor_id = 0;
524 *device_id = 0;
525
526 // Taken from http://developer.nvidia.com/object/device_ids.html
527 DISPLAY_DEVICE dd;
528 dd.cb = sizeof(DISPLAY_DEVICE);
529 std::wstring id;
530 for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) {
531 if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
532 id = dd.DeviceID;
533 break;
534 }
535 }
536
537 if (id.length() > 20) {
538 int vendor = 0, device = 0;
539 std::wstring vendor_string = id.substr(8, 4);
540 std::wstring device_string = id.substr(17, 4);
541 base::HexStringToInt(WideToASCII(vendor_string), &vendor);
542 base::HexStringToInt(WideToASCII(device_string), &device);
543 *vendor_id = vendor;
544 *device_id = device;
545 return kGpuIDSuccess;
546 }
547 return kGpuIDFailure;
548 }
549
550 bool CollectBasicGraphicsInfo(content::GPUInfo* gpu_info) {
551 TRACE_EVENT0("gpu", "CollectPreliminaryGraphicsInfo");
552
553 DCHECK(gpu_info);
554
555 gpu_info->performance_stats = RetrieveGpuPerformanceStatsWithHistograms();
556
557 // nvd3d9wrap.dll is loaded into all processes when Optimus is enabled.
558 HMODULE nvd3d9wrap = GetModuleHandleW(L"nvd3d9wrap.dll");
559 gpu_info->optimus = nvd3d9wrap != NULL;
560
561 gpu_info->lenovo_dcute = IsLenovoDCuteInstalled();
562
563 gpu_info->display_link_version = DisplayLinkVersion();
564
565 if (!gpu_info->display_link_version .IsValid()) {
566 UMA_HISTOGRAM_ENUMERATION("GPU.DisplayLinkInstallationStatus",
567 DISPLAY_LINK_NOT_INSTALLED,
568 DISPLAY_LINK_INSTALLATION_STATUS_MAX);
569 } else if (gpu_info->display_link_version.IsOlderThan("7.2")) {
570 UMA_HISTOGRAM_ENUMERATION("GPU.DisplayLinkInstallationStatus",
571 DISPLAY_LINK_7_1_OR_EARLIER,
572 DISPLAY_LINK_INSTALLATION_STATUS_MAX);
573 } else {
574 UMA_HISTOGRAM_ENUMERATION("GPU.DisplayLinkInstallationStatus",
575 DISPLAY_LINK_7_2_OR_LATER,
576 DISPLAY_LINK_INSTALLATION_STATUS_MAX);
577 }
578
579 // Taken from http://developer.nvidia.com/object/device_ids.html
580 DISPLAY_DEVICE dd;
581 dd.cb = sizeof(DISPLAY_DEVICE);
582 std::wstring id;
583 for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) {
584 if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
585 id = dd.DeviceID;
586 break;
587 }
588 }
589
590 if (id.length() <= 20)
591 return false;
592
593 int vendor_id = 0, device_id = 0;
594 string16 vendor_id_string = id.substr(8, 4);
595 string16 device_id_string = id.substr(17, 4);
596 base::HexStringToInt(WideToASCII(vendor_id_string), &vendor_id);
597 base::HexStringToInt(WideToASCII(device_id_string), &device_id);
598 gpu_info->gpu.vendor_id = vendor_id;
599 gpu_info->gpu.device_id = device_id;
600 // TODO(zmo): we only need to call CollectDriverInfoD3D() if we use ANGLE.
601 if (!CollectDriverInfoD3D(id, gpu_info))
602 return false;
603
604 // Collect basic information about supported D3D11 features. Delay for 45
605 // seconds so as not to regress performance tests.
606 if (D3D11ShouldWork(*gpu_info)) {
607 base::MessageLoop::current()->PostDelayedTask(
608 FROM_HERE,
609 base::Bind(&CollectD3D11Support),
610 base::TimeDelta::FromSeconds(45));
611 }
612
613 return true;
614 }
615
616 bool CollectDriverInfoGL(content::GPUInfo* gpu_info) {
617 TRACE_EVENT0("gpu", "CollectDriverInfoGL");
618
619 if (!gpu_info->driver_version.empty())
620 return true;
621
622 std::string gl_version_string = gpu_info->gl_version_string;
623
624 return RE2::PartialMatch(gl_version_string,
625 "([\\d\\.]+)$",
626 &gpu_info->driver_version);
627 }
628
629 void MergeGPUInfo(content::GPUInfo* basic_gpu_info,
630 const content::GPUInfo& context_gpu_info) {
631 DCHECK(basic_gpu_info);
632
633 if (context_gpu_info.software_rendering) {
634 basic_gpu_info->software_rendering = true;
635 return;
636 }
637
638 MergeGPUInfoGL(basic_gpu_info, context_gpu_info);
639
640 basic_gpu_info->dx_diagnostics = context_gpu_info.dx_diagnostics;
641 }
642
643 } // namespace gpu_info_collector
OLDNEW
« no previous file with comments | « content/gpu/gpu_info_collector_unittest.cc ('k') | content/gpu/gpu_info_collector_x11.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698