1 // Copyright (c) 2013 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 "content/browser/gpu/gpu_data_manager_impl_private.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/metrics/field_trial.h"
11 #include "base/metrics/histogram.h"
12 #include "base/metrics/sparse_histogram.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/sys_info.h"
16 #include "base/trace_event/trace_event.h"
17 #include "base/version.h"
18 #include "cc/base/switches.h"
19 #include "content/browser/gpu/gpu_process_host.h"
20 #include "content/common/gpu/gpu_messages.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/gpu_data_manager_observer.h"
23 #include "content/public/common/content_client.h"
24 #include "content/public/common/content_constants.h"
25 #include "content/public/common/content_switches.h"
26 #include "content/public/common/web_preferences.h"
27 #include "gpu/command_buffer/service/gpu_switches.h"
28 #include "gpu/config/gpu_control_list_jsons.h"
29 #include "gpu/config/gpu_driver_bug_workaround_type.h"
30 #include "gpu/config/gpu_feature_type.h"
31 #include "gpu/config/gpu_info_collector.h"
32 #include "gpu/config/gpu_switches.h"
33 #include "gpu/config/gpu_util.h"
34 #include "ui/base/ui_base_switches.h"
35 #include "ui/gl/gl_implementation.h"
36 #include "ui/gl/gl_switches.h"
37 #include "ui/gl/gpu_switching_manager.h"
39 #if defined(OS_MACOSX)
40 #include <ApplicationServices/ApplicationServices.h>
43 #include "base/win/windows_version.h"
45 #if defined(OS_ANDROID)
46 #include "ui/gfx/android/device_display_info.h"
53 enum GpuFeatureStatus
{
54 kGpuFeatureEnabled
= 0,
55 kGpuFeatureBlacklisted
= 1,
56 kGpuFeatureDisabled
= 2, // disabled by user but not blacklisted
71 int GetGpuBlacklistHistogramValueWin(GpuFeatureStatus status
) {
72 static WinSubVersion sub_version
= kNumWinSubVersions
;
73 if (sub_version
== kNumWinSubVersions
) {
74 sub_version
= kWinOthers
;
75 std::string version_str
= base::SysInfo::OperatingSystemVersion();
76 size_t pos
= version_str
.find_first_not_of("0123456789.");
77 if (pos
!= std::string::npos
)
78 version_str
= version_str
.substr(0, pos
);
79 Version
os_version(version_str
);
80 if (os_version
.IsValid() && os_version
.components().size() >= 2) {
81 const std::vector
<uint32_t>& version_numbers
= os_version
.components();
82 if (version_numbers
[0] == 5)
84 else if (version_numbers
[0] == 6 && version_numbers
[1] == 0)
85 sub_version
= kWinVista
;
86 else if (version_numbers
[0] == 6 && version_numbers
[1] == 1)
88 else if (version_numbers
[0] == 6 && version_numbers
[1] == 2)
92 int entry_index
= static_cast<int>(sub_version
) * kGpuFeatureNumStatus
;
94 case kGpuFeatureEnabled
:
96 case kGpuFeatureBlacklisted
:
99 case kGpuFeatureDisabled
:
107 // Send UMA histograms about the enabled features and GPU properties.
108 void UpdateStats(const gpu::GPUInfo
& gpu_info
,
109 const gpu::GpuBlacklist
* blacklist
,
110 const std::set
<int>& blacklisted_features
) {
111 uint32 max_entry_id
= blacklist
->max_entry_id();
112 if (max_entry_id
== 0) {
113 // GPU Blacklist was not loaded. No need to go further.
117 const base::CommandLine
& command_line
=
118 *base::CommandLine::ForCurrentProcess();
119 bool disabled
= false;
121 // Use entry 0 to capture the total number of times that data
122 // was recorded in this histogram in order to have a convenient
123 // denominator to compute blacklist percentages for the rest of the
125 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry",
126 0, max_entry_id
+ 1);
128 if (blacklisted_features
.size() != 0) {
129 std::vector
<uint32
> flag_entries
;
130 blacklist
->GetDecisionEntries(&flag_entries
, disabled
);
131 DCHECK_GT(flag_entries
.size(), 0u);
132 for (size_t i
= 0; i
< flag_entries
.size(); ++i
) {
133 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry",
134 flag_entries
[i
], max_entry_id
+ 1);
138 // This counts how many users are affected by a disabled entry - this allows
139 // us to understand the impact of an entry before enable it.
140 std::vector
<uint32
> flag_disabled_entries
;
142 blacklist
->GetDecisionEntries(&flag_disabled_entries
, disabled
);
143 for (uint32 disabled_entry
: flag_disabled_entries
) {
144 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerDisabledEntry",
145 disabled_entry
, max_entry_id
+ 1);
148 const gpu::GpuFeatureType kGpuFeatures
[] = {
149 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS
,
150 gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING
, gpu::GPU_FEATURE_TYPE_WEBGL
};
151 const std::string kGpuBlacklistFeatureHistogramNames
[] = {
152 "GPU.BlacklistFeatureTestResults.Accelerated2dCanvas",
153 "GPU.BlacklistFeatureTestResults.GpuCompositing",
154 "GPU.BlacklistFeatureTestResults.Webgl", };
155 const bool kGpuFeatureUserFlags
[] = {
156 command_line
.HasSwitch(switches::kDisableAccelerated2dCanvas
),
157 command_line
.HasSwitch(switches::kDisableGpu
),
158 command_line
.HasSwitch(switches::kDisableExperimentalWebGL
), };
160 const std::string kGpuBlacklistFeatureHistogramNamesWin
[] = {
161 "GPU.BlacklistFeatureTestResultsWindows.Accelerated2dCanvas",
162 "GPU.BlacklistFeatureTestResultsWindows.GpuCompositing",
163 "GPU.BlacklistFeatureTestResultsWindows.Webgl", };
165 const size_t kNumFeatures
=
166 sizeof(kGpuFeatures
) / sizeof(gpu::GpuFeatureType
);
167 for (size_t i
= 0; i
< kNumFeatures
; ++i
) {
168 // We can't use UMA_HISTOGRAM_ENUMERATION here because the same name is
169 // expected if the macro is used within a loop.
170 GpuFeatureStatus value
= kGpuFeatureEnabled
;
171 if (blacklisted_features
.count(kGpuFeatures
[i
]))
172 value
= kGpuFeatureBlacklisted
;
173 else if (kGpuFeatureUserFlags
[i
])
174 value
= kGpuFeatureDisabled
;
175 base::HistogramBase
* histogram_pointer
= base::LinearHistogram::FactoryGet(
176 kGpuBlacklistFeatureHistogramNames
[i
],
177 1, kGpuFeatureNumStatus
, kGpuFeatureNumStatus
+ 1,
178 base::HistogramBase::kUmaTargetedHistogramFlag
);
179 histogram_pointer
->Add(value
);
181 histogram_pointer
= base::LinearHistogram::FactoryGet(
182 kGpuBlacklistFeatureHistogramNamesWin
[i
],
183 1, kNumWinSubVersions
* kGpuFeatureNumStatus
,
184 kNumWinSubVersions
* kGpuFeatureNumStatus
+ 1,
185 base::HistogramBase::kUmaTargetedHistogramFlag
);
186 histogram_pointer
->Add(GetGpuBlacklistHistogramValueWin(value
));
190 UMA_HISTOGRAM_SPARSE_SLOWLY("GPU.GLResetNotificationStrategy",
191 gpu_info
.gl_reset_notification_strategy
);
194 // Combine the integers into a string, seperated by ','.
195 std::string
IntSetToString(const std::set
<int>& list
) {
197 for (std::set
<int>::const_iterator it
= list
.begin();
198 it
!= list
.end(); ++it
) {
201 rt
+= base::IntToString(*it
);
206 #if defined(OS_MACOSX)
207 void DisplayReconfigCallback(CGDirectDisplayID display
,
208 CGDisplayChangeSummaryFlags flags
,
209 void* gpu_data_manager
) {
210 if (flags
== kCGDisplayBeginConfigurationFlag
)
211 return; // This call contains no information about the display change
213 GpuDataManagerImpl
* manager
=
214 reinterpret_cast<GpuDataManagerImpl
*>(gpu_data_manager
);
218 bool display_changed
= false;
219 uint32_t displayCount
;
220 CGGetActiveDisplayList(0, NULL
, &displayCount
);
221 if (displayCount
!= manager
->GetDisplayCount()) {
222 manager
->SetDisplayCount(displayCount
);
223 display_changed
= true;
227 bool gpu_changed
= false;
228 if (flags
& kCGDisplayAddFlag
) {
229 uint32 vendor_id
, device_id
;
230 if (gpu::CollectGpuID(&vendor_id
, &device_id
) == gpu::kCollectInfoSuccess
) {
231 gpu_changed
= manager
->UpdateActiveGpu(vendor_id
, device_id
);
235 if (display_changed
|| gpu_changed
)
236 manager
->HandleGpuSwitch();
240 // Block all domains' use of 3D APIs for this many milliseconds if
241 // approaching a threshold where system stability might be compromised.
242 const int64 kBlockAllDomainsMs
= 10000;
243 const int kNumResetsWithinDuration
= 1;
245 // Enums for UMA histograms.
246 enum BlockStatusHistogram
{
247 BLOCK_STATUS_NOT_BLOCKED
,
248 BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED
,
249 BLOCK_STATUS_ALL_DOMAINS_BLOCKED
,
253 } // namespace anonymous
255 void GpuDataManagerImplPrivate::InitializeForTesting(
256 const std::string
& gpu_blacklist_json
,
257 const gpu::GPUInfo
& gpu_info
) {
258 // This function is for testing only, so disable histograms.
259 update_histograms_
= false;
261 // Prevent all further initialization.
264 InitializeImpl(gpu_blacklist_json
, std::string(), gpu_info
);
267 bool GpuDataManagerImplPrivate::IsFeatureBlacklisted(int feature
) const {
268 #if defined(OS_CHROMEOS)
269 if (feature
== gpu::GPU_FEATURE_TYPE_PANEL_FITTING
&&
270 base::CommandLine::ForCurrentProcess()->HasSwitch(
271 switches::kDisablePanelFitting
)) {
274 #endif // OS_CHROMEOS
275 if (use_swiftshader_
|| ShouldUseWarp()) {
276 // Skia's software rendering is probably more efficient than going through
277 // software emulation of the GPU, so use that.
278 if (feature
== gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS
)
283 return (blacklisted_features_
.count(feature
) == 1);
286 bool GpuDataManagerImplPrivate::IsDriverBugWorkaroundActive(int feature
) const {
287 return (gpu_driver_bugs_
.count(feature
) == 1);
290 size_t GpuDataManagerImplPrivate::GetBlacklistedFeatureCount() const {
291 if (use_swiftshader_
|| ShouldUseWarp())
293 return blacklisted_features_
.size();
296 void GpuDataManagerImplPrivate::SetDisplayCount(unsigned int display_count
) {
297 display_count_
= display_count
;
300 unsigned int GpuDataManagerImplPrivate::GetDisplayCount() const {
301 return display_count_
;
304 gpu::GPUInfo
GpuDataManagerImplPrivate::GetGPUInfo() const {
308 void GpuDataManagerImplPrivate::GetGpuProcessHandles(
309 const GpuDataManager::GetGpuProcessHandlesCallback
& callback
) const {
310 GpuProcessHost::GetProcessHandles(callback
);
313 bool GpuDataManagerImplPrivate::GpuAccessAllowed(
314 std::string
* reason
) const {
315 if (use_swiftshader_
|| ShouldUseWarp())
318 if (!gpu_process_accessible_
) {
320 *reason
= "GPU process launch failed.";
325 if (card_blacklisted_
) {
327 *reason
= "GPU access is disabled ";
328 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
329 if (command_line
->HasSwitch(switches::kDisableGpu
))
330 *reason
+= "through commandline switch --disable-gpu.";
332 *reason
+= "in chrome://settings.";
337 // We only need to block GPU process if more features are disallowed other
338 // than those in the preliminary gpu feature flags because the latter work
339 // through renderer commandline switches.
340 std::set
<int> features
= preliminary_blacklisted_features_
;
341 gpu::MergeFeatureSets(&features
, blacklisted_features_
);
342 if (features
.size() > preliminary_blacklisted_features_
.size()) {
344 *reason
= "Features are disabled upon full but not preliminary GPU info.";
349 if (blacklisted_features_
.size() == gpu::NUMBER_OF_GPU_FEATURE_TYPES
) {
350 // On Linux, we use cached GL strings to make blacklist decsions at browser
351 // startup time. We need to launch the GPU process to validate these
352 // strings even if all features are blacklisted. If all GPU features are
353 // disabled, the GPU process will only initialize GL bindings, create a GL
354 // context, and collect full GPU info.
355 #if !defined(OS_LINUX)
357 *reason
= "All GPU features are blacklisted.";
366 void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
367 if (complete_gpu_info_already_requested_
|| IsCompleteGpuInfoAvailable())
369 complete_gpu_info_already_requested_
= true;
371 GpuProcessHost::SendOnIO(
373 GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED
,
375 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED
,
377 CAUSE_FOR_GPU_LAUNCH_GPUDATAMANAGER_REQUESTCOMPLETEGPUINFOIFNEEDED
,
378 new GpuMsg_CollectGraphicsInfo());
381 bool GpuDataManagerImplPrivate::IsEssentialGpuInfoAvailable() const {
382 if (gpu_info_
.basic_info_state
== gpu::kCollectInfoNone
||
383 gpu_info_
.context_info_state
== gpu::kCollectInfoNone
) {
389 bool GpuDataManagerImplPrivate::IsCompleteGpuInfoAvailable() const {
391 if (gpu_info_
.dx_diagnostics_info_state
== gpu::kCollectInfoNone
)
394 return IsEssentialGpuInfoAvailable();
397 void GpuDataManagerImplPrivate::RequestVideoMemoryUsageStatsUpdate() const {
398 GpuProcessHost::SendOnIO(
399 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED
,
400 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH
,
401 new GpuMsg_GetVideoMemoryUsageStats());
404 bool GpuDataManagerImplPrivate::ShouldUseSwiftShader() const {
405 return use_swiftshader_
;
408 void GpuDataManagerImplPrivate::RegisterSwiftShaderPath(
409 const base::FilePath
& path
) {
410 swiftshader_path_
= path
;
411 EnableSwiftShaderIfNecessary();
414 bool GpuDataManagerImplPrivate::ShouldUseWarp() const {
415 std::string angle_impl_flag
=
416 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
417 switches::kUseANGLE
);
418 return use_warp_
|| angle_impl_flag
== gfx::kANGLEImplementationWARPName
;
421 void GpuDataManagerImplPrivate::AddObserver(GpuDataManagerObserver
* observer
) {
422 GpuDataManagerImpl::UnlockedSession
session(owner_
);
423 observer_list_
->AddObserver(observer
);
426 void GpuDataManagerImplPrivate::RemoveObserver(
427 GpuDataManagerObserver
* observer
) {
428 GpuDataManagerImpl::UnlockedSession
session(owner_
);
429 observer_list_
->RemoveObserver(observer
);
432 void GpuDataManagerImplPrivate::UnblockDomainFrom3DAPIs(const GURL
& url
) {
433 // This method must do two things:
435 // 1. If the specific domain is blocked, then unblock it.
437 // 2. Reset our notion of how many GPU resets have occurred recently.
438 // This is necessary even if the specific domain was blocked.
439 // Otherwise, if we call Are3DAPIsBlocked with the same domain right
440 // after unblocking it, it will probably still be blocked because of
441 // the recent GPU reset caused by that domain.
443 // These policies could be refined, but at a certain point the behavior
444 // will become difficult to explain.
445 std::string domain
= GetDomainFromURL(url
);
447 blocked_domains_
.erase(domain
);
448 timestamps_of_gpu_resets_
.clear();
451 void GpuDataManagerImplPrivate::DisableGpuWatchdog() {
452 GpuProcessHost::SendOnIO(
453 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED
,
454 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH
,
455 new GpuMsg_DisableWatchdog
);
458 void GpuDataManagerImplPrivate::SetGLStrings(const std::string
& gl_vendor
,
459 const std::string
& gl_renderer
,
460 const std::string
& gl_version
) {
461 if (gl_vendor
.empty() && gl_renderer
.empty() && gl_version
.empty())
464 // If GPUInfo already got GL strings, do nothing. This is for the rare
465 // situation where GPU process collected GL strings before this call.
466 if (!gpu_info_
.gl_vendor
.empty() ||
467 !gpu_info_
.gl_renderer
.empty() ||
468 !gpu_info_
.gl_version
.empty())
471 gpu::GPUInfo gpu_info
= gpu_info_
;
473 gpu_info
.gl_vendor
= gl_vendor
;
474 gpu_info
.gl_renderer
= gl_renderer
;
475 gpu_info
.gl_version
= gl_version
;
477 gpu::CollectDriverInfoGL(&gpu_info
);
479 UpdateGpuInfo(gpu_info
);
480 UpdateGpuSwitchingManager(gpu_info
);
481 UpdatePreliminaryBlacklistedFeatures();
484 void GpuDataManagerImplPrivate::GetGLStrings(std::string
* gl_vendor
,
485 std::string
* gl_renderer
,
486 std::string
* gl_version
) {
487 DCHECK(gl_vendor
&& gl_renderer
&& gl_version
);
489 *gl_vendor
= gpu_info_
.gl_vendor
;
490 *gl_renderer
= gpu_info_
.gl_renderer
;
491 *gl_version
= gpu_info_
.gl_version
;
494 void GpuDataManagerImplPrivate::Initialize() {
495 TRACE_EVENT0("startup", "GpuDataManagerImpl::Initialize");
497 DVLOG(0) << "GpuDataManagerImpl marked as finalized; skipping Initialize";
501 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
502 if (command_line
->HasSwitch(switches::kSkipGpuDataLoading
))
505 gpu::GPUInfo gpu_info
;
506 if (command_line
->GetSwitchValueASCII(
507 switches::kUseGL
) == gfx::kGLImplementationOSMesaName
) {
508 // If using the OSMesa GL implementation, use fake vendor and device ids to
509 // make sure it never gets blacklisted. This is better than simply
510 // cancelling GPUInfo gathering as it allows us to proceed with loading the
511 // blacklist below which may have non-device specific entries we want to
512 // apply anyways (e.g., OS version blacklisting).
513 gpu_info
.gpu
.vendor_id
= 0xffff;
514 gpu_info
.gpu
.device_id
= 0xffff;
516 // Also declare the driver_vendor to be osmesa to be able to specify
517 // exceptions based on driver_vendor==osmesa for some blacklist rules.
518 gpu_info
.driver_vendor
= gfx::kGLImplementationOSMesaName
;
520 TRACE_EVENT0("startup",
521 "GpuDataManagerImpl::Initialize:CollectBasicGraphicsInfo");
522 gpu::CollectBasicGraphicsInfo(&gpu_info
);
524 #if defined(ARCH_CPU_X86_FAMILY)
525 if (!gpu_info
.gpu
.vendor_id
|| !gpu_info
.gpu
.device_id
) {
526 gpu_info
.context_info_state
= gpu::kCollectInfoNonFatalFailure
;
528 gpu_info
.dx_diagnostics_info_state
= gpu::kCollectInfoNonFatalFailure
;
531 #endif // ARCH_CPU_X86_FAMILY
533 std::string gpu_blacklist_string
;
534 std::string gpu_driver_bug_list_string
;
535 if (!command_line
->HasSwitch(switches::kIgnoreGpuBlacklist
) &&
536 !command_line
->HasSwitch(switches::kUseGpuInTests
)) {
537 gpu_blacklist_string
= gpu::kSoftwareRenderingListJson
;
539 if (!command_line
->HasSwitch(switches::kDisableGpuDriverBugWorkarounds
)) {
540 gpu_driver_bug_list_string
= gpu::kGpuDriverBugListJson
;
542 InitializeImpl(gpu_blacklist_string
,
543 gpu_driver_bug_list_string
,
546 if (command_line
->HasSwitch(switches::kSingleProcess
) ||
547 command_line
->HasSwitch(switches::kInProcessGPU
)) {
548 command_line
->AppendSwitch(switches::kDisableGpuWatchdog
);
549 AppendGpuCommandLine(command_line
);
553 void GpuDataManagerImplPrivate::UpdateGpuInfoHelper() {
554 GetContentClient()->SetGpuInfo(gpu_info_
);
556 if (gpu_blacklist_
) {
557 std::set
<int> features
= gpu_blacklist_
->MakeDecision(
558 gpu::GpuControlList::kOsAny
, std::string(), gpu_info_
);
559 if (update_histograms_
)
560 UpdateStats(gpu_info_
, gpu_blacklist_
.get(), features
);
562 UpdateBlacklistedFeatures(features
);
564 if (gpu_driver_bug_list_
) {
565 gpu_driver_bugs_
= gpu_driver_bug_list_
->MakeDecision(
566 gpu::GpuControlList::kOsAny
, std::string(), gpu_info_
);
568 disabled_extensions_
=
569 JoinString(gpu_driver_bug_list_
->GetDisabledExtensions(), ' ');
571 gpu::GpuDriverBugList::AppendWorkaroundsFromCommandLine(
572 &gpu_driver_bugs_
, *base::CommandLine::ForCurrentProcess());
574 // We have to update GpuFeatureType before notify all the observers.
575 NotifyGpuInfoUpdate();
578 void GpuDataManagerImplPrivate::UpdateGpuInfo(const gpu::GPUInfo
& gpu_info
) {
579 // No further update of gpu_info if falling back to SwiftShader.
580 if (use_swiftshader_
|| ShouldUseWarp())
583 bool was_info_available
= IsCompleteGpuInfoAvailable();
584 gpu::MergeGPUInfo(&gpu_info_
, gpu_info
);
585 if (IsCompleteGpuInfoAvailable()) {
586 complete_gpu_info_already_requested_
= true;
587 } else if (was_info_available
) {
588 // Allow future requests to go through properly.
589 complete_gpu_info_already_requested_
= false;
592 UpdateGpuInfoHelper();
595 void GpuDataManagerImplPrivate::UpdateVideoMemoryUsageStats(
596 const GPUVideoMemoryUsageStats
& video_memory_usage_stats
) {
597 GpuDataManagerImpl::UnlockedSession
session(owner_
);
598 observer_list_
->Notify(FROM_HERE
,
599 &GpuDataManagerObserver::OnVideoMemoryUsageStatsUpdate
,
600 video_memory_usage_stats
);
603 void GpuDataManagerImplPrivate::AppendRendererCommandLine(
604 base::CommandLine
* command_line
) const {
605 DCHECK(command_line
);
607 if (ShouldDisableAcceleratedVideoDecode(command_line
))
608 command_line
->AppendSwitch(switches::kDisableAcceleratedVideoDecode
);
609 #if defined(ENABLE_WEBRTC)
610 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE
) &&
611 !command_line
->HasSwitch(switches::kDisableWebRtcHWEncoding
))
612 command_line
->AppendSwitch(switches::kDisableWebRtcHWEncoding
);
615 #if defined(USE_AURA)
616 if (!CanUseGpuBrowserCompositor())
617 command_line
->AppendSwitch(switches::kDisableGpuCompositing
);
621 void GpuDataManagerImplPrivate::AppendGpuCommandLine(
622 base::CommandLine
* command_line
) const {
623 DCHECK(command_line
);
626 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
628 base::FilePath swiftshader_path
=
629 base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
630 switches::kSwiftShaderPath
);
631 if (gpu_driver_bugs_
.find(gpu::DISABLE_D3D11
) != gpu_driver_bugs_
.end())
632 command_line
->AppendSwitch(switches::kDisableD3D11
);
633 if (use_swiftshader_
) {
634 command_line
->AppendSwitchASCII(switches::kUseGL
, "swiftshader");
635 if (swiftshader_path
.empty())
636 swiftshader_path
= swiftshader_path_
;
637 } else if ((IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL
) ||
638 IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING
) ||
639 IsFeatureBlacklisted(
640 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS
)) &&
642 command_line
->AppendSwitchASCII(
643 switches::kUseGL
, gfx::kGLImplementationOSMesaName
);
644 } else if (!use_gl
.empty()) {
645 command_line
->AppendSwitchASCII(switches::kUseGL
, use_gl
);
647 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus())
648 command_line
->AppendSwitchASCII(switches::kSupportsDualGpus
, "true");
650 command_line
->AppendSwitchASCII(switches::kSupportsDualGpus
, "false");
652 if (!swiftshader_path
.empty()) {
653 command_line
->AppendSwitchPath(switches::kSwiftShaderPath
,
657 if (!gpu_driver_bugs_
.empty()) {
658 command_line
->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds
,
659 IntSetToString(gpu_driver_bugs_
));
662 if (!disabled_extensions_
.empty()) {
663 command_line
->AppendSwitchASCII(switches::kDisableGLExtensions
,
664 disabled_extensions_
);
667 if (ShouldDisableAcceleratedVideoDecode(command_line
)) {
668 command_line
->AppendSwitch(switches::kDisableAcceleratedVideoDecode
);
670 #if defined(ENABLE_WEBRTC)
671 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE
) &&
672 !command_line
->HasSwitch(switches::kDisableWebRtcHWEncoding
)) {
673 command_line
->AppendSwitch(switches::kDisableWebRtcHWEncoding
);
677 // Pass GPU and driver information to GPU process. We try to avoid full GPU
678 // info collection at GPU process startup, but we need gpu vendor_id,
679 // device_id, driver_vendor, driver_version for deciding whether we need to
680 // collect full info (on Linux) and for crash reporting purpose.
681 command_line
->AppendSwitchASCII(switches::kGpuVendorID
,
682 base::StringPrintf("0x%04x", gpu_info_
.gpu
.vendor_id
));
683 command_line
->AppendSwitchASCII(switches::kGpuDeviceID
,
684 base::StringPrintf("0x%04x", gpu_info_
.gpu
.device_id
));
685 command_line
->AppendSwitchASCII(switches::kGpuDriverVendor
,
686 gpu_info_
.driver_vendor
);
687 command_line
->AppendSwitchASCII(switches::kGpuDriverVersion
,
688 gpu_info_
.driver_version
);
690 if (ShouldUseWarp() && !command_line
->HasSwitch(switches::kUseANGLE
)) {
691 command_line
->AppendSwitchASCII(switches::kUseANGLE
,
692 gfx::kANGLEImplementationWARPName
);
696 void GpuDataManagerImplPrivate::AppendPluginCommandLine(
697 base::CommandLine
* command_line
) const {
698 DCHECK(command_line
);
700 #if defined(OS_MACOSX)
701 // TODO(jbauman): Add proper blacklist support for core animation plugins so
702 // special-casing this video card won't be necessary. See
703 // http://crbug.com/134015
704 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING
)) {
705 if (!command_line
->HasSwitch(
706 switches::kDisableCoreAnimationPlugins
))
707 command_line
->AppendSwitch(
708 switches::kDisableCoreAnimationPlugins
);
713 void GpuDataManagerImplPrivate::UpdateRendererWebPrefs(
714 WebPreferences
* prefs
) const {
717 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL
)) {
718 prefs
->experimental_webgl_enabled
= false;
719 prefs
->pepper_3d_enabled
= false;
721 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH3D
))
722 prefs
->flash_3d_enabled
= false;
723 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D
)) {
724 prefs
->flash_stage3d_enabled
= false;
725 prefs
->flash_stage3d_baseline_enabled
= false;
727 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE
))
728 prefs
->flash_stage3d_baseline_enabled
= false;
729 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS
))
730 prefs
->accelerated_2d_canvas_enabled
= false;
731 // TODO(senorblanco): The renderer shouldn't have an extra setting
732 // for this, but should rely on extension availability.
733 // Note that |gl_multisampling_enabled| only affects the decoder's
734 // default framebuffer allocation, which does not support
735 // multisampled_render_to_texture, only msaa with explicit resolve.
736 if (IsDriverBugWorkaroundActive(
737 gpu::DISABLE_CHROMIUM_FRAMEBUFFER_MULTISAMPLE
) ||
738 (IsDriverBugWorkaroundActive(gpu::DISABLE_MULTIMONITOR_MULTISAMPLING
) &&
740 prefs
->gl_multisampling_enabled
= false;
742 #if defined(USE_AURA)
743 if (!CanUseGpuBrowserCompositor()) {
744 prefs
->accelerated_2d_canvas_enabled
= false;
745 prefs
->pepper_3d_enabled
= false;
749 const base::CommandLine
* command_line
=
750 base::CommandLine::ForCurrentProcess();
751 if (!ShouldDisableAcceleratedVideoDecode(command_line
) &&
752 !command_line
->HasSwitch(switches::kDisableAcceleratedVideoDecode
)) {
753 prefs
->pepper_accelerated_video_decode_enabled
= true;
757 void GpuDataManagerImplPrivate::DisableHardwareAcceleration() {
758 card_blacklisted_
= true;
760 for (int i
= 0; i
< gpu::NUMBER_OF_GPU_FEATURE_TYPES
; ++i
)
761 blacklisted_features_
.insert(i
);
763 EnableWarpIfNecessary();
764 EnableSwiftShaderIfNecessary();
765 NotifyGpuInfoUpdate();
768 std::string
GpuDataManagerImplPrivate::GetBlacklistVersion() const {
770 return gpu_blacklist_
->version();
774 std::string
GpuDataManagerImplPrivate::GetDriverBugListVersion() const {
775 if (gpu_driver_bug_list_
)
776 return gpu_driver_bug_list_
->version();
780 void GpuDataManagerImplPrivate::GetBlacklistReasons(
781 base::ListValue
* reasons
) const {
783 gpu_blacklist_
->GetReasons(reasons
, "disabledFeatures");
784 if (gpu_driver_bug_list_
)
785 gpu_driver_bug_list_
->GetReasons(reasons
, "workarounds");
788 std::vector
<std::string
>
789 GpuDataManagerImplPrivate::GetDriverBugWorkarounds() const {
790 std::vector
<std::string
> workarounds
;
791 for (std::set
<int>::const_iterator it
= gpu_driver_bugs_
.begin();
792 it
!= gpu_driver_bugs_
.end(); ++it
) {
793 workarounds
.push_back(
794 gpu::GpuDriverBugWorkaroundTypeToString(
795 static_cast<gpu::GpuDriverBugWorkaroundType
>(*it
)));
800 void GpuDataManagerImplPrivate::AddLogMessage(
801 int level
, const std::string
& header
, const std::string
& message
) {
802 log_messages_
.push_back(LogMessage(level
, header
, message
));
805 void GpuDataManagerImplPrivate::ProcessCrashed(
806 base::TerminationStatus exit_code
) {
807 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
808 // Unretained is ok, because it's posted to UI thread, the thread
809 // where the singleton GpuDataManagerImpl lives until the end.
810 BrowserThread::PostTask(
813 base::Bind(&GpuDataManagerImpl::ProcessCrashed
,
814 base::Unretained(owner_
),
819 gpu_info_
.process_crash_count
= GpuProcessHost::gpu_crash_count();
820 GpuDataManagerImpl::UnlockedSession
session(owner_
);
821 observer_list_
->Notify(
822 FROM_HERE
, &GpuDataManagerObserver::OnGpuProcessCrashed
, exit_code
);
826 base::ListValue
* GpuDataManagerImplPrivate::GetLogMessages() const {
827 base::ListValue
* value
= new base::ListValue
;
828 for (size_t ii
= 0; ii
< log_messages_
.size(); ++ii
) {
829 base::DictionaryValue
* dict
= new base::DictionaryValue();
830 dict
->SetInteger("level", log_messages_
[ii
].level
);
831 dict
->SetString("header", log_messages_
[ii
].header
);
832 dict
->SetString("message", log_messages_
[ii
].message
);
838 void GpuDataManagerImplPrivate::HandleGpuSwitch() {
839 GpuDataManagerImpl::UnlockedSession
session(owner_
);
840 // Notify observers in the browser process.
841 ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched();
842 // Pass the notification to the GPU process to notify observers there.
843 GpuProcessHost::SendOnIO(
844 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED
,
845 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH
,
846 new GpuMsg_GpuSwitched
);
849 bool GpuDataManagerImplPrivate::UpdateActiveGpu(
850 uint32 vendor_id
, uint32 device_id
) {
851 if (gpu_info_
.gpu
.vendor_id
== vendor_id
&&
852 gpu_info_
.gpu
.device_id
== device_id
) {
853 // The primary GPU is active.
854 if (gpu_info_
.gpu
.active
)
856 gpu_info_
.gpu
.active
= true;
857 for (size_t ii
= 0; ii
< gpu_info_
.secondary_gpus
.size(); ++ii
)
858 gpu_info_
.secondary_gpus
[ii
].active
= false;
860 // A secondary GPU is active.
861 for (size_t ii
= 0; ii
< gpu_info_
.secondary_gpus
.size(); ++ii
) {
862 if (gpu_info_
.secondary_gpus
[ii
].vendor_id
== vendor_id
&&
863 gpu_info_
.secondary_gpus
[ii
].device_id
== device_id
) {
864 if (gpu_info_
.secondary_gpus
[ii
].active
)
866 gpu_info_
.secondary_gpus
[ii
].active
= true;
868 gpu_info_
.secondary_gpus
[ii
].active
= false;
871 gpu_info_
.gpu
.active
= false;
873 UpdateGpuInfoHelper();
877 bool GpuDataManagerImplPrivate::CanUseGpuBrowserCompositor() const {
878 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
879 switches::kDisableGpuCompositing
))
883 if (ShouldUseSwiftShader())
885 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING
))
891 bool GpuDataManagerImplPrivate::ShouldDisableAcceleratedVideoDecode(
892 const base::CommandLine
* command_line
) const {
893 // Make sure that we initialize the experiment first to make sure that
894 // statistics are bucket correctly in all cases.
895 // This experiment is temporary and will be removed once enough data
896 // to resolve crbug/442039 has been collected.
897 const std::string group_name
= base::FieldTrialList::FindFullName(
898 "DisableAcceleratedVideoDecode");
899 if (command_line
->HasSwitch(switches::kDisableAcceleratedVideoDecode
)) {
900 // It was already disabled on the command line.
903 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE
))
905 if (group_name
== "Disabled")
910 void GpuDataManagerImplPrivate::GetDisabledExtensions(
911 std::string
* disabled_extensions
) const {
912 DCHECK(disabled_extensions
);
914 *disabled_extensions
= disabled_extensions_
;
917 void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIs(
918 const GURL
& url
, GpuDataManagerImpl::DomainGuilt guilt
) {
919 BlockDomainFrom3DAPIsAtTime(url
, guilt
, base::Time::Now());
922 bool GpuDataManagerImplPrivate::Are3DAPIsBlocked(const GURL
& url
,
923 int render_process_id
,
925 ThreeDAPIType requester
) {
926 bool blocked
= Are3DAPIsBlockedAtTime(url
, base::Time::Now()) !=
927 GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED
;
929 // Unretained is ok, because it's posted to UI thread, the thread
930 // where the singleton GpuDataManagerImpl lives until the end.
931 BrowserThread::PostTask(
932 BrowserThread::UI
, FROM_HERE
,
933 base::Bind(&GpuDataManagerImpl::Notify3DAPIBlocked
,
934 base::Unretained(owner_
), url
, render_process_id
,
935 render_view_id
, requester
));
941 void GpuDataManagerImplPrivate::DisableDomainBlockingFor3DAPIsForTesting() {
942 domain_blocking_enabled_
= false;
946 GpuDataManagerImplPrivate
* GpuDataManagerImplPrivate::Create(
947 GpuDataManagerImpl
* owner
) {
948 return new GpuDataManagerImplPrivate(owner
);
951 GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(
952 GpuDataManagerImpl
* owner
)
953 : complete_gpu_info_already_requested_(false),
954 observer_list_(new GpuDataManagerObserverList
),
955 use_swiftshader_(false),
957 card_blacklisted_(false),
958 update_histograms_(true),
960 domain_blocking_enabled_(true),
963 gpu_process_accessible_(true),
966 const base::CommandLine
* command_line
=
967 base::CommandLine::ForCurrentProcess();
968 if (command_line
->HasSwitch(switches::kDisableGpu
))
969 DisableHardwareAcceleration();
971 #if defined(OS_MACOSX)
972 CGGetActiveDisplayList (0, NULL
, &display_count_
);
973 CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback
, owner_
);
977 if (command_line
->HasSwitch(switches::kDisableDomainBlockingFor3DAPIs
)) {
978 domain_blocking_enabled_
= false;
982 GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() {
983 #if defined(OS_MACOSX)
984 CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback
, owner_
);
988 void GpuDataManagerImplPrivate::InitializeImpl(
989 const std::string
& gpu_blacklist_json
,
990 const std::string
& gpu_driver_bug_list_json
,
991 const gpu::GPUInfo
& gpu_info
) {
992 const bool log_gpu_control_list_decisions
=
993 base::CommandLine::ForCurrentProcess()->HasSwitch(
994 switches::kLogGpuControlListDecisions
);
996 if (!gpu_blacklist_json
.empty()) {
997 gpu_blacklist_
.reset(gpu::GpuBlacklist::Create());
998 if (log_gpu_control_list_decisions
)
999 gpu_blacklist_
->enable_control_list_logging("gpu_blacklist");
1000 bool success
= gpu_blacklist_
->LoadList(
1001 gpu_blacklist_json
, gpu::GpuControlList::kCurrentOsOnly
);
1004 if (!gpu_driver_bug_list_json
.empty()) {
1005 gpu_driver_bug_list_
.reset(gpu::GpuDriverBugList::Create());
1006 if (log_gpu_control_list_decisions
)
1007 gpu_driver_bug_list_
->enable_control_list_logging("gpu_driver_bug_list");
1008 bool success
= gpu_driver_bug_list_
->LoadList(
1009 gpu_driver_bug_list_json
, gpu::GpuControlList::kCurrentOsOnly
);
1013 gpu_info_
= gpu_info
;
1014 UpdateGpuInfo(gpu_info
);
1015 UpdateGpuSwitchingManager(gpu_info
);
1016 UpdatePreliminaryBlacklistedFeatures();
1019 void GpuDataManagerImplPrivate::UpdateBlacklistedFeatures(
1020 const std::set
<int>& features
) {
1021 blacklisted_features_
= features
;
1023 // Force disable using the GPU for these features, even if they would
1024 // otherwise be allowed.
1025 if (card_blacklisted_
) {
1026 blacklisted_features_
.insert(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING
);
1027 blacklisted_features_
.insert(gpu::GPU_FEATURE_TYPE_WEBGL
);
1030 EnableWarpIfNecessary();
1031 EnableSwiftShaderIfNecessary();
1034 void GpuDataManagerImplPrivate::UpdatePreliminaryBlacklistedFeatures() {
1035 preliminary_blacklisted_features_
= blacklisted_features_
;
1038 void GpuDataManagerImplPrivate::UpdateGpuSwitchingManager(
1039 const gpu::GPUInfo
& gpu_info
) {
1040 // The vendor IDs might be 0 on non-PCI devices (like Android), but
1041 // the length of the vector is all we care about in most cases.
1042 std::vector
<uint32
> vendor_ids
;
1043 vendor_ids
.push_back(gpu_info
.gpu
.vendor_id
);
1044 for (const auto& device
: gpu_info
.secondary_gpus
) {
1045 vendor_ids
.push_back(device
.vendor_id
);
1047 ui::GpuSwitchingManager::GetInstance()->SetGpuVendorIds(vendor_ids
);
1049 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) {
1050 if (gpu_driver_bugs_
.count(gpu::FORCE_DISCRETE_GPU
) == 1)
1051 ui::GpuSwitchingManager::GetInstance()->ForceUseOfDiscreteGpu();
1052 else if (gpu_driver_bugs_
.count(gpu::FORCE_INTEGRATED_GPU
) == 1)
1053 ui::GpuSwitchingManager::GetInstance()->ForceUseOfIntegratedGpu();
1057 void GpuDataManagerImplPrivate::NotifyGpuInfoUpdate() {
1058 observer_list_
->Notify(FROM_HERE
, &GpuDataManagerObserver::OnGpuInfoUpdate
);
1061 void GpuDataManagerImplPrivate::EnableSwiftShaderIfNecessary() {
1062 if (ShouldUseWarp())
1065 if (!GpuAccessAllowed(NULL
) ||
1066 blacklisted_features_
.count(gpu::GPU_FEATURE_TYPE_WEBGL
)) {
1067 if (!swiftshader_path_
.empty() &&
1068 !base::CommandLine::ForCurrentProcess()->HasSwitch(
1069 switches::kDisableSoftwareRasterizer
))
1070 use_swiftshader_
= true;
1074 void GpuDataManagerImplPrivate::EnableWarpIfNecessary() {
1078 // We should only use WARP if we are unable to use the regular GPU for
1079 // compositing, and if we in Metro mode.
1080 use_warp_
= base::CommandLine::ForCurrentProcess()->HasSwitch(
1081 switches::kViewerConnect
) &&
1082 !CanUseGpuBrowserCompositor();
1086 void GpuDataManagerImplPrivate::ForceWarpModeForTesting() {
1090 std::string
GpuDataManagerImplPrivate::GetDomainFromURL(
1091 const GURL
& url
) const {
1092 // For the moment, we just use the host, or its IP address, as the
1093 // entry in the set, rather than trying to figure out the top-level
1094 // domain. This does mean that a.foo.com and b.foo.com will be
1095 // treated independently in the blocking of a given domain, but it
1096 // would require a third-party library to reliably figure out the
1097 // top-level domain from a URL.
1098 if (!url
.has_host()) {
1099 return std::string();
1105 void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIsAtTime(
1107 GpuDataManagerImpl::DomainGuilt guilt
,
1108 base::Time at_time
) {
1109 if (!domain_blocking_enabled_
)
1112 std::string domain
= GetDomainFromURL(url
);
1114 DomainBlockEntry
& entry
= blocked_domains_
[domain
];
1115 entry
.last_guilt
= guilt
;
1116 timestamps_of_gpu_resets_
.push_back(at_time
);
1119 GpuDataManagerImpl::DomainBlockStatus
1120 GpuDataManagerImplPrivate::Are3DAPIsBlockedAtTime(
1121 const GURL
& url
, base::Time at_time
) const {
1122 if (!domain_blocking_enabled_
)
1123 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED
;
1125 // Note: adjusting the policies in this code will almost certainly
1126 // require adjusting the associated unit tests.
1127 std::string domain
= GetDomainFromURL(url
);
1129 DomainBlockMap::const_iterator iter
= blocked_domains_
.find(domain
);
1130 if (iter
!= blocked_domains_
.end()) {
1131 // Err on the side of caution, and assume that if a particular
1132 // domain shows up in the block map, it's there for a good
1133 // reason and don't let its presence there automatically expire.
1135 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1136 BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED
,
1139 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED
;
1142 // Look at the timestamps of the recent GPU resets to see if there are
1143 // enough within the threshold which would cause us to blacklist all
1144 // domains. This doesn't need to be overly precise -- if time goes
1145 // backward due to a system clock adjustment, that's fine.
1147 // TODO(kbr): make this pay attention to the TDR thresholds in the
1148 // Windows registry, but make sure it continues to be testable.
1150 std::list
<base::Time
>::iterator iter
= timestamps_of_gpu_resets_
.begin();
1151 int num_resets_within_timeframe
= 0;
1152 while (iter
!= timestamps_of_gpu_resets_
.end()) {
1153 base::Time time
= *iter
;
1154 base::TimeDelta delta_t
= at_time
- time
;
1156 // If this entry has "expired", just remove it.
1157 if (delta_t
.InMilliseconds() > kBlockAllDomainsMs
) {
1158 iter
= timestamps_of_gpu_resets_
.erase(iter
);
1162 ++num_resets_within_timeframe
;
1166 if (num_resets_within_timeframe
>= kNumResetsWithinDuration
) {
1167 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1168 BLOCK_STATUS_ALL_DOMAINS_BLOCKED
,
1171 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED
;
1175 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1176 BLOCK_STATUS_NOT_BLOCKED
,
1179 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED
;
1182 int64
GpuDataManagerImplPrivate::GetBlockAllDomainsDurationInMs() const {
1183 return kBlockAllDomainsMs
;
1186 void GpuDataManagerImplPrivate::Notify3DAPIBlocked(const GURL
& url
,
1187 int render_process_id
,
1189 ThreeDAPIType requester
) {
1190 GpuDataManagerImpl::UnlockedSession
session(owner_
);
1191 observer_list_
->Notify(FROM_HERE
, &GpuDataManagerObserver::DidBlock3DAPIs
,
1192 url
, render_process_id
, render_view_id
, requester
);
1195 void GpuDataManagerImplPrivate::OnGpuProcessInitFailure() {
1196 gpu_process_accessible_
= false;
1197 gpu_info_
.context_info_state
= gpu::kCollectInfoFatalFailure
;
1199 gpu_info_
.dx_diagnostics_info_state
= gpu::kCollectInfoFatalFailure
;
1201 complete_gpu_info_already_requested_
= true;
1202 // Some observers might be waiting.
1203 NotifyGpuInfoUpdate();
1206 } // namespace content