Save errno for logging before potentially overwriting it.
[chromium-blink-merge.git] / content / browser / gpu / gpu_data_manager_impl_private.cc
blobb235fa8766391f8b7ffd3efaee93b45a7b0d893d
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"
7 #include "base/bind.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>
40 #endif // OS_MACOSX
41 #if defined(OS_WIN)
42 #include "base/win/windows_version.h"
43 #endif // OS_WIN
44 #if defined(OS_ANDROID)
45 #include "ui/gfx/android/device_display_info.h"
46 #endif // OS_ANDROID
48 namespace content {
50 namespace {
52 enum GpuFeatureStatus {
53 kGpuFeatureEnabled = 0,
54 kGpuFeatureBlacklisted = 1,
55 kGpuFeatureDisabled = 2, // disabled by user but not blacklisted
56 kGpuFeatureNumStatus
59 #if defined(OS_WIN)
61 enum WinSubVersion {
62 kWinOthers = 0,
63 kWinXP,
64 kWinVista,
65 kWin7,
66 kNumWinSubVersions
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)
81 sub_version = kWinXP;
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)
85 sub_version = kWin7;
88 int entry_index = static_cast<int>(sub_version) * kGpuFeatureNumStatus;
89 switch (status) {
90 case kGpuFeatureEnabled:
91 break;
92 case kGpuFeatureBlacklisted:
93 entry_index++;
94 break;
95 case kGpuFeatureDisabled:
96 entry_index += 2;
97 break;
99 return entry_index;
101 #endif // OS_WIN
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.
109 return;
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);
117 } else {
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;
130 disabled = true;
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)
152 #else
153 command_line.HasSwitch(switches::kDisableExperimentalWebGL)
154 #endif
156 #if defined(OS_WIN)
157 const std::string kGpuBlacklistFeatureHistogramNamesWin[] = {
158 "GPU.BlacklistFeatureTestResultsWindows.Accelerated2dCanvas",
159 "GPU.BlacklistFeatureTestResultsWindows.AcceleratedCompositing",
160 "GPU.BlacklistFeatureTestResultsWindows.Webgl"
162 #endif
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);
178 #if defined(OS_WIN)
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));
185 #endif
189 // Strip out the non-digital info; if after that, we get an empty string,
190 // return "0".
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)
195 return "0";
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())
200 return "0";
201 return version_string;
204 // Combine the integers into a string, seperated by ','.
205 std::string IntSetToString(const std::set<int>& list) {
206 std::string rt;
207 for (std::set<int>::const_iterator it = list.begin();
208 it != list.end(); ++it) {
209 if (!rt.empty())
210 rt += ",";
211 rt += base::IntToString(*it);
213 return rt;
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);
225 DCHECK(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;
237 if (fireGpuSwitch)
238 manager->HandleGpuSwitch();
240 #endif // OS_MACOSX
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));
247 bool is_img =
248 gpu_info.gl_vendor.find("Imagination") != std::string::npos;
249 bool is_arm =
250 gpu_info.gl_vendor.find("ARM") != std::string::npos;
251 bool is_qualcomm =
252 gpu_info.gl_vendor.find("Qualcomm") != std::string::npos;
253 bool is_broadcom =
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;
258 bool is_vivante =
259 gpu_info.gl_extensions.find("GL_VIV_shader_binary") !=
260 std::string::npos;
262 bool is_nexus7 =
263 gpu_info.machine_model.find("Nexus 7") != std::string::npos;
264 bool is_nexus10 =
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 ||
271 is_broadcom)
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);
285 if (numTiles >= 40)
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
291 if (is_img)
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");
315 #endif // OS_ANDROID
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,
327 BLOCK_STATUS_MAX
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)
346 return true;
347 return false;
350 return (blacklisted_features_.count(feature) == 1);
353 size_t GpuDataManagerImplPrivate::GetBlacklistedFeatureCount() const {
354 if (use_swiftshader_)
355 return 1;
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 {
368 return gpu_info_;
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_)
379 return true;
381 if (!gpu_process_accessible_) {
382 if (reason) {
383 *reason = "GPU process launch failed.";
385 return false;
388 if (card_blacklisted_) {
389 if (reason) {
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.";
394 else
395 *reason += "in chrome://settings.";
397 return false;
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()) {
406 if (reason) {
407 *reason = "Features are disabled upon full but not preliminary GPU info.";
409 return false;
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)
419 if (reason) {
420 *reason = "All GPU features are blacklisted.";
422 return false;
423 #endif
426 return true;
429 void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
430 if (complete_gpu_info_already_requested_ || gpu_info_.finalized)
431 return;
432 complete_gpu_info_already_requested_ = true;
434 GpuProcessHost::SendOnIO(
435 #if defined(OS_WIN)
436 GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED,
437 #else
438 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
439 #endif
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())
506 return;
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())
513 return;
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))
542 return;
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;
553 #endif
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,
568 gpu_info);
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_)
574 return;
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>(
598 *(option.begin()));
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);
626 #endif
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;
650 std::string use_gl =
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)) &&
672 (use_gl == "any")) {
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);
684 break;
685 case gpu::GPU_SWITCHING_OPTION_FORCE_INTEGRATED:
686 command_line->AppendSwitchASCII(switches::kGpuSwitching,
687 switches::kGpuSwitchingOptionNameForceIntegrated);
688 break;
689 case gpu::GPU_SWITCHING_OPTION_AUTOMATIC:
690 case gpu::GPU_SWITCHING_OPTION_UNKNOWN:
691 break;
693 } else {
694 command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "false");
697 if (!swiftshader_path.empty()) {
698 command_line->AppendSwitchPath(switches::kSwiftShaderPath,
699 swiftshader_path);
702 if (!gpu_driver_bugs_.empty()) {
703 command_line->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds,
704 IntSetToString(gpu_driver_bugs_));
707 #if defined(OS_WIN)
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;
717 #endif
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);
729 if (reduce_sandbox)
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);
762 #endif
765 void GpuDataManagerImplPrivate::UpdateRendererWebPrefs(
766 WebPreferences* prefs) const {
767 DCHECK(prefs);
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 {
821 if (gpu_blacklist_)
822 return gpu_blacklist_->version();
823 return "0";
826 std::string GpuDataManagerImplPrivate::GetDriverBugListVersion() const {
827 if (gpu_driver_bug_list_)
828 return gpu_driver_bug_list_->version();
829 return "0";
832 void GpuDataManagerImplPrivate::GetBlacklistReasons(
833 base::ListValue* reasons) const {
834 if (gpu_blacklist_)
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(
863 BrowserThread::UI,
864 FROM_HERE,
865 base::Bind(&GpuDataManagerImpl::ProcessCrashed,
866 base::Unretained(owner_),
867 exit_code));
868 return;
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();
880 return value;
883 void GpuDataManagerImplPrivate::HandleGpuSwitch() {
884 GpuDataManagerImpl::UnlockedSession session(owner_);
885 observer_list_->Notify(&GpuDataManagerObserver::OnGpuSwitching);
888 #if defined(OS_WIN)
889 bool GpuDataManagerImplPrivate::IsUsingAcceleratedSurface() const {
890 if (base::win::GetVersion() < base::win::VERSION_VISTA)
891 return false;
893 if (gpu_info_.amd_switchable)
894 return false;
895 if (use_swiftshader_)
896 return false;
897 CommandLine* command_line = CommandLine::ForCurrentProcess();
898 if (command_line->HasSwitch(switches::kDisableImageTransportSurface))
899 return false;
900 return !IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING);
902 #endif
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,
911 int render_view_id,
912 ThreeDAPIType requester) {
913 bool blocked = Are3DAPIsBlockedAtTime(url, base::Time::Now()) !=
914 GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
915 if (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));
925 return blocked;
928 void GpuDataManagerImplPrivate::DisableDomainBlockingFor3DAPIsForTesting() {
929 domain_blocking_enabled_ = false;
932 // static
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),
946 window_count_(0),
947 domain_blocking_enabled_(true),
948 owner_(owner),
949 display_count_(0),
950 gpu_process_accessible_(true) {
951 DCHECK(owner_);
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_);
971 #endif // OS_MACOSX
974 GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() {
975 #if defined(OS_MACOSX)
976 CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback, owner_);
977 #endif
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();
1062 break;
1063 case gpu::GPU_SWITCHING_OPTION_FORCE_INTEGRATED:
1064 ui::GpuSwitchingManager::GetInstance()->ForceUseOfIntegratedGpu();
1065 break;
1066 case gpu::GPU_SWITCHING_OPTION_AUTOMATIC:
1067 case gpu::GPU_SWITCHING_OPTION_UNKNOWN:
1068 break;
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();
1099 return url.host();
1102 void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIsAtTime(
1103 const GURL& url,
1104 GpuDataManagerImpl::DomainGuilt guilt,
1105 base::Time at_time) {
1106 if (!domain_blocking_enabled_)
1107 return;
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,
1134 BLOCK_STATUS_MAX);
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);
1156 continue;
1159 ++num_resets_within_timeframe;
1160 ++iter;
1163 if (num_resets_within_timeframe >= kNumResetsWithinDuration) {
1164 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1165 BLOCK_STATUS_ALL_DOMAINS_BLOCKED,
1166 BLOCK_STATUS_MAX);
1168 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED;
1172 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1173 BLOCK_STATUS_NOT_BLOCKED,
1174 BLOCK_STATUS_MAX);
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,
1185 int render_view_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