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/debug/trace_event.h"
11 #include "base/metrics/field_trial.h"
12 #include "base/metrics/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/version.h"
17 #include "cc/base/switches.h"
18 #include "content/browser/gpu/gpu_process_host.h"
19 #include "content/common/gpu/gpu_messages.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/gpu_data_manager_observer.h"
22 #include "content/public/common/content_client.h"
23 #include "content/public/common/content_constants.h"
24 #include "content/public/common/content_switches.h"
25 #include "gpu/command_buffer/service/gpu_switches.h"
26 #include "gpu/config/gpu_control_list_jsons.h"
27 #include "gpu/config/gpu_driver_bug_workaround_type.h"
28 #include "gpu/config/gpu_feature_type.h"
29 #include "gpu/config/gpu_info_collector.h"
30 #include "gpu/config/gpu_util.h"
31 #include "ui/base/ui_base_switches.h"
32 #include "ui/gl/gl_implementation.h"
33 #include "ui/gl/gl_switches.h"
34 #include "ui/gl/gpu_switching_manager.h"
35 #include "webkit/common/webpreferences.h"
36 #include "webkit/plugins/plugin_switches.h"
38 #if defined(OS_MACOSX)
39 #include <ApplicationServices/ApplicationServices.h>
42 #include "base/win/windows_version.h"
44 #if defined(OS_ANDROID)
45 #include "ui/gfx/android/device_display_info.h"
52 enum GpuFeatureStatus
{
53 kGpuFeatureEnabled
= 0,
54 kGpuFeatureBlacklisted
= 1,
55 kGpuFeatureDisabled
= 2, // disabled by user but not blacklisted
69 int GetGpuBlacklistHistogramValueWin(GpuFeatureStatus status
) {
70 static WinSubVersion sub_version
= kNumWinSubVersions
;
71 if (sub_version
== kNumWinSubVersions
) {
72 sub_version
= kWinOthers
;
73 std::string version_str
= base::SysInfo::OperatingSystemVersion();
74 size_t pos
= version_str
.find_first_not_of("0123456789.");
75 if (pos
!= std::string::npos
)
76 version_str
= version_str
.substr(0, pos
);
77 Version
os_version(version_str
);
78 if (os_version
.IsValid() && os_version
.components().size() >= 2) {
79 const std::vector
<uint16
>& version_numbers
= os_version
.components();
80 if (version_numbers
[0] == 5)
82 else if (version_numbers
[0] == 6 && version_numbers
[1] == 0)
83 sub_version
= kWinVista
;
84 else if (version_numbers
[0] == 6 && version_numbers
[1] == 1)
88 int entry_index
= static_cast<int>(sub_version
) * kGpuFeatureNumStatus
;
90 case kGpuFeatureEnabled
:
92 case kGpuFeatureBlacklisted
:
95 case kGpuFeatureDisabled
:
103 // Send UMA histograms about the enabled features.
104 void UpdateStats(const gpu::GpuBlacklist
* blacklist
,
105 const std::set
<int>& blacklisted_features
) {
106 uint32 max_entry_id
= blacklist
->max_entry_id();
107 if (max_entry_id
== 0) {
108 // GPU Blacklist was not loaded. No need to go further.
112 const CommandLine
& command_line
= *CommandLine::ForCurrentProcess();
113 bool disabled
= false;
114 if (blacklisted_features
.size() == 0) {
115 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry",
116 0, max_entry_id
+ 1);
118 std::vector
<uint32
> flag_entries
;
119 blacklist
->GetDecisionEntries(&flag_entries
, disabled
);
120 DCHECK_GT(flag_entries
.size(), 0u);
121 for (size_t i
= 0; i
< flag_entries
.size(); ++i
) {
122 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry",
123 flag_entries
[i
], max_entry_id
+ 1);
127 // This counts how many users are affected by a disabled entry - this allows
128 // us to understand the impact of an entry before enable it.
129 std::vector
<uint32
> flag_disabled_entries
;
131 blacklist
->GetDecisionEntries(&flag_disabled_entries
, disabled
);
132 for (size_t i
= 0; i
< flag_disabled_entries
.size(); ++i
) {
133 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerDisabledEntry",
134 flag_disabled_entries
[i
], max_entry_id
+ 1);
137 const gpu::GpuFeatureType kGpuFeatures
[] = {
138 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS
,
139 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING
,
140 gpu::GPU_FEATURE_TYPE_WEBGL
142 const std::string kGpuBlacklistFeatureHistogramNames
[] = {
143 "GPU.BlacklistFeatureTestResults.Accelerated2dCanvas",
144 "GPU.BlacklistFeatureTestResults.AcceleratedCompositing",
145 "GPU.BlacklistFeatureTestResults.Webgl"
147 const bool kGpuFeatureUserFlags
[] = {
148 command_line
.HasSwitch(switches::kDisableAccelerated2dCanvas
),
149 command_line
.HasSwitch(switches::kDisableAcceleratedCompositing
),
150 #if defined(OS_ANDROID)
151 !command_line
.HasSwitch(switches::kEnableExperimentalWebGL
)
153 command_line
.HasSwitch(switches::kDisableExperimentalWebGL
)
157 const std::string kGpuBlacklistFeatureHistogramNamesWin
[] = {
158 "GPU.BlacklistFeatureTestResultsWindows.Accelerated2dCanvas",
159 "GPU.BlacklistFeatureTestResultsWindows.AcceleratedCompositing",
160 "GPU.BlacklistFeatureTestResultsWindows.Webgl"
163 const size_t kNumFeatures
=
164 sizeof(kGpuFeatures
) / sizeof(gpu::GpuFeatureType
);
165 for (size_t i
= 0; i
< kNumFeatures
; ++i
) {
166 // We can't use UMA_HISTOGRAM_ENUMERATION here because the same name is
167 // expected if the macro is used within a loop.
168 GpuFeatureStatus value
= kGpuFeatureEnabled
;
169 if (blacklisted_features
.count(kGpuFeatures
[i
]))
170 value
= kGpuFeatureBlacklisted
;
171 else if (kGpuFeatureUserFlags
[i
])
172 value
= kGpuFeatureDisabled
;
173 base::HistogramBase
* histogram_pointer
= base::LinearHistogram::FactoryGet(
174 kGpuBlacklistFeatureHistogramNames
[i
],
175 1, kGpuFeatureNumStatus
, kGpuFeatureNumStatus
+ 1,
176 base::HistogramBase::kUmaTargetedHistogramFlag
);
177 histogram_pointer
->Add(value
);
179 histogram_pointer
= base::LinearHistogram::FactoryGet(
180 kGpuBlacklistFeatureHistogramNamesWin
[i
],
181 1, kNumWinSubVersions
* kGpuFeatureNumStatus
,
182 kNumWinSubVersions
* kGpuFeatureNumStatus
+ 1,
183 base::HistogramBase::kUmaTargetedHistogramFlag
);
184 histogram_pointer
->Add(GetGpuBlacklistHistogramValueWin(value
));
189 // Strip out the non-digital info; if after that, we get an empty string,
191 std::string
ProcessVersionString(const std::string
& raw_string
) {
192 const std::string valid_set
= "0123456789.";
193 size_t start_pos
= raw_string
.find_first_of(valid_set
);
194 if (start_pos
== std::string::npos
)
196 size_t end_pos
= raw_string
.find_first_not_of(raw_string
, start_pos
);
197 std::string version_string
= raw_string
.substr(
198 start_pos
, end_pos
- start_pos
);
199 if (version_string
.empty())
201 return version_string
;
204 // Combine the integers into a string, seperated by ','.
205 std::string
IntSetToString(const std::set
<int>& list
) {
207 for (std::set
<int>::const_iterator it
= list
.begin();
208 it
!= list
.end(); ++it
) {
211 rt
+= base::IntToString(*it
);
216 #if defined(OS_MACOSX)
217 void DisplayReconfigCallback(CGDirectDisplayID display
,
218 CGDisplayChangeSummaryFlags flags
,
219 void* gpu_data_manager
) {
220 if(flags
== kCGDisplayBeginConfigurationFlag
)
221 return; // This call contains no information about the display change
223 GpuDataManagerImpl
* manager
=
224 reinterpret_cast<GpuDataManagerImpl
*>(gpu_data_manager
);
227 uint32_t displayCount
;
228 CGGetActiveDisplayList(0, NULL
, &displayCount
);
230 bool fireGpuSwitch
= flags
& kCGDisplayAddFlag
;
232 if (displayCount
!= manager
->GetDisplayCount()) {
233 manager
->SetDisplayCount(displayCount
);
234 fireGpuSwitch
= true;
238 manager
->HandleGpuSwitch();
242 #if defined(OS_ANDROID)
243 void ApplyAndroidWorkarounds(const gpu::GPUInfo
& gpu_info
,
244 CommandLine
* command_line
) {
245 std::string
vendor(StringToLowerASCII(gpu_info
.gl_vendor
));
246 std::string
renderer(StringToLowerASCII(gpu_info
.gl_renderer
));
248 gpu_info
.gl_vendor
.find("Imagination") != std::string::npos
;
250 gpu_info
.gl_vendor
.find("ARM") != std::string::npos
;
252 gpu_info
.gl_vendor
.find("Qualcomm") != std::string::npos
;
254 gpu_info
.gl_vendor
.find("Broadcom") != std::string::npos
;
255 bool is_mali_t604
= is_arm
&&
256 gpu_info
.gl_renderer
.find("Mali-T604") != std::string::npos
;
259 gpu_info
.gl_extensions
.find("GL_VIV_shader_binary") !=
263 gpu_info
.machine_model
.find("Nexus 7") != std::string::npos
;
265 gpu_info
.machine_model
.find("Nexus 10") != std::string::npos
;
267 // IMG: avoid context switching perf problems, crashes with share groups
268 // Mali-T604: http://crbug.com/154715
269 // QualComm, NVIDIA: Crashes with share groups
270 if (is_vivante
|| is_img
|| is_mali_t604
|| is_nexus7
|| is_qualcomm
||
272 command_line
->AppendSwitch(switches::kEnableVirtualGLContexts
);
274 gfx::DeviceDisplayInfo info
;
275 int default_tile_size
= 256;
277 // For very high resolution displays (eg. Nexus 10), set the default
278 // tile size to be 512. This should be removed in favour of a generic
279 // hueristic that works across all platforms and devices, once that
280 // exists: http://crbug.com/159524. This switches to 512 for screens
281 // containing 40 or more 256x256 tiles, such that 1080p devices do
282 // not use 512x512 tiles (eg. 1920x1280 requires 37.5 tiles)
283 int numTiles
= (info
.GetDisplayWidth() *
284 info
.GetDisplayHeight()) / (256 * 256);
286 default_tile_size
= 512;
288 // IMG: Fast async texture uploads only work with non-power-of-two,
289 // but still multiple-of-eight sizes.
290 // http://crbug.com/168099
292 default_tile_size
-= 8;
294 // Set the command line if it isn't already set and we changed
295 // the default tile size.
296 if (default_tile_size
!= 256 &&
297 !command_line
->HasSwitch(switches::kDefaultTileWidth
) &&
298 !command_line
->HasSwitch(switches::kDefaultTileHeight
)) {
299 std::stringstream size
;
300 size
<< default_tile_size
;
301 command_line
->AppendSwitchASCII(
302 switches::kDefaultTileWidth
, size
.str());
303 command_line
->AppendSwitchASCII(
304 switches::kDefaultTileHeight
, size
.str());
307 // Increase the resolution of low resolution tiles for Nexus tablets.
308 if ((is_nexus7
|| is_nexus10
) &&
309 !command_line
->HasSwitch(
310 cc::switches::kLowResolutionContentsScaleFactor
)) {
311 command_line
->AppendSwitchASCII(
312 cc::switches::kLowResolutionContentsScaleFactor
, "0.25");
317 // Block all domains' use of 3D APIs for this many milliseconds if
318 // approaching a threshold where system stability might be compromised.
319 const int64 kBlockAllDomainsMs
= 10000;
320 const int kNumResetsWithinDuration
= 1;
322 // Enums for UMA histograms.
323 enum BlockStatusHistogram
{
324 BLOCK_STATUS_NOT_BLOCKED
,
325 BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED
,
326 BLOCK_STATUS_ALL_DOMAINS_BLOCKED
,
330 } // namespace anonymous
332 void GpuDataManagerImplPrivate::InitializeForTesting(
333 const std::string
& gpu_blacklist_json
,
334 const gpu::GPUInfo
& gpu_info
) {
335 // This function is for testing only, so disable histograms.
336 update_histograms_
= false;
338 InitializeImpl(gpu_blacklist_json
, std::string(), std::string(), gpu_info
);
341 bool GpuDataManagerImplPrivate::IsFeatureBlacklisted(int feature
) const {
342 if (use_swiftshader_
) {
343 // Skia's software rendering is probably more efficient than going through
344 // software emulation of the GPU, so use that.
345 if (feature
== gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS
)
350 return (blacklisted_features_
.count(feature
) == 1);
353 size_t GpuDataManagerImplPrivate::GetBlacklistedFeatureCount() const {
354 if (use_swiftshader_
)
356 return blacklisted_features_
.size();
359 void GpuDataManagerImplPrivate::SetDisplayCount(unsigned int display_count
) {
360 display_count_
= display_count
;
363 unsigned int GpuDataManagerImplPrivate::GetDisplayCount() const {
364 return display_count_
;
367 gpu::GPUInfo
GpuDataManagerImplPrivate::GetGPUInfo() const {
371 void GpuDataManagerImplPrivate::GetGpuProcessHandles(
372 const GpuDataManager::GetGpuProcessHandlesCallback
& callback
) const {
373 GpuProcessHost::GetProcessHandles(callback
);
376 bool GpuDataManagerImplPrivate::GpuAccessAllowed(
377 std::string
* reason
) const {
378 if (use_swiftshader_
)
381 if (!gpu_process_accessible_
) {
383 *reason
= "GPU process launch failed.";
388 if (card_blacklisted_
) {
390 *reason
= "GPU access is disabled ";
391 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
392 if (command_line
->HasSwitch(switches::kDisableGpu
))
393 *reason
+= "through commandline switch --disable-gpu.";
395 *reason
+= "in chrome://settings.";
400 // We only need to block GPU process if more features are disallowed other
401 // than those in the preliminary gpu feature flags because the latter work
402 // through renderer commandline switches.
403 std::set
<int> features
= preliminary_blacklisted_features_
;
404 gpu::MergeFeatureSets(&features
, blacklisted_features_
);
405 if (features
.size() > preliminary_blacklisted_features_
.size()) {
407 *reason
= "Features are disabled upon full but not preliminary GPU info.";
412 if (blacklisted_features_
.size() == gpu::NUMBER_OF_GPU_FEATURE_TYPES
) {
413 // On Linux, we use cached GL strings to make blacklist decsions at browser
414 // startup time. We need to launch the GPU process to validate these
415 // strings even if all features are blacklisted. If all GPU features are
416 // disabled, the GPU process will only initialize GL bindings, create a GL
417 // context, and collect full GPU info.
418 #if !defined(OS_LINUX)
420 *reason
= "All GPU features are blacklisted.";
429 void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
430 if (complete_gpu_info_already_requested_
|| gpu_info_
.finalized
)
432 complete_gpu_info_already_requested_
= true;
434 GpuProcessHost::SendOnIO(
436 GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED
,
438 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED
,
440 CAUSE_FOR_GPU_LAUNCH_GPUDATAMANAGER_REQUESTCOMPLETEGPUINFOIFNEEDED
,
441 new GpuMsg_CollectGraphicsInfo());
444 bool GpuDataManagerImplPrivate::IsCompleteGpuInfoAvailable() const {
445 return gpu_info_
.finalized
;
448 void GpuDataManagerImplPrivate::RequestVideoMemoryUsageStatsUpdate() const {
449 GpuProcessHost::SendOnIO(
450 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED
,
451 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH
,
452 new GpuMsg_GetVideoMemoryUsageStats());
455 bool GpuDataManagerImplPrivate::ShouldUseSwiftShader() const {
456 return use_swiftshader_
;
459 void GpuDataManagerImplPrivate::RegisterSwiftShaderPath(
460 const base::FilePath
& path
) {
461 swiftshader_path_
= path
;
462 EnableSwiftShaderIfNecessary();
465 void GpuDataManagerImplPrivate::AddObserver(GpuDataManagerObserver
* observer
) {
466 GpuDataManagerImpl::UnlockedSession
session(owner_
);
467 observer_list_
->AddObserver(observer
);
470 void GpuDataManagerImplPrivate::RemoveObserver(
471 GpuDataManagerObserver
* observer
) {
472 GpuDataManagerImpl::UnlockedSession
session(owner_
);
473 observer_list_
->RemoveObserver(observer
);
476 void GpuDataManagerImplPrivate::UnblockDomainFrom3DAPIs(const GURL
& url
) {
477 // This method must do two things:
479 // 1. If the specific domain is blocked, then unblock it.
481 // 2. Reset our notion of how many GPU resets have occurred recently.
482 // This is necessary even if the specific domain was blocked.
483 // Otherwise, if we call Are3DAPIsBlocked with the same domain right
484 // after unblocking it, it will probably still be blocked because of
485 // the recent GPU reset caused by that domain.
487 // These policies could be refined, but at a certain point the behavior
488 // will become difficult to explain.
489 std::string domain
= GetDomainFromURL(url
);
491 blocked_domains_
.erase(domain
);
492 timestamps_of_gpu_resets_
.clear();
495 void GpuDataManagerImplPrivate::DisableGpuWatchdog() {
496 GpuProcessHost::SendOnIO(
497 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED
,
498 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH
,
499 new GpuMsg_DisableWatchdog
);
502 void GpuDataManagerImplPrivate::SetGLStrings(const std::string
& gl_vendor
,
503 const std::string
& gl_renderer
,
504 const std::string
& gl_version
) {
505 if (gl_vendor
.empty() && gl_renderer
.empty() && gl_version
.empty())
508 // If GPUInfo already got GL strings, do nothing. This is for the rare
509 // situation where GPU process collected GL strings before this call.
510 if (!gpu_info_
.gl_vendor
.empty() ||
511 !gpu_info_
.gl_renderer
.empty() ||
512 !gpu_info_
.gl_version_string
.empty())
515 gpu::GPUInfo gpu_info
= gpu_info_
;
517 gpu_info
.gl_vendor
= gl_vendor
;
518 gpu_info
.gl_renderer
= gl_renderer
;
519 gpu_info
.gl_version_string
= gl_version
;
521 gpu::CollectDriverInfoGL(&gpu_info
);
523 UpdateGpuInfo(gpu_info
);
524 UpdateGpuSwitchingManager(gpu_info
);
525 UpdatePreliminaryBlacklistedFeatures();
528 void GpuDataManagerImplPrivate::GetGLStrings(std::string
* gl_vendor
,
529 std::string
* gl_renderer
,
530 std::string
* gl_version
) {
531 DCHECK(gl_vendor
&& gl_renderer
&& gl_version
);
533 *gl_vendor
= gpu_info_
.gl_vendor
;
534 *gl_renderer
= gpu_info_
.gl_renderer
;
535 *gl_version
= gpu_info_
.gl_version_string
;
538 void GpuDataManagerImplPrivate::Initialize() {
539 TRACE_EVENT0("startup", "GpuDataManagerImpl::Initialize");
540 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
541 if (command_line
->HasSwitch(switches::kSkipGpuDataLoading
))
544 gpu::GPUInfo gpu_info
;
546 TRACE_EVENT0("startup",
547 "GpuDataManagerImpl::Initialize:CollectBasicGraphicsInfo");
548 gpu::CollectBasicGraphicsInfo(&gpu_info
);
550 #if defined(ARCH_CPU_X86_FAMILY)
551 if (!gpu_info
.gpu
.vendor_id
|| !gpu_info
.gpu
.device_id
)
552 gpu_info
.finalized
= true;
555 std::string gpu_blacklist_string
;
556 std::string gpu_switching_list_string
;
557 std::string gpu_driver_bug_list_string
;
558 if (!command_line
->HasSwitch(switches::kIgnoreGpuBlacklist
)) {
559 gpu_blacklist_string
= gpu::kSoftwareRenderingListJson
;
560 gpu_switching_list_string
= gpu::kGpuSwitchingListJson
;
562 if (!command_line
->HasSwitch(switches::kDisableGpuDriverBugWorkarounds
)) {
563 gpu_driver_bug_list_string
= gpu::kGpuDriverBugListJson
;
565 InitializeImpl(gpu_blacklist_string
,
566 gpu_switching_list_string
,
567 gpu_driver_bug_list_string
,
571 void GpuDataManagerImplPrivate::UpdateGpuInfo(const gpu::GPUInfo
& gpu_info
) {
572 // No further update of gpu_info if falling back to SwiftShader.
573 if (use_swiftshader_
)
576 gpu::MergeGPUInfo(&gpu_info_
, gpu_info
);
577 complete_gpu_info_already_requested_
=
578 complete_gpu_info_already_requested_
|| gpu_info_
.finalized
;
580 GetContentClient()->SetGpuInfo(gpu_info_
);
582 if (gpu_blacklist_
) {
583 std::set
<int> features
= gpu_blacklist_
->MakeDecision(
584 gpu::GpuControlList::kOsAny
, std::string(), gpu_info_
);
585 if (update_histograms_
)
586 UpdateStats(gpu_blacklist_
.get(), features
);
588 UpdateBlacklistedFeatures(features
);
590 if (gpu_switching_list_
) {
591 std::set
<int> option
= gpu_switching_list_
->MakeDecision(
592 gpu::GpuControlList::kOsAny
, std::string(), gpu_info_
);
593 if (option
.size() == 1) {
594 // Blacklist decision should not overwrite commandline switch from users.
595 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
596 if (!command_line
->HasSwitch(switches::kGpuSwitching
)) {
597 gpu_switching_
= static_cast<gpu::GpuSwitchingOption
>(
602 if (gpu_driver_bug_list_
) {
603 gpu_driver_bugs_
= gpu_driver_bug_list_
->MakeDecision(
604 gpu::GpuControlList::kOsAny
, std::string(), gpu_info_
);
607 // We have to update GpuFeatureType before notify all the observers.
608 NotifyGpuInfoUpdate();
611 void GpuDataManagerImplPrivate::UpdateVideoMemoryUsageStats(
612 const GPUVideoMemoryUsageStats
& video_memory_usage_stats
) {
613 GpuDataManagerImpl::UnlockedSession
session(owner_
);
614 observer_list_
->Notify(&GpuDataManagerObserver::OnVideoMemoryUsageStatsUpdate
,
615 video_memory_usage_stats
);
618 void GpuDataManagerImplPrivate::AppendRendererCommandLine(
619 CommandLine
* command_line
) const {
620 DCHECK(command_line
);
622 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL
)) {
623 #if !defined(OS_ANDROID)
624 if (!command_line
->HasSwitch(switches::kDisableExperimentalWebGL
))
625 command_line
->AppendSwitch(switches::kDisableExperimentalWebGL
);
627 if (!command_line
->HasSwitch(switches::kDisablePepper3d
))
628 command_line
->AppendSwitch(switches::kDisablePepper3d
);
630 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_MULTISAMPLING
) &&
631 !command_line
->HasSwitch(switches::kDisableGLMultisampling
))
632 command_line
->AppendSwitch(switches::kDisableGLMultisampling
);
633 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING
) &&
634 !command_line
->HasSwitch(switches::kDisableAcceleratedCompositing
))
635 command_line
->AppendSwitch(switches::kDisableAcceleratedCompositing
);
636 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS
) &&
637 !command_line
->HasSwitch(switches::kDisableAccelerated2dCanvas
))
638 command_line
->AppendSwitch(switches::kDisableAccelerated2dCanvas
);
639 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE
) &&
640 !command_line
->HasSwitch(switches::kDisableAcceleratedVideoDecode
))
641 command_line
->AppendSwitch(switches::kDisableAcceleratedVideoDecode
);
644 void GpuDataManagerImplPrivate::AppendGpuCommandLine(
645 CommandLine
* command_line
) const {
646 DCHECK(command_line
);
648 bool reduce_sandbox
= false;
651 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL
);
652 base::FilePath swiftshader_path
=
653 CommandLine::ForCurrentProcess()->GetSwitchValuePath(
654 switches::kSwiftShaderPath
);
655 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_MULTISAMPLING
) &&
656 !command_line
->HasSwitch(switches::kDisableGLMultisampling
)) {
657 command_line
->AppendSwitch(switches::kDisableGLMultisampling
);
659 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING
)) {
660 command_line
->AppendSwitch(switches::kDisableImageTransportSurface
);
661 reduce_sandbox
= true;
663 if (use_swiftshader_
) {
664 command_line
->AppendSwitchASCII(switches::kUseGL
, "swiftshader");
665 if (swiftshader_path
.empty())
666 swiftshader_path
= swiftshader_path_
;
667 } else if ((IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL
) ||
668 IsFeatureBlacklisted(
669 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING
) ||
670 IsFeatureBlacklisted(
671 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS
)) &&
673 command_line
->AppendSwitchASCII(
674 switches::kUseGL
, gfx::kGLImplementationOSMesaName
);
675 } else if (!use_gl
.empty()) {
676 command_line
->AppendSwitchASCII(switches::kUseGL
, use_gl
);
678 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) {
679 command_line
->AppendSwitchASCII(switches::kSupportsDualGpus
, "true");
680 switch (gpu_switching_
) {
681 case gpu::GPU_SWITCHING_OPTION_FORCE_DISCRETE
:
682 command_line
->AppendSwitchASCII(switches::kGpuSwitching
,
683 switches::kGpuSwitchingOptionNameForceDiscrete
);
685 case gpu::GPU_SWITCHING_OPTION_FORCE_INTEGRATED
:
686 command_line
->AppendSwitchASCII(switches::kGpuSwitching
,
687 switches::kGpuSwitchingOptionNameForceIntegrated
);
689 case gpu::GPU_SWITCHING_OPTION_AUTOMATIC
:
690 case gpu::GPU_SWITCHING_OPTION_UNKNOWN
:
694 command_line
->AppendSwitchASCII(switches::kSupportsDualGpus
, "false");
697 if (!swiftshader_path
.empty()) {
698 command_line
->AppendSwitchPath(switches::kSwiftShaderPath
,
702 if (!gpu_driver_bugs_
.empty()) {
703 command_line
->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds
,
704 IntSetToString(gpu_driver_bugs_
));
708 // DisplayLink 7.1 and earlier can cause the GPU process to crash on startup.
709 // http://crbug.com/177611
710 // Thinkpad USB Port Replicator driver causes GPU process to crash when the
711 // sandbox is enabled. http://crbug.com/181665.
712 if ((gpu_info_
.display_link_version
.IsValid()
713 && gpu_info_
.display_link_version
.IsOlderThan("7.2")) ||
714 gpu_info_
.lenovo_dcute
) {
715 reduce_sandbox
= true;
719 if (gpu_info_
.optimus
)
720 reduce_sandbox
= true;
722 if (gpu_info_
.amd_switchable
) {
723 // The image transport surface currently doesn't work with AMD Dynamic
724 // Switchable graphics.
725 reduce_sandbox
= true;
726 command_line
->AppendSwitch(switches::kDisableImageTransportSurface
);
730 command_line
->AppendSwitch(switches::kReduceGpuSandbox
);
732 // Pass GPU and driver information to GPU process. We try to avoid full GPU
733 // info collection at GPU process startup, but we need gpu vendor_id,
734 // device_id, driver_vendor, driver_version for deciding whether we need to
735 // collect full info (on Linux) and for crash reporting purpose.
736 command_line
->AppendSwitchASCII(switches::kGpuVendorID
,
737 base::StringPrintf("0x%04x", gpu_info_
.gpu
.vendor_id
));
738 command_line
->AppendSwitchASCII(switches::kGpuDeviceID
,
739 base::StringPrintf("0x%04x", gpu_info_
.gpu
.device_id
));
740 command_line
->AppendSwitchASCII(switches::kGpuDriverVendor
,
741 gpu_info_
.driver_vendor
);
742 command_line
->AppendSwitchASCII(switches::kGpuDriverVersion
,
743 gpu_info_
.driver_version
);
746 void GpuDataManagerImplPrivate::AppendPluginCommandLine(
747 CommandLine
* command_line
) const {
748 DCHECK(command_line
);
750 #if defined(OS_MACOSX)
751 // TODO(jbauman): Add proper blacklist support for core animation plugins so
752 // special-casing this video card won't be necessary. See
753 // http://crbug.com/134015
754 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING
) ||
755 CommandLine::ForCurrentProcess()->HasSwitch(
756 switches::kDisableAcceleratedCompositing
)) {
757 if (!command_line
->HasSwitch(
758 switches::kDisableCoreAnimationPlugins
))
759 command_line
->AppendSwitch(
760 switches::kDisableCoreAnimationPlugins
);
765 void GpuDataManagerImplPrivate::UpdateRendererWebPrefs(
766 WebPreferences
* prefs
) const {
769 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING
))
770 prefs
->accelerated_compositing_enabled
= false;
771 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL
))
772 prefs
->experimental_webgl_enabled
= false;
773 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH3D
))
774 prefs
->flash_3d_enabled
= false;
775 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D
)) {
776 prefs
->flash_stage3d_enabled
= false;
777 prefs
->flash_stage3d_baseline_enabled
= false;
779 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE
))
780 prefs
->flash_stage3d_baseline_enabled
= false;
781 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS
))
782 prefs
->accelerated_2d_canvas_enabled
= false;
783 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_MULTISAMPLING
)
784 || display_count_
> 1)
785 prefs
->gl_multisampling_enabled
= false;
786 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_3D_CSS
)) {
787 prefs
->accelerated_compositing_for_3d_transforms_enabled
= false;
788 prefs
->accelerated_compositing_for_animation_enabled
= false;
790 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO
))
791 prefs
->accelerated_compositing_for_video_enabled
= false;
793 // Accelerated video and animation are slower than regular when using
794 // SwiftShader. 3D CSS may also be too slow to be worthwhile.
795 if (ShouldUseSwiftShader()) {
796 prefs
->accelerated_compositing_for_video_enabled
= false;
797 prefs
->accelerated_compositing_for_animation_enabled
= false;
798 prefs
->accelerated_compositing_for_3d_transforms_enabled
= false;
799 prefs
->accelerated_compositing_for_plugins_enabled
= false;
803 gpu::GpuSwitchingOption
804 GpuDataManagerImplPrivate::GetGpuSwitchingOption() const {
805 if (!ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus())
806 return gpu::GPU_SWITCHING_OPTION_UNKNOWN
;
807 return gpu_switching_
;
810 void GpuDataManagerImplPrivate::DisableHardwareAcceleration() {
811 card_blacklisted_
= true;
813 for (int i
= 0; i
< gpu::NUMBER_OF_GPU_FEATURE_TYPES
; ++i
)
814 blacklisted_features_
.insert(i
);
816 EnableSwiftShaderIfNecessary();
817 NotifyGpuInfoUpdate();
820 std::string
GpuDataManagerImplPrivate::GetBlacklistVersion() const {
822 return gpu_blacklist_
->version();
826 std::string
GpuDataManagerImplPrivate::GetDriverBugListVersion() const {
827 if (gpu_driver_bug_list_
)
828 return gpu_driver_bug_list_
->version();
832 void GpuDataManagerImplPrivate::GetBlacklistReasons(
833 base::ListValue
* reasons
) const {
835 gpu_blacklist_
->GetReasons(reasons
);
838 void GpuDataManagerImplPrivate::GetDriverBugWorkarounds(
839 base::ListValue
* workarounds
) const {
840 for (std::set
<int>::const_iterator it
= gpu_driver_bugs_
.begin();
841 it
!= gpu_driver_bugs_
.end(); ++it
) {
842 workarounds
->AppendString(
843 gpu::GpuDriverBugWorkaroundTypeToString(
844 static_cast<gpu::GpuDriverBugWorkaroundType
>(*it
)));
848 void GpuDataManagerImplPrivate::AddLogMessage(
849 int level
, const std::string
& header
, const std::string
& message
) {
850 base::DictionaryValue
* dict
= new base::DictionaryValue();
851 dict
->SetInteger("level", level
);
852 dict
->SetString("header", header
);
853 dict
->SetString("message", message
);
854 log_messages_
.Append(dict
);
857 void GpuDataManagerImplPrivate::ProcessCrashed(
858 base::TerminationStatus exit_code
) {
859 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
860 // Unretained is ok, because it's posted to UI thread, the thread
861 // where the singleton GpuDataManagerImpl lives until the end.
862 BrowserThread::PostTask(
865 base::Bind(&GpuDataManagerImpl::ProcessCrashed
,
866 base::Unretained(owner_
),
871 GpuDataManagerImpl::UnlockedSession
session(owner_
);
872 observer_list_
->Notify(
873 &GpuDataManagerObserver::OnGpuProcessCrashed
, exit_code
);
877 base::ListValue
* GpuDataManagerImplPrivate::GetLogMessages() const {
878 base::ListValue
* value
;
879 value
= log_messages_
.DeepCopy();
883 void GpuDataManagerImplPrivate::HandleGpuSwitch() {
884 GpuDataManagerImpl::UnlockedSession
session(owner_
);
885 observer_list_
->Notify(&GpuDataManagerObserver::OnGpuSwitching
);
889 bool GpuDataManagerImplPrivate::IsUsingAcceleratedSurface() const {
890 if (base::win::GetVersion() < base::win::VERSION_VISTA
)
893 if (gpu_info_
.amd_switchable
)
895 if (use_swiftshader_
)
897 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
898 if (command_line
->HasSwitch(switches::kDisableImageTransportSurface
))
900 return !IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING
);
904 void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIs(
905 const GURL
& url
, GpuDataManagerImpl::DomainGuilt guilt
) {
906 BlockDomainFrom3DAPIsAtTime(url
, guilt
, base::Time::Now());
909 bool GpuDataManagerImplPrivate::Are3DAPIsBlocked(const GURL
& url
,
910 int render_process_id
,
912 ThreeDAPIType requester
) {
913 bool blocked
= Are3DAPIsBlockedAtTime(url
, base::Time::Now()) !=
914 GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED
;
916 // Unretained is ok, because it's posted to UI thread, the thread
917 // where the singleton GpuDataManagerImpl lives until the end.
918 BrowserThread::PostTask(
919 BrowserThread::UI
, FROM_HERE
,
920 base::Bind(&GpuDataManagerImpl::Notify3DAPIBlocked
,
921 base::Unretained(owner_
), url
, render_process_id
,
922 render_view_id
, requester
));
928 void GpuDataManagerImplPrivate::DisableDomainBlockingFor3DAPIsForTesting() {
929 domain_blocking_enabled_
= false;
933 GpuDataManagerImplPrivate
* GpuDataManagerImplPrivate::Create(
934 GpuDataManagerImpl
* owner
) {
935 return new GpuDataManagerImplPrivate(owner
);
938 GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(
939 GpuDataManagerImpl
* owner
)
940 : complete_gpu_info_already_requested_(false),
941 gpu_switching_(gpu::GPU_SWITCHING_OPTION_AUTOMATIC
),
942 observer_list_(new GpuDataManagerObserverList
),
943 use_swiftshader_(false),
944 card_blacklisted_(false),
945 update_histograms_(true),
947 domain_blocking_enabled_(true),
950 gpu_process_accessible_(true) {
952 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
953 if (command_line
->HasSwitch(switches::kDisableAcceleratedCompositing
)) {
954 command_line
->AppendSwitch(switches::kDisableAccelerated2dCanvas
);
955 command_line
->AppendSwitch(switches::kDisableAcceleratedLayers
);
957 if (command_line
->HasSwitch(switches::kDisableGpu
))
958 DisableHardwareAcceleration();
959 if (command_line
->HasSwitch(switches::kGpuSwitching
)) {
960 std::string option_string
= command_line
->GetSwitchValueASCII(
961 switches::kGpuSwitching
);
962 gpu::GpuSwitchingOption option
=
963 gpu::StringToGpuSwitchingOption(option_string
);
964 if (option
!= gpu::GPU_SWITCHING_OPTION_UNKNOWN
)
965 gpu_switching_
= option
;
968 #if defined(OS_MACOSX)
969 CGGetActiveDisplayList (0, NULL
, &display_count_
);
970 CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback
, owner_
);
974 GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() {
975 #if defined(OS_MACOSX)
976 CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback
, owner_
);
980 void GpuDataManagerImplPrivate::InitializeImpl(
981 const std::string
& gpu_blacklist_json
,
982 const std::string
& gpu_switching_list_json
,
983 const std::string
& gpu_driver_bug_list_json
,
984 const gpu::GPUInfo
& gpu_info
) {
985 std::string browser_version_string
= ProcessVersionString(
986 GetContentClient()->GetProduct());
987 CHECK(!browser_version_string
.empty());
989 if (!gpu_blacklist_json
.empty()) {
990 gpu_blacklist_
.reset(gpu::GpuBlacklist::Create());
991 gpu_blacklist_
->LoadList(
992 browser_version_string
, gpu_blacklist_json
,
993 gpu::GpuControlList::kCurrentOsOnly
);
995 if (!gpu_switching_list_json
.empty()) {
996 gpu_switching_list_
.reset(gpu::GpuSwitchingList::Create());
997 gpu_switching_list_
->LoadList(
998 browser_version_string
, gpu_switching_list_json
,
999 gpu::GpuControlList::kCurrentOsOnly
);
1001 if (!gpu_driver_bug_list_json
.empty()) {
1002 gpu_driver_bug_list_
.reset(gpu::GpuDriverBugList::Create());
1003 gpu_driver_bug_list_
->LoadList(
1004 browser_version_string
, gpu_driver_bug_list_json
,
1005 gpu::GpuControlList::kCurrentOsOnly
);
1008 gpu_info_
= gpu_info
;
1009 UpdateGpuInfo(gpu_info
);
1010 UpdateGpuSwitchingManager(gpu_info
);
1011 UpdatePreliminaryBlacklistedFeatures();
1013 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
1014 // We pass down the list to GPU command buffer through commandline
1015 // switches at GPU process launch. However, in situations where we don't
1016 // have a GPU process, we append the browser process commandline.
1017 if (command_line
->HasSwitch(switches::kSingleProcess
) ||
1018 command_line
->HasSwitch(switches::kInProcessGPU
)) {
1019 if (!gpu_driver_bugs_
.empty()) {
1020 command_line
->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds
,
1021 IntSetToString(gpu_driver_bugs_
));
1024 #if defined(OS_ANDROID)
1025 ApplyAndroidWorkarounds(gpu_info
, command_line
);
1026 #endif // OS_ANDROID
1029 void GpuDataManagerImplPrivate::UpdateBlacklistedFeatures(
1030 const std::set
<int>& features
) {
1031 CommandLine
* command_line
= CommandLine::ForCurrentProcess();
1032 blacklisted_features_
= features
;
1034 // Force disable using the GPU for these features, even if they would
1035 // otherwise be allowed.
1036 if (card_blacklisted_
||
1037 command_line
->HasSwitch(switches::kBlacklistAcceleratedCompositing
)) {
1038 blacklisted_features_
.insert(
1039 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING
);
1041 if (card_blacklisted_
||
1042 command_line
->HasSwitch(switches::kBlacklistWebGL
)) {
1043 blacklisted_features_
.insert(gpu::GPU_FEATURE_TYPE_WEBGL
);
1046 EnableSwiftShaderIfNecessary();
1049 void GpuDataManagerImplPrivate::UpdatePreliminaryBlacklistedFeatures() {
1050 preliminary_blacklisted_features_
= blacklisted_features_
;
1053 void GpuDataManagerImplPrivate::UpdateGpuSwitchingManager(
1054 const gpu::GPUInfo
& gpu_info
) {
1055 ui::GpuSwitchingManager::GetInstance()->SetGpuCount(
1056 gpu_info
.secondary_gpus
.size() + 1);
1058 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) {
1059 switch (gpu_switching_
) {
1060 case gpu::GPU_SWITCHING_OPTION_FORCE_DISCRETE
:
1061 ui::GpuSwitchingManager::GetInstance()->ForceUseOfDiscreteGpu();
1063 case gpu::GPU_SWITCHING_OPTION_FORCE_INTEGRATED
:
1064 ui::GpuSwitchingManager::GetInstance()->ForceUseOfIntegratedGpu();
1066 case gpu::GPU_SWITCHING_OPTION_AUTOMATIC
:
1067 case gpu::GPU_SWITCHING_OPTION_UNKNOWN
:
1073 void GpuDataManagerImplPrivate::NotifyGpuInfoUpdate() {
1074 observer_list_
->Notify(&GpuDataManagerObserver::OnGpuInfoUpdate
);
1077 void GpuDataManagerImplPrivate::EnableSwiftShaderIfNecessary() {
1078 if (!GpuAccessAllowed(NULL
) ||
1079 blacklisted_features_
.count(gpu::GPU_FEATURE_TYPE_WEBGL
)) {
1080 if (!swiftshader_path_
.empty() &&
1081 !CommandLine::ForCurrentProcess()->HasSwitch(
1082 switches::kDisableSoftwareRasterizer
))
1083 use_swiftshader_
= true;
1087 std::string
GpuDataManagerImplPrivate::GetDomainFromURL(
1088 const GURL
& url
) const {
1089 // For the moment, we just use the host, or its IP address, as the
1090 // entry in the set, rather than trying to figure out the top-level
1091 // domain. This does mean that a.foo.com and b.foo.com will be
1092 // treated independently in the blocking of a given domain, but it
1093 // would require a third-party library to reliably figure out the
1094 // top-level domain from a URL.
1095 if (!url
.has_host()) {
1096 return std::string();
1102 void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIsAtTime(
1104 GpuDataManagerImpl::DomainGuilt guilt
,
1105 base::Time at_time
) {
1106 if (!domain_blocking_enabled_
)
1109 std::string domain
= GetDomainFromURL(url
);
1111 DomainBlockEntry
& entry
= blocked_domains_
[domain
];
1112 entry
.last_guilt
= guilt
;
1113 timestamps_of_gpu_resets_
.push_back(at_time
);
1116 GpuDataManagerImpl::DomainBlockStatus
1117 GpuDataManagerImplPrivate::Are3DAPIsBlockedAtTime(
1118 const GURL
& url
, base::Time at_time
) const {
1119 if (!domain_blocking_enabled_
)
1120 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED
;
1122 // Note: adjusting the policies in this code will almost certainly
1123 // require adjusting the associated unit tests.
1124 std::string domain
= GetDomainFromURL(url
);
1126 DomainBlockMap::const_iterator iter
= blocked_domains_
.find(domain
);
1127 if (iter
!= blocked_domains_
.end()) {
1128 // Err on the side of caution, and assume that if a particular
1129 // domain shows up in the block map, it's there for a good
1130 // reason and don't let its presence there automatically expire.
1132 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1133 BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED
,
1136 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED
;
1139 // Look at the timestamps of the recent GPU resets to see if there are
1140 // enough within the threshold which would cause us to blacklist all
1141 // domains. This doesn't need to be overly precise -- if time goes
1142 // backward due to a system clock adjustment, that's fine.
1144 // TODO(kbr): make this pay attention to the TDR thresholds in the
1145 // Windows registry, but make sure it continues to be testable.
1147 std::list
<base::Time
>::iterator iter
= timestamps_of_gpu_resets_
.begin();
1148 int num_resets_within_timeframe
= 0;
1149 while (iter
!= timestamps_of_gpu_resets_
.end()) {
1150 base::Time time
= *iter
;
1151 base::TimeDelta delta_t
= at_time
- time
;
1153 // If this entry has "expired", just remove it.
1154 if (delta_t
.InMilliseconds() > kBlockAllDomainsMs
) {
1155 iter
= timestamps_of_gpu_resets_
.erase(iter
);
1159 ++num_resets_within_timeframe
;
1163 if (num_resets_within_timeframe
>= kNumResetsWithinDuration
) {
1164 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1165 BLOCK_STATUS_ALL_DOMAINS_BLOCKED
,
1168 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED
;
1172 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1173 BLOCK_STATUS_NOT_BLOCKED
,
1176 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED
;
1179 int64
GpuDataManagerImplPrivate::GetBlockAllDomainsDurationInMs() const {
1180 return kBlockAllDomainsMs
;
1183 void GpuDataManagerImplPrivate::Notify3DAPIBlocked(const GURL
& url
,
1184 int render_process_id
,
1186 ThreeDAPIType requester
) {
1187 GpuDataManagerImpl::UnlockedSession
session(owner_
);
1188 observer_list_
->Notify(&GpuDataManagerObserver::DidBlock3DAPIs
,
1189 url
, render_process_id
, render_view_id
, requester
);
1192 void GpuDataManagerImplPrivate::OnGpuProcessInitFailure() {
1193 gpu_process_accessible_
= false;
1194 gpu_info_
.finalized
= true;
1195 complete_gpu_info_already_requested_
= true;
1196 // Some observers might be waiting.
1197 NotifyGpuInfoUpdate();
1200 } // namespace content