IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / browser / gpu / gpu_data_manager_impl_private.cc
blobc90c0d536a3c14b3ca63a9f6e377aa9a2f69c873
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/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>
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 kWin8,
67 kNumWinSubVersions
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)
82 sub_version = kWinXP;
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)
86 sub_version = kWin7;
87 else if (version_numbers[0] == 6 && version_numbers[1] == 2)
88 sub_version = kWin8;
91 int entry_index = static_cast<int>(sub_version) * kGpuFeatureNumStatus;
92 switch (status) {
93 case kGpuFeatureEnabled:
94 break;
95 case kGpuFeatureBlacklisted:
96 entry_index++;
97 break;
98 case kGpuFeatureDisabled:
99 entry_index += 2;
100 break;
102 return entry_index;
104 #endif // OS_WIN
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.
113 return;
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
122 // entries.
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;
139 disabled = true;
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)
164 #if defined(OS_WIN)
165 const std::string kGpuBlacklistFeatureHistogramNamesWin[] = {
166 "GPU.BlacklistFeatureTestResultsWindows.Accelerated2dCanvas",
167 "GPU.BlacklistFeatureTestResultsWindows.AcceleratedCompositing",
168 "GPU.BlacklistFeatureTestResultsWindows.Webgl",
169 "GPU.BlacklistFeatureTestResultsWindows.TextureSharing"
171 #endif
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);
187 #if defined(OS_WIN)
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));
194 #endif
197 UMA_HISTOGRAM_SPARSE_SLOWLY("GPU.GLResetNotificationStrategy",
198 gpu_info.gl_reset_notification_strategy);
201 // Combine the integers into a string, seperated by ','.
202 std::string IntSetToString(const std::set<int>& list) {
203 std::string rt;
204 for (std::set<int>::const_iterator it = list.begin();
205 it != list.end(); ++it) {
206 if (!rt.empty())
207 rt += ",";
208 rt += base::IntToString(*it);
210 return rt;
213 #if defined(OS_MACOSX)
214 void DisplayReconfigCallback(CGDirectDisplayID display,
215 CGDisplayChangeSummaryFlags flags,
216 void* gpu_data_manager) {
217 if (flags == kCGDisplayBeginConfigurationFlag)
218 return; // This call contains no information about the display change
220 GpuDataManagerImpl* manager =
221 reinterpret_cast<GpuDataManagerImpl*>(gpu_data_manager);
222 DCHECK(manager);
224 uint32_t displayCount;
225 CGGetActiveDisplayList(0, NULL, &displayCount);
227 bool fireGpuSwitch = flags & kCGDisplayAddFlag;
229 if (displayCount != manager->GetDisplayCount()) {
230 manager->SetDisplayCount(displayCount);
231 fireGpuSwitch = true;
234 if (fireGpuSwitch)
235 manager->HandleGpuSwitch();
237 #endif // OS_MACOSX
239 #if defined(OS_ANDROID)
240 void ApplyAndroidWorkarounds(const gpu::GPUInfo& gpu_info,
241 CommandLine* command_line) {
242 std::string vendor(StringToLowerASCII(gpu_info.gl_vendor));
243 std::string renderer(StringToLowerASCII(gpu_info.gl_renderer));
244 bool is_img =
245 gpu_info.gl_vendor.find("Imagination") != std::string::npos;
247 gfx::DeviceDisplayInfo info;
248 int default_tile_size = 256;
250 // TODO(epenner): Now that this is somewhat generic, maybe we can
251 // unify this for all platforms (http://crbug.com/159524)
253 bool real_size_supported = true;
254 int display_width = info.GetPhysicalDisplayWidth();
255 int display_height = info.GetPhysicalDisplayHeight();
256 if (display_width == 0 || display_height == 0) {
257 real_size_supported = false;
258 display_width = info.GetDisplayWidth();
259 display_height = info.GetDisplayHeight();
262 int portrait_width = std::min(display_width, display_height);
263 int landscape_width = std::max(display_width, display_height);
265 if (real_size_supported) {
266 // Maximum HD dimensions should be 768x1280
267 // Maximum FHD dimensions should be 1200x1920
268 if (portrait_width > 768 || landscape_width > 1280)
269 default_tile_size = 384;
270 if (portrait_width > 1200 || landscape_width > 1920)
271 default_tile_size = 512;
273 // Adjust for some resolutions that barely straddle an extra
274 // tile when in portrait mode. This helps worst case scroll/raster
275 // by not needing a full extra tile for each row.
276 if (default_tile_size == 256 && portrait_width == 768)
277 default_tile_size += 32;
278 if (default_tile_size == 384 && portrait_width == 1200)
279 default_tile_size += 32;
280 } else {
281 // We don't know the exact resolution due to screen controls etc.
282 // So this just estimates the values above using tile counts.
283 int numTiles = (display_width * display_height) / (256 * 256);
284 if (numTiles > 16)
285 default_tile_size = 384;
286 if (numTiles >= 40)
287 default_tile_size = 512;
290 // IMG: Fast async texture uploads only work with non-power-of-two,
291 // but still multiple-of-eight sizes.
292 // http://crbug.com/168099
293 if (is_img)
294 default_tile_size -= 8;
296 // Set the command line if it isn't already set and we changed
297 // the default tile size.
298 if (default_tile_size != 256 &&
299 !command_line->HasSwitch(switches::kDefaultTileWidth) &&
300 !command_line->HasSwitch(switches::kDefaultTileHeight)) {
301 std::stringstream size;
302 size << default_tile_size;
303 command_line->AppendSwitchASCII(
304 switches::kDefaultTileWidth, size.str());
305 command_line->AppendSwitchASCII(
306 switches::kDefaultTileHeight, size.str());
309 #endif // OS_ANDROID
311 // Overwrite force gpu workaround if a commandline switch exists.
312 void AdjustGpuSwitchingOption(std::set<int>* workarounds) {
313 DCHECK(workarounds);
314 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
315 std::string option = command_line.GetSwitchValueASCII(
316 switches::kGpuSwitching);
317 if (option == switches::kGpuSwitchingOptionNameForceDiscrete) {
318 workarounds->erase(gpu::FORCE_INTEGRATED_GPU);
319 workarounds->insert(gpu::FORCE_DISCRETE_GPU);
320 } else if (option == switches::kGpuSwitchingOptionNameForceIntegrated) {
321 workarounds->erase(gpu::FORCE_DISCRETE_GPU);
322 workarounds->insert(gpu::FORCE_INTEGRATED_GPU);
326 // Block all domains' use of 3D APIs for this many milliseconds if
327 // approaching a threshold where system stability might be compromised.
328 const int64 kBlockAllDomainsMs = 10000;
329 const int kNumResetsWithinDuration = 1;
331 // Enums for UMA histograms.
332 enum BlockStatusHistogram {
333 BLOCK_STATUS_NOT_BLOCKED,
334 BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED,
335 BLOCK_STATUS_ALL_DOMAINS_BLOCKED,
336 BLOCK_STATUS_MAX
339 } // namespace anonymous
341 void GpuDataManagerImplPrivate::InitializeForTesting(
342 const std::string& gpu_blacklist_json,
343 const gpu::GPUInfo& gpu_info) {
344 // This function is for testing only, so disable histograms.
345 update_histograms_ = false;
347 // Prevent all further initialization.
348 finalized_ = true;
350 InitializeImpl(gpu_blacklist_json, std::string(), gpu_info);
353 bool GpuDataManagerImplPrivate::IsFeatureBlacklisted(int feature) const {
354 if (CommandLine::ForCurrentProcess()->HasSwitch("chrome-frame") &&
355 feature == gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING)
356 return false;
357 #if defined(OS_CHROMEOS)
358 if (feature == gpu::GPU_FEATURE_TYPE_PANEL_FITTING &&
359 CommandLine::ForCurrentProcess()->HasSwitch(
360 switches::kDisablePanelFitting)) {
361 return true;
363 #endif // OS_CHROMEOS
364 if (use_swiftshader_) {
365 // Skia's software rendering is probably more efficient than going through
366 // software emulation of the GPU, so use that.
367 if (feature == gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)
368 return true;
369 return false;
372 return (blacklisted_features_.count(feature) == 1);
375 bool GpuDataManagerImplPrivate::IsDriverBugWorkaroundActive(int feature) const {
376 return (gpu_driver_bugs_.count(feature) == 1);
379 size_t GpuDataManagerImplPrivate::GetBlacklistedFeatureCount() const {
380 if (use_swiftshader_)
381 return 1;
382 return blacklisted_features_.size();
385 void GpuDataManagerImplPrivate::SetDisplayCount(unsigned int display_count) {
386 display_count_ = display_count;
389 unsigned int GpuDataManagerImplPrivate::GetDisplayCount() const {
390 return display_count_;
393 gpu::GPUInfo GpuDataManagerImplPrivate::GetGPUInfo() const {
394 return gpu_info_;
397 void GpuDataManagerImplPrivate::GetGpuProcessHandles(
398 const GpuDataManager::GetGpuProcessHandlesCallback& callback) const {
399 GpuProcessHost::GetProcessHandles(callback);
402 bool GpuDataManagerImplPrivate::GpuAccessAllowed(
403 std::string* reason) const {
404 if (use_swiftshader_)
405 return true;
407 if (!gpu_process_accessible_) {
408 if (reason) {
409 *reason = "GPU process launch failed.";
411 return false;
414 if (card_blacklisted_) {
415 if (reason) {
416 *reason = "GPU access is disabled ";
417 CommandLine* command_line = CommandLine::ForCurrentProcess();
418 if (command_line->HasSwitch(switches::kDisableGpu))
419 *reason += "through commandline switch --disable-gpu.";
420 else
421 *reason += "in chrome://settings.";
423 return false;
426 // We only need to block GPU process if more features are disallowed other
427 // than those in the preliminary gpu feature flags because the latter work
428 // through renderer commandline switches.
429 std::set<int> features = preliminary_blacklisted_features_;
430 gpu::MergeFeatureSets(&features, blacklisted_features_);
431 if (features.size() > preliminary_blacklisted_features_.size()) {
432 if (reason) {
433 *reason = "Features are disabled upon full but not preliminary GPU info.";
435 return false;
438 if (blacklisted_features_.size() == gpu::NUMBER_OF_GPU_FEATURE_TYPES) {
439 // On Linux, we use cached GL strings to make blacklist decsions at browser
440 // startup time. We need to launch the GPU process to validate these
441 // strings even if all features are blacklisted. If all GPU features are
442 // disabled, the GPU process will only initialize GL bindings, create a GL
443 // context, and collect full GPU info.
444 #if !defined(OS_LINUX)
445 if (reason) {
446 *reason = "All GPU features are blacklisted.";
448 return false;
449 #endif
452 return true;
455 void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
456 if (complete_gpu_info_already_requested_ || gpu_info_.finalized)
457 return;
458 complete_gpu_info_already_requested_ = true;
460 GpuProcessHost::SendOnIO(
461 #if defined(OS_WIN)
462 GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED,
463 #else
464 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
465 #endif
466 CAUSE_FOR_GPU_LAUNCH_GPUDATAMANAGER_REQUESTCOMPLETEGPUINFOIFNEEDED,
467 new GpuMsg_CollectGraphicsInfo());
470 bool GpuDataManagerImplPrivate::IsCompleteGpuInfoAvailable() const {
471 return gpu_info_.finalized;
474 void GpuDataManagerImplPrivate::RequestVideoMemoryUsageStatsUpdate() const {
475 GpuProcessHost::SendOnIO(
476 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
477 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
478 new GpuMsg_GetVideoMemoryUsageStats());
481 bool GpuDataManagerImplPrivate::ShouldUseSwiftShader() const {
482 return use_swiftshader_;
485 void GpuDataManagerImplPrivate::RegisterSwiftShaderPath(
486 const base::FilePath& path) {
487 swiftshader_path_ = path;
488 EnableSwiftShaderIfNecessary();
491 void GpuDataManagerImplPrivate::AddObserver(GpuDataManagerObserver* observer) {
492 GpuDataManagerImpl::UnlockedSession session(owner_);
493 observer_list_->AddObserver(observer);
496 void GpuDataManagerImplPrivate::RemoveObserver(
497 GpuDataManagerObserver* observer) {
498 GpuDataManagerImpl::UnlockedSession session(owner_);
499 observer_list_->RemoveObserver(observer);
502 void GpuDataManagerImplPrivate::UnblockDomainFrom3DAPIs(const GURL& url) {
503 // This method must do two things:
505 // 1. If the specific domain is blocked, then unblock it.
507 // 2. Reset our notion of how many GPU resets have occurred recently.
508 // This is necessary even if the specific domain was blocked.
509 // Otherwise, if we call Are3DAPIsBlocked with the same domain right
510 // after unblocking it, it will probably still be blocked because of
511 // the recent GPU reset caused by that domain.
513 // These policies could be refined, but at a certain point the behavior
514 // will become difficult to explain.
515 std::string domain = GetDomainFromURL(url);
517 blocked_domains_.erase(domain);
518 timestamps_of_gpu_resets_.clear();
521 void GpuDataManagerImplPrivate::DisableGpuWatchdog() {
522 GpuProcessHost::SendOnIO(
523 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
524 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
525 new GpuMsg_DisableWatchdog);
528 void GpuDataManagerImplPrivate::SetGLStrings(const std::string& gl_vendor,
529 const std::string& gl_renderer,
530 const std::string& gl_version) {
531 if (gl_vendor.empty() && gl_renderer.empty() && gl_version.empty())
532 return;
534 // If GPUInfo already got GL strings, do nothing. This is for the rare
535 // situation where GPU process collected GL strings before this call.
536 if (!gpu_info_.gl_vendor.empty() ||
537 !gpu_info_.gl_renderer.empty() ||
538 !gpu_info_.gl_version_string.empty())
539 return;
541 gpu::GPUInfo gpu_info = gpu_info_;
543 gpu_info.gl_vendor = gl_vendor;
544 gpu_info.gl_renderer = gl_renderer;
545 gpu_info.gl_version_string = gl_version;
547 gpu::CollectDriverInfoGL(&gpu_info);
549 UpdateGpuInfo(gpu_info);
550 UpdateGpuSwitchingManager(gpu_info);
551 UpdatePreliminaryBlacklistedFeatures();
554 void GpuDataManagerImplPrivate::GetGLStrings(std::string* gl_vendor,
555 std::string* gl_renderer,
556 std::string* gl_version) {
557 DCHECK(gl_vendor && gl_renderer && gl_version);
559 *gl_vendor = gpu_info_.gl_vendor;
560 *gl_renderer = gpu_info_.gl_renderer;
561 *gl_version = gpu_info_.gl_version_string;
564 void GpuDataManagerImplPrivate::Initialize() {
565 TRACE_EVENT0("startup", "GpuDataManagerImpl::Initialize");
566 if (finalized_) {
567 DVLOG(0) << "GpuDataManagerImpl marked as finalized; skipping Initialize";
568 return;
571 const CommandLine* command_line = CommandLine::ForCurrentProcess();
572 if (command_line->HasSwitch(switches::kSkipGpuDataLoading))
573 return;
575 gpu::GPUInfo gpu_info;
576 if (command_line->GetSwitchValueASCII(
577 switches::kUseGL) == gfx::kGLImplementationOSMesaName) {
578 // If using the OSMesa GL implementation, use fake vendor and device ids to
579 // make sure it never gets blacklisted. This is better than simply
580 // cancelling GPUInfo gathering as it allows us to proceed with loading the
581 // blacklist below which may have non-device specific entries we want to
582 // apply anyways (e.g., OS version blacklisting).
583 gpu_info.gpu.vendor_id = 0xffff;
584 gpu_info.gpu.device_id = 0xffff;
586 // Also declare the driver_vendor to be osmesa to be able to specify
587 // exceptions based on driver_vendor==osmesa for some blacklist rules.
588 gpu_info.driver_vendor = gfx::kGLImplementationOSMesaName;
589 } else {
590 TRACE_EVENT0("startup",
591 "GpuDataManagerImpl::Initialize:CollectBasicGraphicsInfo");
592 gpu::CollectBasicGraphicsInfo(&gpu_info);
594 #if defined(ARCH_CPU_X86_FAMILY)
595 if (!gpu_info.gpu.vendor_id || !gpu_info.gpu.device_id)
596 gpu_info.finalized = true;
597 #endif
599 std::string gpu_blacklist_string;
600 std::string gpu_driver_bug_list_string;
601 if (!command_line->HasSwitch(switches::kIgnoreGpuBlacklist) &&
602 !command_line->HasSwitch(switches::kUseGpuInTests)) {
603 gpu_blacklist_string = gpu::kSoftwareRenderingListJson;
605 if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
606 gpu_driver_bug_list_string = gpu::kGpuDriverBugListJson;
608 InitializeImpl(gpu_blacklist_string,
609 gpu_driver_bug_list_string,
610 gpu_info);
613 void GpuDataManagerImplPrivate::UpdateGpuInfo(const gpu::GPUInfo& gpu_info) {
614 // No further update of gpu_info if falling back to SwiftShader.
615 if (use_swiftshader_)
616 return;
618 gpu::MergeGPUInfo(&gpu_info_, gpu_info);
619 complete_gpu_info_already_requested_ =
620 complete_gpu_info_already_requested_ || gpu_info_.finalized;
622 GetContentClient()->SetGpuInfo(gpu_info_);
624 if (gpu_blacklist_) {
625 std::set<int> features = gpu_blacklist_->MakeDecision(
626 gpu::GpuControlList::kOsAny, std::string(), gpu_info_);
627 if (update_histograms_)
628 UpdateStats(gpu_info_, gpu_blacklist_.get(), features);
630 UpdateBlacklistedFeatures(features);
632 if (gpu_driver_bug_list_) {
633 gpu_driver_bugs_ = gpu_driver_bug_list_->MakeDecision(
634 gpu::GpuControlList::kOsAny, std::string(), gpu_info_);
636 AdjustGpuSwitchingOption(&gpu_driver_bugs_);
638 // We have to update GpuFeatureType before notify all the observers.
639 NotifyGpuInfoUpdate();
642 void GpuDataManagerImplPrivate::UpdateVideoMemoryUsageStats(
643 const GPUVideoMemoryUsageStats& video_memory_usage_stats) {
644 GpuDataManagerImpl::UnlockedSession session(owner_);
645 observer_list_->Notify(&GpuDataManagerObserver::OnVideoMemoryUsageStatsUpdate,
646 video_memory_usage_stats);
649 void GpuDataManagerImplPrivate::AppendRendererCommandLine(
650 CommandLine* command_line) const {
651 DCHECK(command_line);
653 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) &&
654 !command_line->HasSwitch(switches::kDisableAcceleratedCompositing))
655 command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
656 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) &&
657 !command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode))
658 command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
659 #if defined(ENABLE_WEBRTC)
660 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE) &&
661 !command_line->HasSwitch(switches::kDisableWebRtcHWEncoding))
662 command_line->AppendSwitch(switches::kDisableWebRtcHWEncoding);
663 #endif
665 if (use_software_compositor_ &&
666 !command_line->HasSwitch(switches::kEnableSoftwareCompositing))
667 command_line->AppendSwitch(switches::kEnableSoftwareCompositing);
669 #if defined(USE_AURA)
670 if (!CanUseGpuBrowserCompositor())
671 command_line->AppendSwitch(switches::kDisableGpuCompositing);
672 #endif
675 void GpuDataManagerImplPrivate::AppendGpuCommandLine(
676 CommandLine* command_line) const {
677 DCHECK(command_line);
679 std::string use_gl =
680 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL);
681 base::FilePath swiftshader_path =
682 CommandLine::ForCurrentProcess()->GetSwitchValuePath(
683 switches::kSwiftShaderPath);
684 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_MULTISAMPLING) &&
685 !command_line->HasSwitch(switches::kDisableGLMultisampling)) {
686 command_line->AppendSwitch(switches::kDisableGLMultisampling);
688 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING)) {
689 command_line->AppendSwitch(switches::kDisableImageTransportSurface);
691 if (gpu_driver_bugs_.find(gpu::DISABLE_D3D11) != gpu_driver_bugs_.end())
692 command_line->AppendSwitch(switches::kDisableD3D11);
693 if (use_swiftshader_) {
694 command_line->AppendSwitchASCII(switches::kUseGL, "swiftshader");
695 if (swiftshader_path.empty())
696 swiftshader_path = swiftshader_path_;
697 } else if ((IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL) ||
698 IsFeatureBlacklisted(
699 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) ||
700 IsFeatureBlacklisted(
701 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)) &&
702 (use_gl == "any")) {
703 command_line->AppendSwitchASCII(
704 switches::kUseGL, gfx::kGLImplementationOSMesaName);
705 } else if (!use_gl.empty()) {
706 command_line->AppendSwitchASCII(switches::kUseGL, use_gl);
708 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus())
709 command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "true");
710 else
711 command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "false");
713 if (!swiftshader_path.empty()) {
714 command_line->AppendSwitchPath(switches::kSwiftShaderPath,
715 swiftshader_path);
718 if (!gpu_driver_bugs_.empty()) {
719 command_line->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds,
720 IntSetToString(gpu_driver_bugs_));
723 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) &&
724 !command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) {
725 command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
727 #if defined(ENABLE_WEBRTC)
728 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE) &&
729 !command_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) {
730 command_line->AppendSwitch(switches::kDisableWebRtcHWEncoding);
732 #endif
734 // Pass GPU and driver information to GPU process. We try to avoid full GPU
735 // info collection at GPU process startup, but we need gpu vendor_id,
736 // device_id, driver_vendor, driver_version for deciding whether we need to
737 // collect full info (on Linux) and for crash reporting purpose.
738 command_line->AppendSwitchASCII(switches::kGpuVendorID,
739 base::StringPrintf("0x%04x", gpu_info_.gpu.vendor_id));
740 command_line->AppendSwitchASCII(switches::kGpuDeviceID,
741 base::StringPrintf("0x%04x", gpu_info_.gpu.device_id));
742 command_line->AppendSwitchASCII(switches::kGpuDriverVendor,
743 gpu_info_.driver_vendor);
744 command_line->AppendSwitchASCII(switches::kGpuDriverVersion,
745 gpu_info_.driver_version);
748 void GpuDataManagerImplPrivate::AppendPluginCommandLine(
749 CommandLine* command_line) const {
750 DCHECK(command_line);
752 #if defined(OS_MACOSX)
753 // TODO(jbauman): Add proper blacklist support for core animation plugins so
754 // special-casing this video card won't be necessary. See
755 // http://crbug.com/134015
756 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) ||
757 CommandLine::ForCurrentProcess()->HasSwitch(
758 switches::kDisableAcceleratedCompositing)) {
759 if (!command_line->HasSwitch(
760 switches::kDisableCoreAnimationPlugins))
761 command_line->AppendSwitch(
762 switches::kDisableCoreAnimationPlugins);
764 #endif
767 void GpuDataManagerImplPrivate::UpdateRendererWebPrefs(
768 WebPreferences* prefs) const {
769 DCHECK(prefs);
771 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING))
772 prefs->accelerated_compositing_enabled = false;
773 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL)) {
774 prefs->experimental_webgl_enabled = false;
775 prefs->pepper_3d_enabled = false;
777 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH3D))
778 prefs->flash_3d_enabled = false;
779 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D)) {
780 prefs->flash_stage3d_enabled = false;
781 prefs->flash_stage3d_baseline_enabled = false;
783 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE))
784 prefs->flash_stage3d_baseline_enabled = false;
785 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS))
786 prefs->accelerated_2d_canvas_enabled = false;
787 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_MULTISAMPLING) ||
788 (IsDriverBugWorkaroundActive(gpu::DISABLE_MULTIMONITOR_MULTISAMPLING) &&
789 display_count_ > 1))
790 prefs->gl_multisampling_enabled = false;
791 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_3D_CSS)) {
792 prefs->accelerated_compositing_for_3d_transforms_enabled = false;
793 prefs->accelerated_compositing_for_animation_enabled = false;
795 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO))
796 prefs->accelerated_compositing_for_video_enabled = false;
798 // Accelerated video and animation are slower than regular when using
799 // SwiftShader. 3D CSS or Pepper 3D may also be too slow to be worthwhile.
800 if (ShouldUseSwiftShader()) {
801 prefs->accelerated_compositing_for_video_enabled = false;
802 prefs->accelerated_compositing_for_animation_enabled = false;
803 prefs->accelerated_compositing_for_3d_transforms_enabled = false;
804 prefs->accelerated_compositing_for_plugins_enabled = false;
805 prefs->pepper_3d_enabled = false;
808 if (use_software_compositor_) {
809 prefs->force_compositing_mode = true;
810 prefs->accelerated_compositing_enabled = true;
811 prefs->accelerated_compositing_for_3d_transforms_enabled = true;
812 prefs->accelerated_compositing_for_plugins_enabled = true;
813 prefs->accelerated_compositing_for_video_enabled = true;
816 #if defined(USE_AURA)
817 if (!CanUseGpuBrowserCompositor()) {
818 prefs->accelerated_2d_canvas_enabled = false;
819 prefs->pepper_3d_enabled = false;
821 #endif
824 void GpuDataManagerImplPrivate::DisableHardwareAcceleration() {
825 card_blacklisted_ = true;
827 for (int i = 0; i < gpu::NUMBER_OF_GPU_FEATURE_TYPES; ++i)
828 blacklisted_features_.insert(i);
830 EnableSwiftShaderIfNecessary();
831 NotifyGpuInfoUpdate();
834 std::string GpuDataManagerImplPrivate::GetBlacklistVersion() const {
835 if (gpu_blacklist_)
836 return gpu_blacklist_->version();
837 return "0";
840 std::string GpuDataManagerImplPrivate::GetDriverBugListVersion() const {
841 if (gpu_driver_bug_list_)
842 return gpu_driver_bug_list_->version();
843 return "0";
846 void GpuDataManagerImplPrivate::GetBlacklistReasons(
847 base::ListValue* reasons) const {
848 if (gpu_blacklist_)
849 gpu_blacklist_->GetReasons(reasons);
852 void GpuDataManagerImplPrivate::GetDriverBugWorkarounds(
853 base::ListValue* workarounds) const {
854 for (std::set<int>::const_iterator it = gpu_driver_bugs_.begin();
855 it != gpu_driver_bugs_.end(); ++it) {
856 workarounds->AppendString(
857 gpu::GpuDriverBugWorkaroundTypeToString(
858 static_cast<gpu::GpuDriverBugWorkaroundType>(*it)));
862 void GpuDataManagerImplPrivate::AddLogMessage(
863 int level, const std::string& header, const std::string& message) {
864 log_messages_.push_back(LogMessage(level, header, message));
867 void GpuDataManagerImplPrivate::ProcessCrashed(
868 base::TerminationStatus exit_code) {
869 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
870 // Unretained is ok, because it's posted to UI thread, the thread
871 // where the singleton GpuDataManagerImpl lives until the end.
872 BrowserThread::PostTask(
873 BrowserThread::UI,
874 FROM_HERE,
875 base::Bind(&GpuDataManagerImpl::ProcessCrashed,
876 base::Unretained(owner_),
877 exit_code));
878 return;
881 GpuDataManagerImpl::UnlockedSession session(owner_);
882 observer_list_->Notify(
883 &GpuDataManagerObserver::OnGpuProcessCrashed, exit_code);
887 base::ListValue* GpuDataManagerImplPrivate::GetLogMessages() const {
888 base::ListValue* value = new base::ListValue;
889 for (size_t ii = 0; ii < log_messages_.size(); ++ii) {
890 base::DictionaryValue* dict = new base::DictionaryValue();
891 dict->SetInteger("level", log_messages_[ii].level);
892 dict->SetString("header", log_messages_[ii].header);
893 dict->SetString("message", log_messages_[ii].message);
894 value->Append(dict);
896 return value;
899 void GpuDataManagerImplPrivate::HandleGpuSwitch() {
900 GpuDataManagerImpl::UnlockedSession session(owner_);
901 observer_list_->Notify(&GpuDataManagerObserver::OnGpuSwitching);
904 #if defined(OS_WIN)
905 bool GpuDataManagerImplPrivate::IsUsingAcceleratedSurface() const {
906 if (base::win::GetVersion() < base::win::VERSION_VISTA)
907 return false;
909 if (use_swiftshader_)
910 return false;
911 CommandLine* command_line = CommandLine::ForCurrentProcess();
912 if (command_line->HasSwitch(switches::kDisableImageTransportSurface))
913 return false;
914 return !IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING);
916 #endif
918 bool GpuDataManagerImplPrivate::CanUseGpuBrowserCompositor() const {
919 return !ShouldUseSwiftShader() &&
920 !IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) &&
921 !IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE);
924 void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIs(
925 const GURL& url, GpuDataManagerImpl::DomainGuilt guilt) {
926 BlockDomainFrom3DAPIsAtTime(url, guilt, base::Time::Now());
929 bool GpuDataManagerImplPrivate::Are3DAPIsBlocked(const GURL& url,
930 int render_process_id,
931 int render_view_id,
932 ThreeDAPIType requester) {
933 bool blocked = Are3DAPIsBlockedAtTime(url, base::Time::Now()) !=
934 GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
935 if (blocked) {
936 // Unretained is ok, because it's posted to UI thread, the thread
937 // where the singleton GpuDataManagerImpl lives until the end.
938 BrowserThread::PostTask(
939 BrowserThread::UI, FROM_HERE,
940 base::Bind(&GpuDataManagerImpl::Notify3DAPIBlocked,
941 base::Unretained(owner_), url, render_process_id,
942 render_view_id, requester));
945 return blocked;
948 void GpuDataManagerImplPrivate::DisableDomainBlockingFor3DAPIsForTesting() {
949 domain_blocking_enabled_ = false;
952 // static
953 GpuDataManagerImplPrivate* GpuDataManagerImplPrivate::Create(
954 GpuDataManagerImpl* owner) {
955 return new GpuDataManagerImplPrivate(owner);
958 GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(
959 GpuDataManagerImpl* owner)
960 : complete_gpu_info_already_requested_(false),
961 observer_list_(new GpuDataManagerObserverList),
962 use_swiftshader_(false),
963 card_blacklisted_(false),
964 update_histograms_(true),
965 window_count_(0),
966 domain_blocking_enabled_(true),
967 owner_(owner),
968 display_count_(0),
969 gpu_process_accessible_(true),
970 use_software_compositor_(false),
971 finalized_(false) {
972 DCHECK(owner_);
973 CommandLine* command_line = CommandLine::ForCurrentProcess();
974 if (command_line->HasSwitch(switches::kDisableAcceleratedCompositing)) {
975 command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas);
976 command_line->AppendSwitch(switches::kDisableAcceleratedLayers);
978 if (command_line->HasSwitch(switches::kDisableGpu))
979 DisableHardwareAcceleration();
980 if (command_line->HasSwitch(switches::kEnableSoftwareCompositing))
981 use_software_compositor_ = true;
982 // TODO(jbauman): enable for Chrome OS
983 #if (defined(USE_AURA) && !defined(OS_CHROMEOS)) || defined(OS_MACOSX)
984 use_software_compositor_ = true;
985 #endif
987 #if defined(OS_MACOSX)
988 CGGetActiveDisplayList (0, NULL, &display_count_);
989 CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback, owner_);
990 #endif // OS_MACOSX
992 // For testing only.
993 if (command_line->HasSwitch(switches::kDisableDomainBlockingFor3DAPIs)) {
994 domain_blocking_enabled_ = false;
998 GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() {
999 #if defined(OS_MACOSX)
1000 CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback, owner_);
1001 #endif
1004 void GpuDataManagerImplPrivate::InitializeImpl(
1005 const std::string& gpu_blacklist_json,
1006 const std::string& gpu_driver_bug_list_json,
1007 const gpu::GPUInfo& gpu_info) {
1008 const bool log_gpu_control_list_decisions =
1009 CommandLine::ForCurrentProcess()->HasSwitch(
1010 switches::kLogGpuControlListDecisions);
1012 if (!gpu_blacklist_json.empty()) {
1013 gpu_blacklist_.reset(gpu::GpuBlacklist::Create());
1014 if (log_gpu_control_list_decisions)
1015 gpu_blacklist_->enable_control_list_logging("gpu_blacklist");
1016 bool success = gpu_blacklist_->LoadList(
1017 gpu_blacklist_json, gpu::GpuControlList::kCurrentOsOnly);
1018 DCHECK(success);
1020 if (!gpu_driver_bug_list_json.empty()) {
1021 gpu_driver_bug_list_.reset(gpu::GpuDriverBugList::Create());
1022 if (log_gpu_control_list_decisions)
1023 gpu_driver_bug_list_->enable_control_list_logging("gpu_driver_bug_list");
1024 bool success = gpu_driver_bug_list_->LoadList(
1025 gpu_driver_bug_list_json, gpu::GpuControlList::kCurrentOsOnly);
1026 DCHECK(success);
1029 gpu_info_ = gpu_info;
1030 UpdateGpuInfo(gpu_info);
1031 UpdateGpuSwitchingManager(gpu_info);
1032 UpdatePreliminaryBlacklistedFeatures();
1034 #if defined(OS_ANDROID)
1035 ApplyAndroidWorkarounds(gpu_info, CommandLine::ForCurrentProcess());
1036 #endif // OS_ANDROID
1039 void GpuDataManagerImplPrivate::UpdateBlacklistedFeatures(
1040 const std::set<int>& features) {
1041 CommandLine* command_line = CommandLine::ForCurrentProcess();
1042 blacklisted_features_ = features;
1044 // Force disable using the GPU for these features, even if they would
1045 // otherwise be allowed.
1046 if (card_blacklisted_ ||
1047 command_line->HasSwitch(switches::kBlacklistAcceleratedCompositing)) {
1048 blacklisted_features_.insert(
1049 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING);
1051 if (card_blacklisted_ ||
1052 command_line->HasSwitch(switches::kBlacklistWebGL)) {
1053 blacklisted_features_.insert(gpu::GPU_FEATURE_TYPE_WEBGL);
1056 EnableSwiftShaderIfNecessary();
1059 void GpuDataManagerImplPrivate::UpdatePreliminaryBlacklistedFeatures() {
1060 preliminary_blacklisted_features_ = blacklisted_features_;
1063 void GpuDataManagerImplPrivate::UpdateGpuSwitchingManager(
1064 const gpu::GPUInfo& gpu_info) {
1065 ui::GpuSwitchingManager::GetInstance()->SetGpuCount(
1066 gpu_info.secondary_gpus.size() + 1);
1068 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) {
1069 if (gpu_driver_bugs_.count(gpu::FORCE_DISCRETE_GPU) == 1)
1070 ui::GpuSwitchingManager::GetInstance()->ForceUseOfDiscreteGpu();
1071 else if (gpu_driver_bugs_.count(gpu::FORCE_INTEGRATED_GPU) == 1)
1072 ui::GpuSwitchingManager::GetInstance()->ForceUseOfIntegratedGpu();
1076 void GpuDataManagerImplPrivate::NotifyGpuInfoUpdate() {
1077 observer_list_->Notify(&GpuDataManagerObserver::OnGpuInfoUpdate);
1080 void GpuDataManagerImplPrivate::EnableSwiftShaderIfNecessary() {
1081 if (!GpuAccessAllowed(NULL) ||
1082 blacklisted_features_.count(gpu::GPU_FEATURE_TYPE_WEBGL)) {
1083 if (!swiftshader_path_.empty() &&
1084 !CommandLine::ForCurrentProcess()->HasSwitch(
1085 switches::kDisableSoftwareRasterizer))
1086 use_swiftshader_ = true;
1090 std::string GpuDataManagerImplPrivate::GetDomainFromURL(
1091 const GURL& url) const {
1092 // For the moment, we just use the host, or its IP address, as the
1093 // entry in the set, rather than trying to figure out the top-level
1094 // domain. This does mean that a.foo.com and b.foo.com will be
1095 // treated independently in the blocking of a given domain, but it
1096 // would require a third-party library to reliably figure out the
1097 // top-level domain from a URL.
1098 if (!url.has_host()) {
1099 return std::string();
1102 return url.host();
1105 void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIsAtTime(
1106 const GURL& url,
1107 GpuDataManagerImpl::DomainGuilt guilt,
1108 base::Time at_time) {
1109 if (!domain_blocking_enabled_)
1110 return;
1112 std::string domain = GetDomainFromURL(url);
1114 DomainBlockEntry& entry = blocked_domains_[domain];
1115 entry.last_guilt = guilt;
1116 timestamps_of_gpu_resets_.push_back(at_time);
1119 GpuDataManagerImpl::DomainBlockStatus
1120 GpuDataManagerImplPrivate::Are3DAPIsBlockedAtTime(
1121 const GURL& url, base::Time at_time) const {
1122 if (!domain_blocking_enabled_)
1123 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
1125 // Note: adjusting the policies in this code will almost certainly
1126 // require adjusting the associated unit tests.
1127 std::string domain = GetDomainFromURL(url);
1129 DomainBlockMap::const_iterator iter = blocked_domains_.find(domain);
1130 if (iter != blocked_domains_.end()) {
1131 // Err on the side of caution, and assume that if a particular
1132 // domain shows up in the block map, it's there for a good
1133 // reason and don't let its presence there automatically expire.
1135 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1136 BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED,
1137 BLOCK_STATUS_MAX);
1139 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED;
1142 // Look at the timestamps of the recent GPU resets to see if there are
1143 // enough within the threshold which would cause us to blacklist all
1144 // domains. This doesn't need to be overly precise -- if time goes
1145 // backward due to a system clock adjustment, that's fine.
1147 // TODO(kbr): make this pay attention to the TDR thresholds in the
1148 // Windows registry, but make sure it continues to be testable.
1150 std::list<base::Time>::iterator iter = timestamps_of_gpu_resets_.begin();
1151 int num_resets_within_timeframe = 0;
1152 while (iter != timestamps_of_gpu_resets_.end()) {
1153 base::Time time = *iter;
1154 base::TimeDelta delta_t = at_time - time;
1156 // If this entry has "expired", just remove it.
1157 if (delta_t.InMilliseconds() > kBlockAllDomainsMs) {
1158 iter = timestamps_of_gpu_resets_.erase(iter);
1159 continue;
1162 ++num_resets_within_timeframe;
1163 ++iter;
1166 if (num_resets_within_timeframe >= kNumResetsWithinDuration) {
1167 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1168 BLOCK_STATUS_ALL_DOMAINS_BLOCKED,
1169 BLOCK_STATUS_MAX);
1171 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED;
1175 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1176 BLOCK_STATUS_NOT_BLOCKED,
1177 BLOCK_STATUS_MAX);
1179 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
1182 int64 GpuDataManagerImplPrivate::GetBlockAllDomainsDurationInMs() const {
1183 return kBlockAllDomainsMs;
1186 void GpuDataManagerImplPrivate::Notify3DAPIBlocked(const GURL& url,
1187 int render_process_id,
1188 int render_view_id,
1189 ThreeDAPIType requester) {
1190 GpuDataManagerImpl::UnlockedSession session(owner_);
1191 observer_list_->Notify(&GpuDataManagerObserver::DidBlock3DAPIs,
1192 url, render_process_id, render_view_id, requester);
1195 void GpuDataManagerImplPrivate::OnGpuProcessInitFailure() {
1196 gpu_process_accessible_ = false;
1197 gpu_info_.finalized = true;
1198 complete_gpu_info_already_requested_ = true;
1199 // Some observers might be waiting.
1200 NotifyGpuInfoUpdate();
1203 } // namespace content