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/metrics/sparse_histogram.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/sys_info.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 "gpu/command_buffer/service/gpu_switches.h"
27 #include "gpu/config/gpu_control_list_jsons.h"
28 #include "gpu/config/gpu_driver_bug_workaround_type.h"
29 #include "gpu/config/gpu_feature_type.h"
30 #include "gpu/config/gpu_info_collector.h"
31 #include "gpu/config/gpu_util.h"
32 #include "ui/base/ui_base_switches.h"
33 #include "ui/gl/gl_implementation.h"
34 #include "ui/gl/gl_switches.h"
35 #include "ui/gl/gpu_switching_manager.h"
36 #include "webkit/common/webpreferences.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
70 int GetGpuBlacklistHistogramValueWin(GpuFeatureStatus status) {
71 static WinSubVersion sub_version = kNumWinSubVersions;
72 if (sub_version == kNumWinSubVersions) {
73 sub_version = kWinOthers;
74 std::string version_str = base::SysInfo::OperatingSystemVersion();
75 size_t pos = version_str.find_first_not_of("0123456789.");
76 if (pos != std::string::npos)
77 version_str = version_str.substr(0, pos);
78 Version os_version(version_str);
79 if (os_version.IsValid() && os_version.components().size() >= 2) {
80 const std::vector<uint16>& version_numbers = os_version.components();
81 if (version_numbers[0] == 5)
83 else if (version_numbers[0] == 6 && version_numbers[1] == 0)
84 sub_version = kWinVista;
85 else if (version_numbers[0] == 6 && version_numbers[1] == 1)
87 else if (version_numbers[0] == 6 && version_numbers[1] == 2)
91 int entry_index = static_cast<int>(sub_version) * kGpuFeatureNumStatus;
93 case kGpuFeatureEnabled:
95 case kGpuFeatureBlacklisted:
98 case kGpuFeatureDisabled:
106 // Send UMA histograms about the enabled features and GPU properties.
107 void UpdateStats(const gpu::GPUInfo& gpu_info,
108 const gpu::GpuBlacklist* blacklist,
109 const std::set<int>& blacklisted_features) {
110 uint32 max_entry_id = blacklist->max_entry_id();
111 if (max_entry_id == 0) {
112 // GPU Blacklist was not loaded. No need to go further.
116 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
117 bool disabled = false;
119 // Use entry 0 to capture the total number of times that data
120 // was recorded in this histogram in order to have a convenient
121 // denominator to compute blacklist percentages for the rest of the
123 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry",
124 0, max_entry_id + 1);
126 if (blacklisted_features.size() != 0) {
127 std::vector<uint32> flag_entries;
128 blacklist->GetDecisionEntries(&flag_entries, disabled);
129 DCHECK_GT(flag_entries.size(), 0u);
130 for (size_t i = 0; i < flag_entries.size(); ++i) {
131 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry",
132 flag_entries[i], max_entry_id + 1);
136 // This counts how many users are affected by a disabled entry - this allows
137 // us to understand the impact of an entry before enable it.
138 std::vector<uint32> flag_disabled_entries;
140 blacklist->GetDecisionEntries(&flag_disabled_entries, disabled);
141 for (size_t i = 0; i < flag_disabled_entries.size(); ++i) {
142 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerDisabledEntry",
143 flag_disabled_entries[i], max_entry_id + 1);
146 const gpu::GpuFeatureType kGpuFeatures[] = {
147 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS,
148 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING,
149 gpu::GPU_FEATURE_TYPE_WEBGL,
150 gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING
152 const std::string kGpuBlacklistFeatureHistogramNames[] = {
153 "GPU.BlacklistFeatureTestResults.Accelerated2dCanvas",
154 "GPU.BlacklistFeatureTestResults.AcceleratedCompositing",
155 "GPU.BlacklistFeatureTestResults.Webgl",
156 "GPU.BlacklistFeatureTestResults.TextureSharing"
158 const bool kGpuFeatureUserFlags[] = {
159 command_line.HasSwitch(switches::kDisableAccelerated2dCanvas),
160 command_line.HasSwitch(switches::kDisableAcceleratedCompositing),
161 command_line.HasSwitch(switches::kDisableExperimentalWebGL),
162 command_line.HasSwitch(switches::kDisableImageTransportSurface)
165 const std::string kGpuBlacklistFeatureHistogramNamesWin[] = {
166 "GPU.BlacklistFeatureTestResultsWindows.Accelerated2dCanvas",
167 "GPU.BlacklistFeatureTestResultsWindows.AcceleratedCompositing",
168 "GPU.BlacklistFeatureTestResultsWindows.Webgl",
169 "GPU.BlacklistFeatureTestResultsWindows.TextureSharing"
172 const size_t kNumFeatures =
173 sizeof(kGpuFeatures) / sizeof(gpu::GpuFeatureType);
174 for (size_t i = 0; i < kNumFeatures; ++i) {
175 // We can't use UMA_HISTOGRAM_ENUMERATION here because the same name is
176 // expected if the macro is used within a loop.
177 GpuFeatureStatus value = kGpuFeatureEnabled;
178 if (blacklisted_features.count(kGpuFeatures[i]))
179 value = kGpuFeatureBlacklisted;
180 else if (kGpuFeatureUserFlags[i])
181 value = kGpuFeatureDisabled;
182 base::HistogramBase* histogram_pointer = base::LinearHistogram::FactoryGet(
183 kGpuBlacklistFeatureHistogramNames[i],
184 1, kGpuFeatureNumStatus, kGpuFeatureNumStatus + 1,
185 base::HistogramBase::kUmaTargetedHistogramFlag);
186 histogram_pointer->Add(value);
188 histogram_pointer = base::LinearHistogram::FactoryGet(
189 kGpuBlacklistFeatureHistogramNamesWin[i],
190 1, kNumWinSubVersions * kGpuFeatureNumStatus,
191 kNumWinSubVersions * kGpuFeatureNumStatus + 1,
192 base::HistogramBase::kUmaTargetedHistogramFlag);
193 histogram_pointer->Add(GetGpuBlacklistHistogramValueWin(value));
197 UMA_HISTOGRAM_SPARSE_SLOWLY("GPU.GLResetNotificationStrategy",
198 gpu_info.gl_reset_notification_strategy);
201 // Strip out the non-digital info; if after that, we get an empty string,
203 std::string ProcessVersionString(const std::string& raw_string) {
204 const std::string valid_set = "0123456789.";
205 size_t start_pos = raw_string.find_first_of(valid_set);
206 if (start_pos == std::string::npos)
208 size_t end_pos = raw_string.find_first_not_of(raw_string, start_pos);
209 std::string version_string = raw_string.substr(
210 start_pos, end_pos - start_pos);
211 if (version_string.empty())
213 return version_string;
216 // Combine the integers into a string, seperated by ','.
217 std::string IntSetToString(const std::set<int>& list) {
219 for (std::set<int>::const_iterator it = list.begin();
220 it != list.end(); ++it) {
223 rt += base::IntToString(*it);
228 #if defined(OS_MACOSX)
229 void DisplayReconfigCallback(CGDirectDisplayID display,
230 CGDisplayChangeSummaryFlags flags,
231 void* gpu_data_manager) {
232 if (flags == kCGDisplayBeginConfigurationFlag)
233 return; // This call contains no information about the display change
235 GpuDataManagerImpl* manager =
236 reinterpret_cast<GpuDataManagerImpl*>(gpu_data_manager);
239 uint32_t displayCount;
240 CGGetActiveDisplayList(0, NULL, &displayCount);
242 bool fireGpuSwitch = flags & kCGDisplayAddFlag;
244 if (displayCount != manager->GetDisplayCount()) {
245 manager->SetDisplayCount(displayCount);
246 fireGpuSwitch = true;
250 manager->HandleGpuSwitch();
254 #if defined(OS_ANDROID)
255 void ApplyAndroidWorkarounds(const gpu::GPUInfo& gpu_info,
256 CommandLine* command_line) {
257 std::string vendor(StringToLowerASCII(gpu_info.gl_vendor));
258 std::string renderer(StringToLowerASCII(gpu_info.gl_renderer));
260 gpu_info.gl_vendor.find("Imagination") != std::string::npos;
262 gfx::DeviceDisplayInfo info;
263 int default_tile_size = 256;
265 // For very high resolution displays (eg. Nexus 10), set the default
266 // tile size to be 512. This should be removed in favour of a generic
267 // hueristic that works across all platforms and devices, once that
268 // exists: http://crbug.com/159524. This switches to 512 for screens
269 // containing 40 or more 256x256 tiles, such that 1080p devices do
270 // not use 512x512 tiles (eg. 1920x1280 requires 37.5 tiles)
271 int numTiles = (info.GetDisplayWidth() *
272 info.GetDisplayHeight()) / (256 * 256);
274 default_tile_size = 512;
276 // IMG: Fast async texture uploads only work with non-power-of-two,
277 // but still multiple-of-eight sizes.
278 // http://crbug.com/168099
280 default_tile_size -= 8;
282 // Set the command line if it isn't already set and we changed
283 // the default tile size.
284 if (default_tile_size != 256 &&
285 !command_line->HasSwitch(switches::kDefaultTileWidth) &&
286 !command_line->HasSwitch(switches::kDefaultTileHeight)) {
287 std::stringstream size;
288 size << default_tile_size;
289 command_line->AppendSwitchASCII(
290 switches::kDefaultTileWidth, size.str());
291 command_line->AppendSwitchASCII(
292 switches::kDefaultTileHeight, size.str());
297 // Block all domains' use of 3D APIs for this many milliseconds if
298 // approaching a threshold where system stability might be compromised.
299 const int64 kBlockAllDomainsMs = 10000;
300 const int kNumResetsWithinDuration = 1;
302 // Enums for UMA histograms.
303 enum BlockStatusHistogram {
304 BLOCK_STATUS_NOT_BLOCKED,
305 BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED,
306 BLOCK_STATUS_ALL_DOMAINS_BLOCKED,
310 } // namespace anonymous
312 void GpuDataManagerImplPrivate::InitializeForTesting(
313 const std::string& gpu_blacklist_json,
314 const gpu::GPUInfo& gpu_info) {
315 // This function is for testing only, so disable histograms.
316 update_histograms_ = false;
318 // Prevent all further initialization.
321 InitializeImpl(gpu_blacklist_json, std::string(), std::string(), gpu_info);
324 bool GpuDataManagerImplPrivate::IsFeatureBlacklisted(int feature) const {
325 if (CommandLine::ForCurrentProcess()->HasSwitch("chrome-frame") &&
326 feature == gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING)
328 #if defined(OS_CHROMEOS)
329 if (feature == gpu::GPU_FEATURE_TYPE_PANEL_FITTING &&
330 CommandLine::ForCurrentProcess()->HasSwitch(
331 switches::kDisablePanelFitting)) {
334 #endif // OS_CHROMEOS
335 if (use_swiftshader_) {
336 // Skia's software rendering is probably more efficient than going through
337 // software emulation of the GPU, so use that.
338 if (feature == gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)
343 return (blacklisted_features_.count(feature) == 1);
346 bool GpuDataManagerImplPrivate::IsDriverBugWorkaroundActive(int feature) const {
347 return (gpu_driver_bugs_.count(feature) == 1);
350 size_t GpuDataManagerImplPrivate::GetBlacklistedFeatureCount() const {
351 if (use_swiftshader_)
353 return blacklisted_features_.size();
356 void GpuDataManagerImplPrivate::SetDisplayCount(unsigned int display_count) {
357 display_count_ = display_count;
360 unsigned int GpuDataManagerImplPrivate::GetDisplayCount() const {
361 return display_count_;
364 gpu::GPUInfo GpuDataManagerImplPrivate::GetGPUInfo() const {
368 void GpuDataManagerImplPrivate::GetGpuProcessHandles(
369 const GpuDataManager::GetGpuProcessHandlesCallback& callback) const {
370 GpuProcessHost::GetProcessHandles(callback);
373 bool GpuDataManagerImplPrivate::GpuAccessAllowed(
374 std::string* reason) const {
375 if (use_swiftshader_)
378 if (!gpu_process_accessible_) {
380 *reason = "GPU process launch failed.";
385 if (card_blacklisted_) {
387 *reason = "GPU access is disabled ";
388 CommandLine* command_line = CommandLine::ForCurrentProcess();
389 if (command_line->HasSwitch(switches::kDisableGpu))
390 *reason += "through commandline switch --disable-gpu.";
392 *reason += "in chrome://settings.";
397 // We only need to block GPU process if more features are disallowed other
398 // than those in the preliminary gpu feature flags because the latter work
399 // through renderer commandline switches.
400 std::set<int> features = preliminary_blacklisted_features_;
401 gpu::MergeFeatureSets(&features, blacklisted_features_);
402 if (features.size() > preliminary_blacklisted_features_.size()) {
404 *reason = "Features are disabled upon full but not preliminary GPU info.";
409 if (blacklisted_features_.size() == gpu::NUMBER_OF_GPU_FEATURE_TYPES) {
410 // On Linux, we use cached GL strings to make blacklist decsions at browser
411 // startup time. We need to launch the GPU process to validate these
412 // strings even if all features are blacklisted. If all GPU features are
413 // disabled, the GPU process will only initialize GL bindings, create a GL
414 // context, and collect full GPU info.
415 #if !defined(OS_LINUX)
417 *reason = "All GPU features are blacklisted.";
426 void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
427 if (complete_gpu_info_already_requested_ || gpu_info_.finalized)
429 complete_gpu_info_already_requested_ = true;
431 GpuProcessHost::SendOnIO(
433 GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED,
435 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
437 CAUSE_FOR_GPU_LAUNCH_GPUDATAMANAGER_REQUESTCOMPLETEGPUINFOIFNEEDED,
438 new GpuMsg_CollectGraphicsInfo());
441 bool GpuDataManagerImplPrivate::IsCompleteGpuInfoAvailable() const {
442 return gpu_info_.finalized;
445 void GpuDataManagerImplPrivate::RequestVideoMemoryUsageStatsUpdate() const {
446 GpuProcessHost::SendOnIO(
447 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
448 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
449 new GpuMsg_GetVideoMemoryUsageStats());
452 bool GpuDataManagerImplPrivate::ShouldUseSwiftShader() const {
453 return use_swiftshader_;
456 void GpuDataManagerImplPrivate::RegisterSwiftShaderPath(
457 const base::FilePath& path) {
458 swiftshader_path_ = path;
459 EnableSwiftShaderIfNecessary();
462 void GpuDataManagerImplPrivate::AddObserver(GpuDataManagerObserver* observer) {
463 GpuDataManagerImpl::UnlockedSession session(owner_);
464 observer_list_->AddObserver(observer);
467 void GpuDataManagerImplPrivate::RemoveObserver(
468 GpuDataManagerObserver* observer) {
469 GpuDataManagerImpl::UnlockedSession session(owner_);
470 observer_list_->RemoveObserver(observer);
473 void GpuDataManagerImplPrivate::UnblockDomainFrom3DAPIs(const GURL& url) {
474 // This method must do two things:
476 // 1. If the specific domain is blocked, then unblock it.
478 // 2. Reset our notion of how many GPU resets have occurred recently.
479 // This is necessary even if the specific domain was blocked.
480 // Otherwise, if we call Are3DAPIsBlocked with the same domain right
481 // after unblocking it, it will probably still be blocked because of
482 // the recent GPU reset caused by that domain.
484 // These policies could be refined, but at a certain point the behavior
485 // will become difficult to explain.
486 std::string domain = GetDomainFromURL(url);
488 blocked_domains_.erase(domain);
489 timestamps_of_gpu_resets_.clear();
492 void GpuDataManagerImplPrivate::DisableGpuWatchdog() {
493 GpuProcessHost::SendOnIO(
494 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
495 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
496 new GpuMsg_DisableWatchdog);
499 void GpuDataManagerImplPrivate::SetGLStrings(const std::string& gl_vendor,
500 const std::string& gl_renderer,
501 const std::string& gl_version) {
502 if (gl_vendor.empty() && gl_renderer.empty() && gl_version.empty())
505 // If GPUInfo already got GL strings, do nothing. This is for the rare
506 // situation where GPU process collected GL strings before this call.
507 if (!gpu_info_.gl_vendor.empty() ||
508 !gpu_info_.gl_renderer.empty() ||
509 !gpu_info_.gl_version_string.empty())
512 gpu::GPUInfo gpu_info = gpu_info_;
514 gpu_info.gl_vendor = gl_vendor;
515 gpu_info.gl_renderer = gl_renderer;
516 gpu_info.gl_version_string = gl_version;
518 gpu::CollectDriverInfoGL(&gpu_info);
520 UpdateGpuInfo(gpu_info);
521 UpdateGpuSwitchingManager(gpu_info);
522 UpdatePreliminaryBlacklistedFeatures();
525 void GpuDataManagerImplPrivate::GetGLStrings(std::string* gl_vendor,
526 std::string* gl_renderer,
527 std::string* gl_version) {
528 DCHECK(gl_vendor && gl_renderer && gl_version);
530 *gl_vendor = gpu_info_.gl_vendor;
531 *gl_renderer = gpu_info_.gl_renderer;
532 *gl_version = gpu_info_.gl_version_string;
535 void GpuDataManagerImplPrivate::Initialize() {
536 TRACE_EVENT0("startup", "GpuDataManagerImpl::Initialize");
538 DLOG(INFO) << "GpuDataManagerImpl marked as finalized; skipping Initialize";
542 const CommandLine* command_line = CommandLine::ForCurrentProcess();
543 if (command_line->HasSwitch(switches::kSkipGpuDataLoading))
546 gpu::GPUInfo gpu_info;
547 if (command_line->GetSwitchValueASCII(
548 switches::kUseGL) == gfx::kGLImplementationOSMesaName) {
549 // If using the OSMesa GL implementation, use fake vendor and device ids to
550 // make sure it never gets blacklisted. This is better than simply
551 // cancelling GPUInfo gathering as it allows us to proceed with loading the
552 // blacklist below which may have non-device specific entries we want to
553 // apply anyways (e.g., OS version blacklisting).
554 gpu_info.gpu.vendor_id = 0xffff;
555 gpu_info.gpu.device_id = 0xffff;
557 // Also declare the driver_vendor to be osmesa to be able to specify
558 // exceptions based on driver_vendor==osmesa for some blacklist rules.
559 gpu_info.driver_vendor = gfx::kGLImplementationOSMesaName;
561 TRACE_EVENT0("startup",
562 "GpuDataManagerImpl::Initialize:CollectBasicGraphicsInfo");
563 gpu::CollectBasicGraphicsInfo(&gpu_info);
565 #if defined(ARCH_CPU_X86_FAMILY)
566 if (!gpu_info.gpu.vendor_id || !gpu_info.gpu.device_id)
567 gpu_info.finalized = true;
570 std::string gpu_blacklist_string;
571 std::string gpu_switching_list_string;
572 std::string gpu_driver_bug_list_string;
573 if (!command_line->HasSwitch(switches::kIgnoreGpuBlacklist) &&
574 !command_line->HasSwitch(switches::kUseGpuInTests)) {
575 gpu_blacklist_string = gpu::kSoftwareRenderingListJson;
576 gpu_switching_list_string = gpu::kGpuSwitchingListJson;
578 if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
579 gpu_driver_bug_list_string = gpu::kGpuDriverBugListJson;
581 InitializeImpl(gpu_blacklist_string,
582 gpu_switching_list_string,
583 gpu_driver_bug_list_string,
587 void GpuDataManagerImplPrivate::UpdateGpuInfo(const gpu::GPUInfo& gpu_info) {
588 // No further update of gpu_info if falling back to SwiftShader.
589 if (use_swiftshader_)
592 gpu::MergeGPUInfo(&gpu_info_, gpu_info);
593 complete_gpu_info_already_requested_ =
594 complete_gpu_info_already_requested_ || gpu_info_.finalized;
596 GetContentClient()->SetGpuInfo(gpu_info_);
598 if (gpu_blacklist_) {
599 std::set<int> features = gpu_blacklist_->MakeDecision(
600 gpu::GpuControlList::kOsAny, std::string(), gpu_info_);
601 if (update_histograms_)
602 UpdateStats(gpu_info_, gpu_blacklist_.get(), features);
604 UpdateBlacklistedFeatures(features);
606 if (gpu_switching_list_) {
607 std::set<int> option = gpu_switching_list_->MakeDecision(
608 gpu::GpuControlList::kOsAny, std::string(), gpu_info_);
609 if (option.size() == 1) {
610 // Blacklist decision should not overwrite commandline switch from users.
611 CommandLine* command_line = CommandLine::ForCurrentProcess();
612 if (!command_line->HasSwitch(switches::kGpuSwitching)) {
613 gpu_switching_ = static_cast<gpu::GpuSwitchingOption>(
618 if (gpu_driver_bug_list_) {
619 gpu_driver_bugs_ = gpu_driver_bug_list_->MakeDecision(
620 gpu::GpuControlList::kOsAny, std::string(), gpu_info_);
623 // We have to update GpuFeatureType before notify all the observers.
624 NotifyGpuInfoUpdate();
627 void GpuDataManagerImplPrivate::UpdateVideoMemoryUsageStats(
628 const GPUVideoMemoryUsageStats& video_memory_usage_stats) {
629 GpuDataManagerImpl::UnlockedSession session(owner_);
630 observer_list_->Notify(&GpuDataManagerObserver::OnVideoMemoryUsageStatsUpdate,
631 video_memory_usage_stats);
634 void GpuDataManagerImplPrivate::AppendRendererCommandLine(
635 CommandLine* command_line) const {
636 DCHECK(command_line);
638 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL)) {
639 if (!command_line->HasSwitch(switches::kDisableExperimentalWebGL))
640 command_line->AppendSwitch(switches::kDisableExperimentalWebGL);
641 if (!command_line->HasSwitch(switches::kDisablePepper3d))
642 command_line->AppendSwitch(switches::kDisablePepper3d);
644 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_MULTISAMPLING) &&
645 !command_line->HasSwitch(switches::kDisableGLMultisampling))
646 command_line->AppendSwitch(switches::kDisableGLMultisampling);
647 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) &&
648 !command_line->HasSwitch(switches::kDisableAcceleratedCompositing))
649 command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
650 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS) &&
651 !command_line->HasSwitch(switches::kDisableAccelerated2dCanvas))
652 command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
653 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) &&
654 !command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode))
655 command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
657 if (use_software_compositor_ &&
658 !command_line->HasSwitch(switches::kEnableSoftwareCompositing))
659 command_line->AppendSwitch(switches::kEnableSoftwareCompositing);
661 #if defined(USE_AURA)
662 if (!CanUseGpuBrowserCompositor()) {
663 command_line->AppendSwitch(switches::kDisableGpuCompositing);
664 command_line->AppendSwitch(switches::kDisablePepper3d);
669 void GpuDataManagerImplPrivate::AppendGpuCommandLine(
670 CommandLine* command_line) const {
671 DCHECK(command_line);
673 bool reduce_sandbox = false;
676 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL);
677 base::FilePath swiftshader_path =
678 CommandLine::ForCurrentProcess()->GetSwitchValuePath(
679 switches::kSwiftShaderPath);
680 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_MULTISAMPLING) &&
681 !command_line->HasSwitch(switches::kDisableGLMultisampling)) {
682 command_line->AppendSwitch(switches::kDisableGLMultisampling);
684 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING)) {
685 command_line->AppendSwitch(switches::kDisableImageTransportSurface);
687 if (gpu_driver_bugs_.find(gpu::DISABLE_D3D11) != gpu_driver_bugs_.end())
688 command_line->AppendSwitch(switches::kDisableD3D11);
689 if (use_swiftshader_) {
690 command_line->AppendSwitchASCII(switches::kUseGL, "swiftshader");
691 if (swiftshader_path.empty())
692 swiftshader_path = swiftshader_path_;
693 } else if ((IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL) ||
694 IsFeatureBlacklisted(
695 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) ||
696 IsFeatureBlacklisted(
697 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)) &&
699 command_line->AppendSwitchASCII(
700 switches::kUseGL, gfx::kGLImplementationOSMesaName);
701 } else if (!use_gl.empty()) {
702 command_line->AppendSwitchASCII(switches::kUseGL, use_gl);
704 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) {
705 command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "true");
706 switch (gpu_switching_) {
707 case gpu::GPU_SWITCHING_OPTION_FORCE_DISCRETE:
708 command_line->AppendSwitchASCII(switches::kGpuSwitching,
709 switches::kGpuSwitchingOptionNameForceDiscrete);
711 case gpu::GPU_SWITCHING_OPTION_FORCE_INTEGRATED:
712 command_line->AppendSwitchASCII(switches::kGpuSwitching,
713 switches::kGpuSwitchingOptionNameForceIntegrated);
715 case gpu::GPU_SWITCHING_OPTION_AUTOMATIC:
716 case gpu::GPU_SWITCHING_OPTION_UNKNOWN:
720 command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "false");
723 if (!swiftshader_path.empty()) {
724 command_line->AppendSwitchPath(switches::kSwiftShaderPath,
728 if (!gpu_driver_bugs_.empty()) {
729 command_line->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds,
730 IntSetToString(gpu_driver_bugs_));
733 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) &&
734 !command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) {
735 command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
739 // DisplayLink 7.1 and earlier can cause the GPU process to crash on startup.
740 // http://crbug.com/177611
741 // Thinkpad USB Port Replicator driver causes GPU process to crash when the
742 // sandbox is enabled. http://crbug.com/181665.
743 if ((gpu_info_.display_link_version.IsValid()
744 && gpu_info_.display_link_version.IsOlderThan("7.2")) ||
745 gpu_info_.lenovo_dcute) {
746 reduce_sandbox = true;
750 if (gpu_info_.optimus)
751 reduce_sandbox = true;
754 command_line->AppendSwitch(switches::kReduceGpuSandbox);
756 // Pass GPU and driver information to GPU process. We try to avoid full GPU
757 // info collection at GPU process startup, but we need gpu vendor_id,
758 // device_id, driver_vendor, driver_version for deciding whether we need to
759 // collect full info (on Linux) and for crash reporting purpose.
760 command_line->AppendSwitchASCII(switches::kGpuVendorID,
761 base::StringPrintf("0x%04x", gpu_info_.gpu.vendor_id));
762 command_line->AppendSwitchASCII(switches::kGpuDeviceID,
763 base::StringPrintf("0x%04x", gpu_info_.gpu.device_id));
764 command_line->AppendSwitchASCII(switches::kGpuDriverVendor,
765 gpu_info_.driver_vendor);
766 command_line->AppendSwitchASCII(switches::kGpuDriverVersion,
767 gpu_info_.driver_version);
770 void GpuDataManagerImplPrivate::AppendPluginCommandLine(
771 CommandLine* command_line) const {
772 DCHECK(command_line);
774 #if defined(OS_MACOSX)
775 // TODO(jbauman): Add proper blacklist support for core animation plugins so
776 // special-casing this video card won't be necessary. See
777 // http://crbug.com/134015
778 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) ||
779 CommandLine::ForCurrentProcess()->HasSwitch(
780 switches::kDisableAcceleratedCompositing)) {
781 if (!command_line->HasSwitch(
782 switches::kDisableCoreAnimationPlugins))
783 command_line->AppendSwitch(
784 switches::kDisableCoreAnimationPlugins);
789 void GpuDataManagerImplPrivate::UpdateRendererWebPrefs(
790 WebPreferences* prefs) const {
793 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING))
794 prefs->accelerated_compositing_enabled = false;
795 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL))
796 prefs->experimental_webgl_enabled = false;
797 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH3D))
798 prefs->flash_3d_enabled = false;
799 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D)) {
800 prefs->flash_stage3d_enabled = false;
801 prefs->flash_stage3d_baseline_enabled = false;
803 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE))
804 prefs->flash_stage3d_baseline_enabled = false;
805 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS))
806 prefs->accelerated_2d_canvas_enabled = false;
807 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_MULTISAMPLING) ||
808 (IsDriverBugWorkaroundActive(gpu::DISABLE_MULTIMONITOR_MULTISAMPLING) &&
810 prefs->gl_multisampling_enabled = false;
811 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_3D_CSS)) {
812 prefs->accelerated_compositing_for_3d_transforms_enabled = false;
813 prefs->accelerated_compositing_for_animation_enabled = false;
815 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO))
816 prefs->accelerated_compositing_for_video_enabled = false;
818 // Accelerated video and animation are slower than regular when using
819 // SwiftShader. 3D CSS may also be too slow to be worthwhile.
820 if (ShouldUseSwiftShader()) {
821 prefs->accelerated_compositing_for_video_enabled = false;
822 prefs->accelerated_compositing_for_animation_enabled = false;
823 prefs->accelerated_compositing_for_3d_transforms_enabled = false;
824 prefs->accelerated_compositing_for_plugins_enabled = false;
827 if (use_software_compositor_) {
828 prefs->force_compositing_mode = true;
829 prefs->accelerated_compositing_enabled = true;
830 prefs->accelerated_compositing_for_3d_transforms_enabled = true;
831 prefs->accelerated_compositing_for_plugins_enabled = true;
832 prefs->accelerated_compositing_for_video_enabled = true;
835 #if defined(USE_AURA)
836 if (!CanUseGpuBrowserCompositor())
837 prefs->accelerated_2d_canvas_enabled = false;
841 gpu::GpuSwitchingOption
842 GpuDataManagerImplPrivate::GetGpuSwitchingOption() const {
843 if (!ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus())
844 return gpu::GPU_SWITCHING_OPTION_UNKNOWN;
845 return gpu_switching_;
848 void GpuDataManagerImplPrivate::DisableHardwareAcceleration() {
849 card_blacklisted_ = true;
851 for (int i = 0; i < gpu::NUMBER_OF_GPU_FEATURE_TYPES; ++i)
852 blacklisted_features_.insert(i);
854 EnableSwiftShaderIfNecessary();
855 NotifyGpuInfoUpdate();
858 std::string GpuDataManagerImplPrivate::GetBlacklistVersion() const {
860 return gpu_blacklist_->version();
864 std::string GpuDataManagerImplPrivate::GetDriverBugListVersion() const {
865 if (gpu_driver_bug_list_)
866 return gpu_driver_bug_list_->version();
870 void GpuDataManagerImplPrivate::GetBlacklistReasons(
871 base::ListValue* reasons) const {
873 gpu_blacklist_->GetReasons(reasons);
876 void GpuDataManagerImplPrivate::GetDriverBugWorkarounds(
877 base::ListValue* workarounds) const {
878 for (std::set<int>::const_iterator it = gpu_driver_bugs_.begin();
879 it != gpu_driver_bugs_.end(); ++it) {
880 workarounds->AppendString(
881 gpu::GpuDriverBugWorkaroundTypeToString(
882 static_cast<gpu::GpuDriverBugWorkaroundType>(*it)));
886 void GpuDataManagerImplPrivate::AddLogMessage(
887 int level, const std::string& header, const std::string& message) {
888 base::DictionaryValue* dict = new base::DictionaryValue();
889 dict->SetInteger("level", level);
890 dict->SetString("header", header);
891 dict->SetString("message", message);
892 log_messages_.Append(dict);
895 void GpuDataManagerImplPrivate::ProcessCrashed(
896 base::TerminationStatus exit_code) {
897 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
898 // Unretained is ok, because it's posted to UI thread, the thread
899 // where the singleton GpuDataManagerImpl lives until the end.
900 BrowserThread::PostTask(
903 base::Bind(&GpuDataManagerImpl::ProcessCrashed,
904 base::Unretained(owner_),
909 GpuDataManagerImpl::UnlockedSession session(owner_);
910 observer_list_->Notify(
911 &GpuDataManagerObserver::OnGpuProcessCrashed, exit_code);
915 base::ListValue* GpuDataManagerImplPrivate::GetLogMessages() const {
916 base::ListValue* value;
917 value = log_messages_.DeepCopy();
921 void GpuDataManagerImplPrivate::HandleGpuSwitch() {
922 GpuDataManagerImpl::UnlockedSession session(owner_);
923 observer_list_->Notify(&GpuDataManagerObserver::OnGpuSwitching);
927 bool GpuDataManagerImplPrivate::IsUsingAcceleratedSurface() const {
928 if (base::win::GetVersion() < base::win::VERSION_VISTA)
931 if (use_swiftshader_)
933 CommandLine* command_line = CommandLine::ForCurrentProcess();
934 if (command_line->HasSwitch(switches::kDisableImageTransportSurface))
936 return !IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING);
940 bool GpuDataManagerImplPrivate::CanUseGpuBrowserCompositor() const {
941 return !ShouldUseSwiftShader() &&
942 !IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) &&
943 !IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE);
946 void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIs(
947 const GURL& url, GpuDataManagerImpl::DomainGuilt guilt) {
948 BlockDomainFrom3DAPIsAtTime(url, guilt, base::Time::Now());
951 bool GpuDataManagerImplPrivate::Are3DAPIsBlocked(const GURL& url,
952 int render_process_id,
954 ThreeDAPIType requester) {
955 bool blocked = Are3DAPIsBlockedAtTime(url, base::Time::Now()) !=
956 GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
958 // Unretained is ok, because it's posted to UI thread, the thread
959 // where the singleton GpuDataManagerImpl lives until the end.
960 BrowserThread::PostTask(
961 BrowserThread::UI, FROM_HERE,
962 base::Bind(&GpuDataManagerImpl::Notify3DAPIBlocked,
963 base::Unretained(owner_), url, render_process_id,
964 render_view_id, requester));
970 void GpuDataManagerImplPrivate::DisableDomainBlockingFor3DAPIsForTesting() {
971 domain_blocking_enabled_ = false;
975 GpuDataManagerImplPrivate* GpuDataManagerImplPrivate::Create(
976 GpuDataManagerImpl* owner) {
977 return new GpuDataManagerImplPrivate(owner);
980 GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(
981 GpuDataManagerImpl* owner)
982 : complete_gpu_info_already_requested_(false),
983 gpu_switching_(gpu::GPU_SWITCHING_OPTION_AUTOMATIC),
984 observer_list_(new GpuDataManagerObserverList),
985 use_swiftshader_(false),
986 card_blacklisted_(false),
987 update_histograms_(true),
989 domain_blocking_enabled_(true),
992 gpu_process_accessible_(true),
993 use_software_compositor_(false),
996 CommandLine* command_line = CommandLine::ForCurrentProcess();
997 if (command_line->HasSwitch(switches::kDisableAcceleratedCompositing)) {
998 command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
999 command_line->AppendSwitch(switches::kDisableAcceleratedLayers);
1001 if (command_line->HasSwitch(switches::kDisableGpu))
1002 DisableHardwareAcceleration();
1003 if (command_line->HasSwitch(switches::kEnableSoftwareCompositing))
1004 use_software_compositor_ = true;
1005 //TODO(jbauman): enable for Chrome OS and Linux
1006 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
1007 use_software_compositor_ = true;
1009 if (command_line->HasSwitch(switches::kGpuSwitching)) {
1010 std::string option_string = command_line->GetSwitchValueASCII(
1011 switches::kGpuSwitching);
1012 gpu::GpuSwitchingOption option =
1013 gpu::StringToGpuSwitchingOption(option_string);
1014 if (option != gpu::GPU_SWITCHING_OPTION_UNKNOWN)
1015 gpu_switching_ = option;
1018 #if defined(OS_MACOSX)
1019 CGGetActiveDisplayList (0, NULL, &display_count_);
1020 CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback, owner_);
1023 // For testing only.
1024 if (command_line->HasSwitch(switches::kDisableDomainBlockingFor3DAPIs)) {
1025 domain_blocking_enabled_ = false;
1029 GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() {
1030 #if defined(OS_MACOSX)
1031 CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback, owner_);
1035 void GpuDataManagerImplPrivate::InitializeImpl(
1036 const std::string& gpu_blacklist_json,
1037 const std::string& gpu_switching_list_json,
1038 const std::string& gpu_driver_bug_list_json,
1039 const gpu::GPUInfo& gpu_info) {
1040 std::string browser_version_string = ProcessVersionString(
1041 GetContentClient()->GetProduct());
1042 CHECK(!browser_version_string.empty());
1044 const bool log_gpu_control_list_decisions =
1045 CommandLine::ForCurrentProcess()->HasSwitch(
1046 switches::kLogGpuControlListDecisions);
1048 if (!gpu_blacklist_json.empty()) {
1049 gpu_blacklist_.reset(gpu::GpuBlacklist::Create());
1050 if (log_gpu_control_list_decisions)
1051 gpu_blacklist_->enable_control_list_logging("gpu_blacklist");
1052 bool success = gpu_blacklist_->LoadList(
1053 browser_version_string, gpu_blacklist_json,
1054 gpu::GpuControlList::kCurrentOsOnly);
1057 if (!gpu_switching_list_json.empty()) {
1058 gpu_switching_list_.reset(gpu::GpuSwitchingList::Create());
1059 if (log_gpu_control_list_decisions)
1060 gpu_switching_list_->enable_control_list_logging("gpu_switching_list");
1061 bool success = gpu_switching_list_->LoadList(
1062 browser_version_string, gpu_switching_list_json,
1063 gpu::GpuControlList::kCurrentOsOnly);
1066 if (!gpu_driver_bug_list_json.empty()) {
1067 gpu_driver_bug_list_.reset(gpu::GpuDriverBugList::Create());
1068 if (log_gpu_control_list_decisions)
1069 gpu_driver_bug_list_->enable_control_list_logging("gpu_driver_bug_list");
1070 bool success = gpu_driver_bug_list_->LoadList(
1071 browser_version_string, gpu_driver_bug_list_json,
1072 gpu::GpuControlList::kCurrentOsOnly);
1076 gpu_info_ = gpu_info;
1077 UpdateGpuInfo(gpu_info);
1078 UpdateGpuSwitchingManager(gpu_info);
1079 UpdatePreliminaryBlacklistedFeatures();
1081 CommandLine* command_line = CommandLine::ForCurrentProcess();
1082 // We pass down the list to GPU command buffer through commandline
1083 // switches at GPU process launch. However, in situations where we don't
1084 // have a GPU process, we append the browser process commandline.
1085 if (command_line->HasSwitch(switches::kSingleProcess) ||
1086 command_line->HasSwitch(switches::kInProcessGPU)) {
1087 if (!gpu_driver_bugs_.empty()) {
1088 command_line->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds,
1089 IntSetToString(gpu_driver_bugs_));
1092 #if defined(OS_ANDROID)
1093 ApplyAndroidWorkarounds(gpu_info, command_line);
1094 #endif // OS_ANDROID
1097 void GpuDataManagerImplPrivate::UpdateBlacklistedFeatures(
1098 const std::set<int>& features) {
1099 CommandLine* command_line = CommandLine::ForCurrentProcess();
1100 blacklisted_features_ = features;
1102 // Force disable using the GPU for these features, even if they would
1103 // otherwise be allowed.
1104 if (card_blacklisted_ ||
1105 command_line->HasSwitch(switches::kBlacklistAcceleratedCompositing)) {
1106 blacklisted_features_.insert(
1107 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING);
1109 if (card_blacklisted_ ||
1110 command_line->HasSwitch(switches::kBlacklistWebGL)) {
1111 blacklisted_features_.insert(gpu::GPU_FEATURE_TYPE_WEBGL);
1114 EnableSwiftShaderIfNecessary();
1117 void GpuDataManagerImplPrivate::UpdatePreliminaryBlacklistedFeatures() {
1118 preliminary_blacklisted_features_ = blacklisted_features_;
1121 void GpuDataManagerImplPrivate::UpdateGpuSwitchingManager(
1122 const gpu::GPUInfo& gpu_info) {
1123 ui::GpuSwitchingManager::GetInstance()->SetGpuCount(
1124 gpu_info.secondary_gpus.size() + 1);
1126 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) {
1127 switch (gpu_switching_) {
1128 case gpu::GPU_SWITCHING_OPTION_FORCE_DISCRETE:
1129 ui::GpuSwitchingManager::GetInstance()->ForceUseOfDiscreteGpu();
1131 case gpu::GPU_SWITCHING_OPTION_FORCE_INTEGRATED:
1132 ui::GpuSwitchingManager::GetInstance()->ForceUseOfIntegratedGpu();
1134 case gpu::GPU_SWITCHING_OPTION_AUTOMATIC:
1135 case gpu::GPU_SWITCHING_OPTION_UNKNOWN:
1141 void GpuDataManagerImplPrivate::NotifyGpuInfoUpdate() {
1142 observer_list_->Notify(&GpuDataManagerObserver::OnGpuInfoUpdate);
1145 void GpuDataManagerImplPrivate::EnableSwiftShaderIfNecessary() {
1146 if (!GpuAccessAllowed(NULL) ||
1147 blacklisted_features_.count(gpu::GPU_FEATURE_TYPE_WEBGL)) {
1148 if (!swiftshader_path_.empty() &&
1149 !CommandLine::ForCurrentProcess()->HasSwitch(
1150 switches::kDisableSoftwareRasterizer))
1151 use_swiftshader_ = true;
1155 std::string GpuDataManagerImplPrivate::GetDomainFromURL(
1156 const GURL& url) const {
1157 // For the moment, we just use the host, or its IP address, as the
1158 // entry in the set, rather than trying to figure out the top-level
1159 // domain. This does mean that a.foo.com and b.foo.com will be
1160 // treated independently in the blocking of a given domain, but it
1161 // would require a third-party library to reliably figure out the
1162 // top-level domain from a URL.
1163 if (!url.has_host()) {
1164 return std::string();
1170 void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIsAtTime(
1172 GpuDataManagerImpl::DomainGuilt guilt,
1173 base::Time at_time) {
1174 if (!domain_blocking_enabled_)
1177 std::string domain = GetDomainFromURL(url);
1179 DomainBlockEntry& entry = blocked_domains_[domain];
1180 entry.last_guilt = guilt;
1181 timestamps_of_gpu_resets_.push_back(at_time);
1184 GpuDataManagerImpl::DomainBlockStatus
1185 GpuDataManagerImplPrivate::Are3DAPIsBlockedAtTime(
1186 const GURL& url, base::Time at_time) const {
1187 if (!domain_blocking_enabled_)
1188 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
1190 // Note: adjusting the policies in this code will almost certainly
1191 // require adjusting the associated unit tests.
1192 std::string domain = GetDomainFromURL(url);
1194 DomainBlockMap::const_iterator iter = blocked_domains_.find(domain);
1195 if (iter != blocked_domains_.end()) {
1196 // Err on the side of caution, and assume that if a particular
1197 // domain shows up in the block map, it's there for a good
1198 // reason and don't let its presence there automatically expire.
1200 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1201 BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED,
1204 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED;
1207 // Look at the timestamps of the recent GPU resets to see if there are
1208 // enough within the threshold which would cause us to blacklist all
1209 // domains. This doesn't need to be overly precise -- if time goes
1210 // backward due to a system clock adjustment, that's fine.
1212 // TODO(kbr): make this pay attention to the TDR thresholds in the
1213 // Windows registry, but make sure it continues to be testable.
1215 std::list<base::Time>::iterator iter = timestamps_of_gpu_resets_.begin();
1216 int num_resets_within_timeframe = 0;
1217 while (iter != timestamps_of_gpu_resets_.end()) {
1218 base::Time time = *iter;
1219 base::TimeDelta delta_t = at_time - time;
1221 // If this entry has "expired", just remove it.
1222 if (delta_t.InMilliseconds() > kBlockAllDomainsMs) {
1223 iter = timestamps_of_gpu_resets_.erase(iter);
1227 ++num_resets_within_timeframe;
1231 if (num_resets_within_timeframe >= kNumResetsWithinDuration) {
1232 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1233 BLOCK_STATUS_ALL_DOMAINS_BLOCKED,
1236 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED;
1240 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1241 BLOCK_STATUS_NOT_BLOCKED,
1244 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
1247 int64 GpuDataManagerImplPrivate::GetBlockAllDomainsDurationInMs() const {
1248 return kBlockAllDomainsMs;
1251 void GpuDataManagerImplPrivate::Notify3DAPIBlocked(const GURL& url,
1252 int render_process_id,
1254 ThreeDAPIType requester) {
1255 GpuDataManagerImpl::UnlockedSession session(owner_);
1256 observer_list_->Notify(&GpuDataManagerObserver::DidBlock3DAPIs,
1257 url, render_process_id, render_view_id, requester);
1260 void GpuDataManagerImplPrivate::OnGpuProcessInitFailure() {
1261 gpu_process_accessible_ = false;
1262 gpu_info_.finalized = true;
1263 complete_gpu_info_already_requested_ = true;
1264 // Some observers might be waiting.
1265 NotifyGpuInfoUpdate();
1268 } // namespace content