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