Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / gpu / gpu_data_manager_impl_private.cc
blobec1776cd4b31b9b23bab96e8e19a17ef3d304154
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/metrics/field_trial.h"
11 #include "base/metrics/histogram.h"
12 #include "base/metrics/sparse_histogram.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/sys_info.h"
16 #include "base/trace_event/trace_event.h"
17 #include "base/version.h"
18 #include "cc/base/switches.h"
19 #include "content/browser/gpu/gpu_process_host.h"
20 #include "content/common/gpu/gpu_messages.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/gpu_data_manager_observer.h"
23 #include "content/public/common/content_client.h"
24 #include "content/public/common/content_constants.h"
25 #include "content/public/common/content_switches.h"
26 #include "content/public/common/web_preferences.h"
27 #include "gpu/command_buffer/service/gpu_switches.h"
28 #include "gpu/config/gpu_control_list_jsons.h"
29 #include "gpu/config/gpu_driver_bug_workaround_type.h"
30 #include "gpu/config/gpu_feature_type.h"
31 #include "gpu/config/gpu_info_collector.h"
32 #include "gpu/config/gpu_switches.h"
33 #include "gpu/config/gpu_util.h"
34 #include "ui/base/ui_base_switches.h"
35 #include "ui/gl/gl_implementation.h"
36 #include "ui/gl/gl_switches.h"
37 #include "ui/gl/gpu_switching_manager.h"
39 #if defined(OS_MACOSX)
40 #include <ApplicationServices/ApplicationServices.h>
41 #endif // OS_MACOSX
42 #if defined(OS_WIN)
43 #include "base/win/windows_version.h"
44 #endif // OS_WIN
45 #if defined(OS_ANDROID)
46 #include "ui/gfx/android/device_display_info.h"
47 #endif // OS_ANDROID
49 namespace content {
51 namespace {
53 enum GpuFeatureStatus {
54 kGpuFeatureEnabled = 0,
55 kGpuFeatureBlacklisted = 1,
56 kGpuFeatureDisabled = 2, // disabled by user but not blacklisted
57 kGpuFeatureNumStatus
60 #if defined(OS_WIN)
62 enum WinSubVersion {
63 kWinOthers = 0,
64 kWinXP,
65 kWinVista,
66 kWin7,
67 kWin8,
68 kNumWinSubVersions
71 int GetGpuBlacklistHistogramValueWin(GpuFeatureStatus status) {
72 static WinSubVersion sub_version = kNumWinSubVersions;
73 if (sub_version == kNumWinSubVersions) {
74 sub_version = kWinOthers;
75 std::string version_str = base::SysInfo::OperatingSystemVersion();
76 size_t pos = version_str.find_first_not_of("0123456789.");
77 if (pos != std::string::npos)
78 version_str = version_str.substr(0, pos);
79 Version os_version(version_str);
80 if (os_version.IsValid() && os_version.components().size() >= 2) {
81 const std::vector<uint32_t>& version_numbers = os_version.components();
82 if (version_numbers[0] == 5)
83 sub_version = kWinXP;
84 else if (version_numbers[0] == 6 && version_numbers[1] == 0)
85 sub_version = kWinVista;
86 else if (version_numbers[0] == 6 && version_numbers[1] == 1)
87 sub_version = kWin7;
88 else if (version_numbers[0] == 6 && version_numbers[1] == 2)
89 sub_version = kWin8;
92 int entry_index = static_cast<int>(sub_version) * kGpuFeatureNumStatus;
93 switch (status) {
94 case kGpuFeatureEnabled:
95 break;
96 case kGpuFeatureBlacklisted:
97 entry_index++;
98 break;
99 case kGpuFeatureDisabled:
100 entry_index += 2;
101 break;
102 case kGpuFeatureNumStatus:
103 NOTREACHED();
104 break;
106 return entry_index;
108 #endif // OS_WIN
110 // Send UMA histograms about the enabled features and GPU properties.
111 void UpdateStats(const gpu::GPUInfo& gpu_info,
112 const gpu::GpuBlacklist* blacklist,
113 const std::set<int>& blacklisted_features) {
114 uint32 max_entry_id = blacklist->max_entry_id();
115 if (max_entry_id == 0) {
116 // GPU Blacklist was not loaded. No need to go further.
117 return;
120 const base::CommandLine& command_line =
121 *base::CommandLine::ForCurrentProcess();
122 bool disabled = false;
124 // Use entry 0 to capture the total number of times that data
125 // was recorded in this histogram in order to have a convenient
126 // denominator to compute blacklist percentages for the rest of the
127 // entries.
128 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry",
129 0, max_entry_id + 1);
131 if (blacklisted_features.size() != 0) {
132 std::vector<uint32> flag_entries;
133 blacklist->GetDecisionEntries(&flag_entries, disabled);
134 DCHECK_GT(flag_entries.size(), 0u);
135 for (size_t i = 0; i < flag_entries.size(); ++i) {
136 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry",
137 flag_entries[i], max_entry_id + 1);
141 // This counts how many users are affected by a disabled entry - this allows
142 // us to understand the impact of an entry before enable it.
143 std::vector<uint32> flag_disabled_entries;
144 disabled = true;
145 blacklist->GetDecisionEntries(&flag_disabled_entries, disabled);
146 for (uint32 disabled_entry : flag_disabled_entries) {
147 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerDisabledEntry",
148 disabled_entry, max_entry_id + 1);
151 const gpu::GpuFeatureType kGpuFeatures[] = {
152 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS,
153 gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING,
154 gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION,
155 gpu::GPU_FEATURE_TYPE_WEBGL};
156 const std::string kGpuBlacklistFeatureHistogramNames[] = {
157 "GPU.BlacklistFeatureTestResults.Accelerated2dCanvas",
158 "GPU.BlacklistFeatureTestResults.GpuCompositing",
159 "GPU.BlacklistFeatureTestResults.GpuRasterization",
160 "GPU.BlacklistFeatureTestResults.Webgl"};
161 const bool kGpuFeatureUserFlags[] = {
162 command_line.HasSwitch(switches::kDisableAccelerated2dCanvas),
163 command_line.HasSwitch(switches::kDisableGpu),
164 command_line.HasSwitch(switches::kDisableGpuRasterization),
165 command_line.HasSwitch(switches::kDisableExperimentalWebGL)};
166 #if defined(OS_WIN)
167 const std::string kGpuBlacklistFeatureHistogramNamesWin[] = {
168 "GPU.BlacklistFeatureTestResultsWindows.Accelerated2dCanvas",
169 "GPU.BlacklistFeatureTestResultsWindows.GpuCompositing",
170 "GPU.BlacklistFeatureTestResultsWindows.GpuRasterization",
171 "GPU.BlacklistFeatureTestResultsWindows.Webgl"};
172 #endif
173 const size_t kNumFeatures =
174 sizeof(kGpuFeatures) / sizeof(gpu::GpuFeatureType);
175 for (size_t i = 0; i < kNumFeatures; ++i) {
176 // We can't use UMA_HISTOGRAM_ENUMERATION here because the same name is
177 // expected if the macro is used within a loop.
178 GpuFeatureStatus value = kGpuFeatureEnabled;
179 if (blacklisted_features.count(kGpuFeatures[i]))
180 value = kGpuFeatureBlacklisted;
181 else if (kGpuFeatureUserFlags[i])
182 value = kGpuFeatureDisabled;
183 base::HistogramBase* histogram_pointer = base::LinearHistogram::FactoryGet(
184 kGpuBlacklistFeatureHistogramNames[i],
185 1, kGpuFeatureNumStatus, kGpuFeatureNumStatus + 1,
186 base::HistogramBase::kUmaTargetedHistogramFlag);
187 histogram_pointer->Add(value);
188 #if defined(OS_WIN)
189 histogram_pointer = base::LinearHistogram::FactoryGet(
190 kGpuBlacklistFeatureHistogramNamesWin[i],
191 1, kNumWinSubVersions * kGpuFeatureNumStatus,
192 kNumWinSubVersions * kGpuFeatureNumStatus + 1,
193 base::HistogramBase::kUmaTargetedHistogramFlag);
194 histogram_pointer->Add(GetGpuBlacklistHistogramValueWin(value));
195 #endif
198 UMA_HISTOGRAM_SPARSE_SLOWLY("GPU.GLResetNotificationStrategy",
199 gpu_info.gl_reset_notification_strategy);
202 // Combine the integers into a string, seperated by ','.
203 std::string IntSetToString(const std::set<int>& list) {
204 std::string rt;
205 for (std::set<int>::const_iterator it = list.begin();
206 it != list.end(); ++it) {
207 if (!rt.empty())
208 rt += ",";
209 rt += base::IntToString(*it);
211 return rt;
214 #if defined(OS_MACOSX)
215 void DisplayReconfigCallback(CGDirectDisplayID display,
216 CGDisplayChangeSummaryFlags flags,
217 void* gpu_data_manager) {
218 if (flags == kCGDisplayBeginConfigurationFlag)
219 return; // This call contains no information about the display change
221 GpuDataManagerImpl* manager =
222 reinterpret_cast<GpuDataManagerImpl*>(gpu_data_manager);
223 DCHECK(manager);
225 // Display change.
226 bool display_changed = false;
227 uint32_t displayCount;
228 CGGetActiveDisplayList(0, NULL, &displayCount);
229 if (displayCount != manager->GetDisplayCount()) {
230 manager->SetDisplayCount(displayCount);
231 display_changed = true;
234 // Gpu change.
235 bool gpu_changed = false;
236 if (flags & kCGDisplayAddFlag) {
237 uint32 vendor_id, device_id;
238 if (gpu::CollectGpuID(&vendor_id, &device_id) == gpu::kCollectInfoSuccess) {
239 gpu_changed = manager->UpdateActiveGpu(vendor_id, device_id);
243 if (display_changed || gpu_changed)
244 manager->HandleGpuSwitch();
246 #endif // OS_MACOSX
248 // Block all domains' use of 3D APIs for this many milliseconds if
249 // approaching a threshold where system stability might be compromised.
250 const int64 kBlockAllDomainsMs = 10000;
251 const int kNumResetsWithinDuration = 1;
253 // Enums for UMA histograms.
254 enum BlockStatusHistogram {
255 BLOCK_STATUS_NOT_BLOCKED,
256 BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED,
257 BLOCK_STATUS_ALL_DOMAINS_BLOCKED,
258 BLOCK_STATUS_MAX
261 } // namespace anonymous
263 void GpuDataManagerImplPrivate::InitializeForTesting(
264 const std::string& gpu_blacklist_json,
265 const gpu::GPUInfo& gpu_info) {
266 // This function is for testing only, so disable histograms.
267 update_histograms_ = false;
269 // Prevent all further initialization.
270 finalized_ = true;
272 InitializeImpl(gpu_blacklist_json, std::string(), gpu_info);
275 bool GpuDataManagerImplPrivate::IsFeatureBlacklisted(int feature) const {
276 #if defined(OS_CHROMEOS)
277 if (feature == gpu::GPU_FEATURE_TYPE_PANEL_FITTING &&
278 base::CommandLine::ForCurrentProcess()->HasSwitch(
279 switches::kDisablePanelFitting)) {
280 return true;
282 #endif // OS_CHROMEOS
283 if (use_swiftshader_ || ShouldUseWarp()) {
284 // Skia's software rendering is probably more efficient than going through
285 // software emulation of the GPU, so use that.
286 if (feature == gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)
287 return true;
288 return false;
291 return (blacklisted_features_.count(feature) == 1);
294 bool GpuDataManagerImplPrivate::IsDriverBugWorkaroundActive(int feature) const {
295 return (gpu_driver_bugs_.count(feature) == 1);
298 size_t GpuDataManagerImplPrivate::GetBlacklistedFeatureCount() const {
299 if (use_swiftshader_ || ShouldUseWarp())
300 return 1;
301 return blacklisted_features_.size();
304 void GpuDataManagerImplPrivate::SetDisplayCount(unsigned int display_count) {
305 display_count_ = display_count;
308 unsigned int GpuDataManagerImplPrivate::GetDisplayCount() const {
309 return display_count_;
312 gpu::GPUInfo GpuDataManagerImplPrivate::GetGPUInfo() const {
313 return gpu_info_;
316 void GpuDataManagerImplPrivate::GetGpuProcessHandles(
317 const GpuDataManager::GetGpuProcessHandlesCallback& callback) const {
318 GpuProcessHost::GetProcessHandles(callback);
321 bool GpuDataManagerImplPrivate::GpuAccessAllowed(
322 std::string* reason) const {
323 if (use_swiftshader_ || ShouldUseWarp())
324 return true;
326 if (!gpu_process_accessible_) {
327 if (reason) {
328 *reason = "GPU process launch failed.";
330 return false;
333 if (card_blacklisted_) {
334 if (reason) {
335 *reason = "GPU access is disabled ";
336 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
337 if (command_line->HasSwitch(switches::kDisableGpu))
338 *reason += "through commandline switch --disable-gpu.";
339 else
340 *reason += "in chrome://settings.";
342 return false;
345 // We only need to block GPU process if more features are disallowed other
346 // than those in the preliminary gpu feature flags because the latter work
347 // through renderer commandline switches.
348 std::set<int> features = preliminary_blacklisted_features_;
349 gpu::MergeFeatureSets(&features, blacklisted_features_);
350 if (features.size() > preliminary_blacklisted_features_.size()) {
351 if (reason) {
352 *reason = "Features are disabled upon full but not preliminary GPU info.";
354 return false;
357 if (blacklisted_features_.size() == gpu::NUMBER_OF_GPU_FEATURE_TYPES) {
358 // On Linux, we use cached GL strings to make blacklist decsions at browser
359 // startup time. We need to launch the GPU process to validate these
360 // strings even if all features are blacklisted. If all GPU features are
361 // disabled, the GPU process will only initialize GL bindings, create a GL
362 // context, and collect full GPU info.
363 #if !defined(OS_LINUX)
364 if (reason) {
365 *reason = "All GPU features are blacklisted.";
367 return false;
368 #endif
371 return true;
374 void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
375 if (complete_gpu_info_already_requested_ || IsCompleteGpuInfoAvailable())
376 return;
377 complete_gpu_info_already_requested_ = true;
379 GpuProcessHost::SendOnIO(
380 #if defined(OS_WIN)
381 GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED,
382 #else
383 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
384 #endif
385 CAUSE_FOR_GPU_LAUNCH_GPUDATAMANAGER_REQUESTCOMPLETEGPUINFOIFNEEDED,
386 new GpuMsg_CollectGraphicsInfo());
389 bool GpuDataManagerImplPrivate::IsEssentialGpuInfoAvailable() const {
390 if (gpu_info_.basic_info_state == gpu::kCollectInfoNone ||
391 gpu_info_.context_info_state == gpu::kCollectInfoNone) {
392 return false;
394 return true;
397 bool GpuDataManagerImplPrivate::IsCompleteGpuInfoAvailable() const {
398 #if defined(OS_WIN)
399 if (gpu_info_.dx_diagnostics_info_state == gpu::kCollectInfoNone)
400 return false;
401 #endif
402 return IsEssentialGpuInfoAvailable();
405 void GpuDataManagerImplPrivate::RequestVideoMemoryUsageStatsUpdate() const {
406 GpuProcessHost::SendOnIO(
407 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
408 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
409 new GpuMsg_GetVideoMemoryUsageStats());
412 bool GpuDataManagerImplPrivate::ShouldUseSwiftShader() const {
413 return use_swiftshader_;
416 void GpuDataManagerImplPrivate::RegisterSwiftShaderPath(
417 const base::FilePath& path) {
418 swiftshader_path_ = path;
419 EnableSwiftShaderIfNecessary();
422 bool GpuDataManagerImplPrivate::ShouldUseWarp() const {
423 std::string angle_impl_flag =
424 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
425 switches::kUseANGLE);
426 return use_warp_ || angle_impl_flag == gfx::kANGLEImplementationWARPName;
429 void GpuDataManagerImplPrivate::AddObserver(GpuDataManagerObserver* observer) {
430 GpuDataManagerImpl::UnlockedSession session(owner_);
431 observer_list_->AddObserver(observer);
434 void GpuDataManagerImplPrivate::RemoveObserver(
435 GpuDataManagerObserver* observer) {
436 GpuDataManagerImpl::UnlockedSession session(owner_);
437 observer_list_->RemoveObserver(observer);
440 void GpuDataManagerImplPrivate::UnblockDomainFrom3DAPIs(const GURL& url) {
441 // This method must do two things:
443 // 1. If the specific domain is blocked, then unblock it.
445 // 2. Reset our notion of how many GPU resets have occurred recently.
446 // This is necessary even if the specific domain was blocked.
447 // Otherwise, if we call Are3DAPIsBlocked with the same domain right
448 // after unblocking it, it will probably still be blocked because of
449 // the recent GPU reset caused by that domain.
451 // These policies could be refined, but at a certain point the behavior
452 // will become difficult to explain.
453 std::string domain = GetDomainFromURL(url);
455 blocked_domains_.erase(domain);
456 timestamps_of_gpu_resets_.clear();
459 void GpuDataManagerImplPrivate::DisableGpuWatchdog() {
460 GpuProcessHost::SendOnIO(
461 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
462 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
463 new GpuMsg_DisableWatchdog);
466 void GpuDataManagerImplPrivate::SetGLStrings(const std::string& gl_vendor,
467 const std::string& gl_renderer,
468 const std::string& gl_version) {
469 if (gl_vendor.empty() && gl_renderer.empty() && gl_version.empty())
470 return;
472 // If GPUInfo already got GL strings, do nothing. This is for the rare
473 // situation where GPU process collected GL strings before this call.
474 if (!gpu_info_.gl_vendor.empty() ||
475 !gpu_info_.gl_renderer.empty() ||
476 !gpu_info_.gl_version.empty())
477 return;
479 gpu::GPUInfo gpu_info = gpu_info_;
481 gpu_info.gl_vendor = gl_vendor;
482 gpu_info.gl_renderer = gl_renderer;
483 gpu_info.gl_version = gl_version;
485 gpu::CollectDriverInfoGL(&gpu_info);
487 UpdateGpuInfo(gpu_info);
488 UpdateGpuSwitchingManager(gpu_info);
489 UpdatePreliminaryBlacklistedFeatures();
492 void GpuDataManagerImplPrivate::GetGLStrings(std::string* gl_vendor,
493 std::string* gl_renderer,
494 std::string* gl_version) {
495 DCHECK(gl_vendor && gl_renderer && gl_version);
497 *gl_vendor = gpu_info_.gl_vendor;
498 *gl_renderer = gpu_info_.gl_renderer;
499 *gl_version = gpu_info_.gl_version;
502 void GpuDataManagerImplPrivate::Initialize() {
503 TRACE_EVENT0("startup", "GpuDataManagerImpl::Initialize");
504 if (finalized_) {
505 DVLOG(0) << "GpuDataManagerImpl marked as finalized; skipping Initialize";
506 return;
509 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
510 if (command_line->HasSwitch(switches::kSkipGpuDataLoading))
511 return;
513 gpu::GPUInfo gpu_info;
514 if (command_line->GetSwitchValueASCII(
515 switches::kUseGL) == gfx::kGLImplementationOSMesaName) {
516 // If using the OSMesa GL implementation, use fake vendor and device ids to
517 // make sure it never gets blacklisted. This is better than simply
518 // cancelling GPUInfo gathering as it allows us to proceed with loading the
519 // blacklist below which may have non-device specific entries we want to
520 // apply anyways (e.g., OS version blacklisting).
521 gpu_info.gpu.vendor_id = 0xffff;
522 gpu_info.gpu.device_id = 0xffff;
524 // Also declare the driver_vendor to be osmesa to be able to specify
525 // exceptions based on driver_vendor==osmesa for some blacklist rules.
526 gpu_info.driver_vendor = gfx::kGLImplementationOSMesaName;
527 } else {
528 TRACE_EVENT0("startup",
529 "GpuDataManagerImpl::Initialize:CollectBasicGraphicsInfo");
530 gpu::CollectBasicGraphicsInfo(&gpu_info);
532 #if defined(ARCH_CPU_X86_FAMILY)
533 if (!gpu_info.gpu.vendor_id || !gpu_info.gpu.device_id) {
534 gpu_info.context_info_state = gpu::kCollectInfoNonFatalFailure;
535 #if defined(OS_WIN)
536 gpu_info.dx_diagnostics_info_state = gpu::kCollectInfoNonFatalFailure;
537 #endif // OS_WIN
539 #endif // ARCH_CPU_X86_FAMILY
541 std::string gpu_blacklist_string;
542 std::string gpu_driver_bug_list_string;
543 if (!command_line->HasSwitch(switches::kIgnoreGpuBlacklist) &&
544 !command_line->HasSwitch(switches::kUseGpuInTests)) {
545 gpu_blacklist_string = gpu::kSoftwareRenderingListJson;
547 if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
548 gpu_driver_bug_list_string = gpu::kGpuDriverBugListJson;
550 InitializeImpl(gpu_blacklist_string,
551 gpu_driver_bug_list_string,
552 gpu_info);
554 if (command_line->HasSwitch(switches::kSingleProcess) ||
555 command_line->HasSwitch(switches::kInProcessGPU)) {
556 command_line->AppendSwitch(switches::kDisableGpuWatchdog);
557 AppendGpuCommandLine(command_line);
561 void GpuDataManagerImplPrivate::UpdateGpuInfoHelper() {
562 GetContentClient()->SetGpuInfo(gpu_info_);
564 if (gpu_blacklist_) {
565 std::set<int> features = gpu_blacklist_->MakeDecision(
566 gpu::GpuControlList::kOsAny, std::string(), gpu_info_);
567 if (update_histograms_)
568 UpdateStats(gpu_info_, gpu_blacklist_.get(), features);
570 UpdateBlacklistedFeatures(features);
572 if (gpu_driver_bug_list_) {
573 gpu_driver_bugs_ = gpu_driver_bug_list_->MakeDecision(
574 gpu::GpuControlList::kOsAny, std::string(), gpu_info_);
576 disabled_extensions_ =
577 base::JoinString(gpu_driver_bug_list_->GetDisabledExtensions(), " ");
579 gpu::GpuDriverBugList::AppendWorkaroundsFromCommandLine(
580 &gpu_driver_bugs_, *base::CommandLine::ForCurrentProcess());
582 // We have to update GpuFeatureType before notify all the observers.
583 NotifyGpuInfoUpdate();
586 void GpuDataManagerImplPrivate::UpdateGpuInfo(const gpu::GPUInfo& gpu_info) {
587 // No further update of gpu_info if falling back to SwiftShader.
588 if (use_swiftshader_ || ShouldUseWarp())
589 return;
591 bool was_info_available = IsCompleteGpuInfoAvailable();
592 gpu::MergeGPUInfo(&gpu_info_, gpu_info);
593 if (IsCompleteGpuInfoAvailable()) {
594 complete_gpu_info_already_requested_ = true;
595 } else if (was_info_available) {
596 // Allow future requests to go through properly.
597 complete_gpu_info_already_requested_ = false;
600 UpdateGpuInfoHelper();
603 void GpuDataManagerImplPrivate::UpdateVideoMemoryUsageStats(
604 const GPUVideoMemoryUsageStats& video_memory_usage_stats) {
605 GpuDataManagerImpl::UnlockedSession session(owner_);
606 observer_list_->Notify(FROM_HERE,
607 &GpuDataManagerObserver::OnVideoMemoryUsageStatsUpdate,
608 video_memory_usage_stats);
611 void GpuDataManagerImplPrivate::AppendRendererCommandLine(
612 base::CommandLine* command_line) const {
613 DCHECK(command_line);
615 if (ShouldDisableAcceleratedVideoDecode(command_line))
616 command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
617 #if defined(ENABLE_WEBRTC)
618 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE) &&
619 !command_line->HasSwitch(switches::kDisableWebRtcHWEncoding))
620 command_line->AppendSwitch(switches::kDisableWebRtcHWEncoding);
621 #endif
623 #if defined(USE_AURA)
624 if (!CanUseGpuBrowserCompositor())
625 command_line->AppendSwitch(switches::kDisableGpuCompositing);
626 #endif
629 void GpuDataManagerImplPrivate::AppendGpuCommandLine(
630 base::CommandLine* command_line) const {
631 DCHECK(command_line);
633 std::string use_gl =
634 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
635 switches::kUseGL);
636 base::FilePath swiftshader_path =
637 base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
638 switches::kSwiftShaderPath);
639 if (gpu_driver_bugs_.find(gpu::DISABLE_D3D11) != gpu_driver_bugs_.end())
640 command_line->AppendSwitch(switches::kDisableD3D11);
641 if (use_swiftshader_) {
642 command_line->AppendSwitchASCII(switches::kUseGL, "swiftshader");
643 if (swiftshader_path.empty())
644 swiftshader_path = swiftshader_path_;
645 } else if ((IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL) ||
646 IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING) ||
647 IsFeatureBlacklisted(
648 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)) &&
649 (use_gl == "any")) {
650 command_line->AppendSwitchASCII(
651 switches::kUseGL, gfx::kGLImplementationOSMesaName);
652 } else if (!use_gl.empty()) {
653 command_line->AppendSwitchASCII(switches::kUseGL, use_gl);
655 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus())
656 command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "true");
657 else
658 command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "false");
660 if (!swiftshader_path.empty()) {
661 command_line->AppendSwitchPath(switches::kSwiftShaderPath,
662 swiftshader_path);
665 if (!gpu_driver_bugs_.empty()) {
666 command_line->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds,
667 IntSetToString(gpu_driver_bugs_));
670 if (!disabled_extensions_.empty()) {
671 command_line->AppendSwitchASCII(switches::kDisableGLExtensions,
672 disabled_extensions_);
675 if (ShouldDisableAcceleratedVideoDecode(command_line)) {
676 command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
678 #if defined(ENABLE_WEBRTC)
679 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE) &&
680 !command_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) {
681 command_line->AppendSwitch(switches::kDisableWebRtcHWEncoding);
683 #endif
685 // Pass GPU and driver information to GPU process. We try to avoid full GPU
686 // info collection at GPU process startup, but we need gpu vendor_id,
687 // device_id, driver_vendor, driver_version for deciding whether we need to
688 // collect full info (on Linux) and for crash reporting purpose.
689 command_line->AppendSwitchASCII(switches::kGpuVendorID,
690 base::StringPrintf("0x%04x", gpu_info_.gpu.vendor_id));
691 command_line->AppendSwitchASCII(switches::kGpuDeviceID,
692 base::StringPrintf("0x%04x", gpu_info_.gpu.device_id));
693 command_line->AppendSwitchASCII(switches::kGpuDriverVendor,
694 gpu_info_.driver_vendor);
695 command_line->AppendSwitchASCII(switches::kGpuDriverVersion,
696 gpu_info_.driver_version);
698 if (ShouldUseWarp() && !command_line->HasSwitch(switches::kUseANGLE)) {
699 command_line->AppendSwitchASCII(switches::kUseANGLE,
700 gfx::kANGLEImplementationWARPName);
704 void GpuDataManagerImplPrivate::AppendPluginCommandLine(
705 base::CommandLine* command_line) const {
706 DCHECK(command_line);
708 #if defined(OS_MACOSX)
709 // TODO(jbauman): Add proper blacklist support for core animation plugins so
710 // special-casing this video card won't be necessary. See
711 // http://crbug.com/134015
712 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING)) {
713 if (!command_line->HasSwitch(
714 switches::kDisableCoreAnimationPlugins))
715 command_line->AppendSwitch(
716 switches::kDisableCoreAnimationPlugins);
718 #endif
721 void GpuDataManagerImplPrivate::UpdateRendererWebPrefs(
722 WebPreferences* prefs) const {
723 DCHECK(prefs);
725 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL)) {
726 prefs->experimental_webgl_enabled = false;
727 prefs->pepper_3d_enabled = false;
729 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH3D))
730 prefs->flash_3d_enabled = false;
731 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D)) {
732 prefs->flash_stage3d_enabled = false;
733 prefs->flash_stage3d_baseline_enabled = false;
735 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE))
736 prefs->flash_stage3d_baseline_enabled = false;
737 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS))
738 prefs->accelerated_2d_canvas_enabled = false;
739 // TODO(senorblanco): The renderer shouldn't have an extra setting
740 // for this, but should rely on extension availability.
741 // Note that |gl_multisampling_enabled| only affects the decoder's
742 // default framebuffer allocation, which does not support
743 // multisampled_render_to_texture, only msaa with explicit resolve.
744 if (IsDriverBugWorkaroundActive(
745 gpu::DISABLE_CHROMIUM_FRAMEBUFFER_MULTISAMPLE) ||
746 (IsDriverBugWorkaroundActive(gpu::DISABLE_MULTIMONITOR_MULTISAMPLING) &&
747 display_count_ > 1))
748 prefs->gl_multisampling_enabled = false;
750 #if defined(USE_AURA)
751 if (!CanUseGpuBrowserCompositor()) {
752 prefs->accelerated_2d_canvas_enabled = false;
753 prefs->pepper_3d_enabled = false;
755 #endif
757 const base::CommandLine* command_line =
758 base::CommandLine::ForCurrentProcess();
759 if (!ShouldDisableAcceleratedVideoDecode(command_line) &&
760 !command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) {
761 prefs->pepper_accelerated_video_decode_enabled = true;
765 void GpuDataManagerImplPrivate::DisableHardwareAcceleration() {
766 card_blacklisted_ = true;
768 for (int i = 0; i < gpu::NUMBER_OF_GPU_FEATURE_TYPES; ++i)
769 blacklisted_features_.insert(i);
771 EnableWarpIfNecessary();
772 EnableSwiftShaderIfNecessary();
773 NotifyGpuInfoUpdate();
776 std::string GpuDataManagerImplPrivate::GetBlacklistVersion() const {
777 if (gpu_blacklist_)
778 return gpu_blacklist_->version();
779 return "0";
782 std::string GpuDataManagerImplPrivate::GetDriverBugListVersion() const {
783 if (gpu_driver_bug_list_)
784 return gpu_driver_bug_list_->version();
785 return "0";
788 void GpuDataManagerImplPrivate::GetBlacklistReasons(
789 base::ListValue* reasons) const {
790 if (gpu_blacklist_)
791 gpu_blacklist_->GetReasons(reasons, "disabledFeatures");
792 if (gpu_driver_bug_list_)
793 gpu_driver_bug_list_->GetReasons(reasons, "workarounds");
796 std::vector<std::string>
797 GpuDataManagerImplPrivate::GetDriverBugWorkarounds() const {
798 std::vector<std::string> workarounds;
799 for (std::set<int>::const_iterator it = gpu_driver_bugs_.begin();
800 it != gpu_driver_bugs_.end(); ++it) {
801 workarounds.push_back(
802 gpu::GpuDriverBugWorkaroundTypeToString(
803 static_cast<gpu::GpuDriverBugWorkaroundType>(*it)));
805 return workarounds;
808 void GpuDataManagerImplPrivate::AddLogMessage(
809 int level, const std::string& header, const std::string& message) {
810 log_messages_.push_back(LogMessage(level, header, message));
813 void GpuDataManagerImplPrivate::ProcessCrashed(
814 base::TerminationStatus exit_code) {
815 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
816 // Unretained is ok, because it's posted to UI thread, the thread
817 // where the singleton GpuDataManagerImpl lives until the end.
818 BrowserThread::PostTask(
819 BrowserThread::UI,
820 FROM_HERE,
821 base::Bind(&GpuDataManagerImpl::ProcessCrashed,
822 base::Unretained(owner_),
823 exit_code));
824 return;
827 gpu_info_.process_crash_count = GpuProcessHost::gpu_crash_count();
828 GpuDataManagerImpl::UnlockedSession session(owner_);
829 observer_list_->Notify(
830 FROM_HERE, &GpuDataManagerObserver::OnGpuProcessCrashed, exit_code);
834 base::ListValue* GpuDataManagerImplPrivate::GetLogMessages() const {
835 base::ListValue* value = new base::ListValue;
836 for (size_t ii = 0; ii < log_messages_.size(); ++ii) {
837 base::DictionaryValue* dict = new base::DictionaryValue();
838 dict->SetInteger("level", log_messages_[ii].level);
839 dict->SetString("header", log_messages_[ii].header);
840 dict->SetString("message", log_messages_[ii].message);
841 value->Append(dict);
843 return value;
846 void GpuDataManagerImplPrivate::HandleGpuSwitch() {
847 GpuDataManagerImpl::UnlockedSession session(owner_);
848 // Notify observers in the browser process.
849 ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched();
850 // Pass the notification to the GPU process to notify observers there.
851 GpuProcessHost::SendOnIO(
852 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
853 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
854 new GpuMsg_GpuSwitched);
857 bool GpuDataManagerImplPrivate::UpdateActiveGpu(
858 uint32 vendor_id, uint32 device_id) {
859 if (gpu_info_.gpu.vendor_id == vendor_id &&
860 gpu_info_.gpu.device_id == device_id) {
861 // The primary GPU is active.
862 if (gpu_info_.gpu.active)
863 return false;
864 gpu_info_.gpu.active = true;
865 for (size_t ii = 0; ii < gpu_info_.secondary_gpus.size(); ++ii)
866 gpu_info_.secondary_gpus[ii].active = false;
867 } else {
868 // A secondary GPU is active.
869 for (size_t ii = 0; ii < gpu_info_.secondary_gpus.size(); ++ii) {
870 if (gpu_info_.secondary_gpus[ii].vendor_id == vendor_id &&
871 gpu_info_.secondary_gpus[ii].device_id == device_id) {
872 if (gpu_info_.secondary_gpus[ii].active)
873 return false;
874 gpu_info_.secondary_gpus[ii].active = true;
875 } else {
876 gpu_info_.secondary_gpus[ii].active = false;
879 gpu_info_.gpu.active = false;
881 UpdateGpuInfoHelper();
882 return true;
885 bool GpuDataManagerImplPrivate::CanUseGpuBrowserCompositor() const {
886 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
887 switches::kDisableGpuCompositing))
888 return false;
889 if (ShouldUseWarp())
890 return true;
891 if (ShouldUseSwiftShader())
892 return false;
893 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING))
894 return false;
895 return true;
899 bool GpuDataManagerImplPrivate::ShouldDisableAcceleratedVideoDecode(
900 const base::CommandLine* command_line) const {
901 // Make sure that we initialize the experiment first to make sure that
902 // statistics are bucket correctly in all cases.
903 // This experiment is temporary and will be removed once enough data
904 // to resolve crbug/442039 has been collected.
905 const std::string group_name = base::FieldTrialList::FindFullName(
906 "DisableAcceleratedVideoDecode");
907 if (command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) {
908 // It was already disabled on the command line.
909 return false;
911 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE))
912 return true;
913 if (group_name == "Disabled")
914 return true;
915 return false;
918 void GpuDataManagerImplPrivate::GetDisabledExtensions(
919 std::string* disabled_extensions) const {
920 DCHECK(disabled_extensions);
922 *disabled_extensions = disabled_extensions_;
925 void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIs(
926 const GURL& url, GpuDataManagerImpl::DomainGuilt guilt) {
927 BlockDomainFrom3DAPIsAtTime(url, guilt, base::Time::Now());
930 bool GpuDataManagerImplPrivate::Are3DAPIsBlocked(const GURL& top_origin_url,
931 int render_process_id,
932 int render_frame_id,
933 ThreeDAPIType requester) {
934 bool blocked = Are3DAPIsBlockedAtTime(top_origin_url, base::Time::Now()) !=
935 GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
936 if (blocked) {
937 // Unretained is ok, because it's posted to UI thread, the thread
938 // where the singleton GpuDataManagerImpl lives until the end.
939 BrowserThread::PostTask(
940 BrowserThread::UI, FROM_HERE,
941 base::Bind(&GpuDataManagerImpl::Notify3DAPIBlocked,
942 base::Unretained(owner_), top_origin_url, render_process_id,
943 render_frame_id, requester));
946 return blocked;
949 void GpuDataManagerImplPrivate::DisableDomainBlockingFor3DAPIsForTesting() {
950 domain_blocking_enabled_ = false;
953 // static
954 GpuDataManagerImplPrivate* GpuDataManagerImplPrivate::Create(
955 GpuDataManagerImpl* owner) {
956 return new GpuDataManagerImplPrivate(owner);
959 GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(
960 GpuDataManagerImpl* owner)
961 : complete_gpu_info_already_requested_(false),
962 observer_list_(new GpuDataManagerObserverList),
963 use_swiftshader_(false),
964 use_warp_(false),
965 card_blacklisted_(false),
966 update_histograms_(true),
967 window_count_(0),
968 domain_blocking_enabled_(true),
969 owner_(owner),
970 display_count_(0),
971 gpu_process_accessible_(true),
972 finalized_(false) {
973 DCHECK(owner_);
974 const base::CommandLine* command_line =
975 base::CommandLine::ForCurrentProcess();
976 if (command_line->HasSwitch(switches::kDisableGpu))
977 DisableHardwareAcceleration();
979 #if defined(OS_MACOSX)
980 CGGetActiveDisplayList (0, NULL, &display_count_);
981 CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback, owner_);
982 #endif // OS_MACOSX
984 // For testing only.
985 if (command_line->HasSwitch(switches::kDisableDomainBlockingFor3DAPIs)) {
986 domain_blocking_enabled_ = false;
990 GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() {
991 #if defined(OS_MACOSX)
992 CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback, owner_);
993 #endif
996 void GpuDataManagerImplPrivate::InitializeImpl(
997 const std::string& gpu_blacklist_json,
998 const std::string& gpu_driver_bug_list_json,
999 const gpu::GPUInfo& gpu_info) {
1000 const bool log_gpu_control_list_decisions =
1001 base::CommandLine::ForCurrentProcess()->HasSwitch(
1002 switches::kLogGpuControlListDecisions);
1004 if (!gpu_blacklist_json.empty()) {
1005 gpu_blacklist_.reset(gpu::GpuBlacklist::Create());
1006 if (log_gpu_control_list_decisions)
1007 gpu_blacklist_->enable_control_list_logging("gpu_blacklist");
1008 bool success = gpu_blacklist_->LoadList(
1009 gpu_blacklist_json, gpu::GpuControlList::kCurrentOsOnly);
1010 DCHECK(success);
1012 if (!gpu_driver_bug_list_json.empty()) {
1013 gpu_driver_bug_list_.reset(gpu::GpuDriverBugList::Create());
1014 if (log_gpu_control_list_decisions)
1015 gpu_driver_bug_list_->enable_control_list_logging("gpu_driver_bug_list");
1016 bool success = gpu_driver_bug_list_->LoadList(
1017 gpu_driver_bug_list_json, gpu::GpuControlList::kCurrentOsOnly);
1018 DCHECK(success);
1021 gpu_info_ = gpu_info;
1022 UpdateGpuInfo(gpu_info);
1023 UpdateGpuSwitchingManager(gpu_info);
1024 UpdatePreliminaryBlacklistedFeatures();
1027 void GpuDataManagerImplPrivate::UpdateBlacklistedFeatures(
1028 const std::set<int>& features) {
1029 blacklisted_features_ = features;
1031 // Force disable using the GPU for these features, even if they would
1032 // otherwise be allowed.
1033 if (card_blacklisted_) {
1034 blacklisted_features_.insert(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING);
1035 blacklisted_features_.insert(gpu::GPU_FEATURE_TYPE_WEBGL);
1038 EnableWarpIfNecessary();
1039 EnableSwiftShaderIfNecessary();
1042 void GpuDataManagerImplPrivate::UpdatePreliminaryBlacklistedFeatures() {
1043 preliminary_blacklisted_features_ = blacklisted_features_;
1046 void GpuDataManagerImplPrivate::UpdateGpuSwitchingManager(
1047 const gpu::GPUInfo& gpu_info) {
1048 // The vendor IDs might be 0 on non-PCI devices (like Android), but
1049 // the length of the vector is all we care about in most cases.
1050 std::vector<uint32> vendor_ids;
1051 vendor_ids.push_back(gpu_info.gpu.vendor_id);
1052 for (const auto& device : gpu_info.secondary_gpus) {
1053 vendor_ids.push_back(device.vendor_id);
1055 ui::GpuSwitchingManager::GetInstance()->SetGpuVendorIds(vendor_ids);
1057 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) {
1058 if (gpu_driver_bugs_.count(gpu::FORCE_DISCRETE_GPU) == 1)
1059 ui::GpuSwitchingManager::GetInstance()->ForceUseOfDiscreteGpu();
1060 else if (gpu_driver_bugs_.count(gpu::FORCE_INTEGRATED_GPU) == 1)
1061 ui::GpuSwitchingManager::GetInstance()->ForceUseOfIntegratedGpu();
1065 void GpuDataManagerImplPrivate::NotifyGpuInfoUpdate() {
1066 observer_list_->Notify(FROM_HERE, &GpuDataManagerObserver::OnGpuInfoUpdate);
1069 void GpuDataManagerImplPrivate::EnableSwiftShaderIfNecessary() {
1070 if (ShouldUseWarp())
1071 return;
1073 if (!GpuAccessAllowed(NULL) ||
1074 blacklisted_features_.count(gpu::GPU_FEATURE_TYPE_WEBGL)) {
1075 if (!swiftshader_path_.empty() &&
1076 !base::CommandLine::ForCurrentProcess()->HasSwitch(
1077 switches::kDisableSoftwareRasterizer))
1078 use_swiftshader_ = true;
1082 void GpuDataManagerImplPrivate::EnableWarpIfNecessary() {
1083 #if defined(OS_WIN)
1084 if (use_warp_)
1085 return;
1086 // We should only use WARP if we are unable to use the regular GPU for
1087 // compositing, and if we in Metro mode.
1088 use_warp_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
1089 switches::kViewerConnect) &&
1090 !CanUseGpuBrowserCompositor();
1091 #endif
1094 void GpuDataManagerImplPrivate::ForceWarpModeForTesting() {
1095 use_warp_ = true;
1098 std::string GpuDataManagerImplPrivate::GetDomainFromURL(
1099 const GURL& url) const {
1100 // For the moment, we just use the host, or its IP address, as the
1101 // entry in the set, rather than trying to figure out the top-level
1102 // domain. This does mean that a.foo.com and b.foo.com will be
1103 // treated independently in the blocking of a given domain, but it
1104 // would require a third-party library to reliably figure out the
1105 // top-level domain from a URL.
1106 if (!url.has_host()) {
1107 return std::string();
1110 return url.host();
1113 void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIsAtTime(
1114 const GURL& url,
1115 GpuDataManagerImpl::DomainGuilt guilt,
1116 base::Time at_time) {
1117 if (!domain_blocking_enabled_)
1118 return;
1120 std::string domain = GetDomainFromURL(url);
1122 DomainBlockEntry& entry = blocked_domains_[domain];
1123 entry.last_guilt = guilt;
1124 timestamps_of_gpu_resets_.push_back(at_time);
1127 GpuDataManagerImpl::DomainBlockStatus
1128 GpuDataManagerImplPrivate::Are3DAPIsBlockedAtTime(
1129 const GURL& url, base::Time at_time) const {
1130 if (!domain_blocking_enabled_)
1131 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
1133 // Note: adjusting the policies in this code will almost certainly
1134 // require adjusting the associated unit tests.
1135 std::string domain = GetDomainFromURL(url);
1137 DomainBlockMap::const_iterator iter = blocked_domains_.find(domain);
1138 if (iter != blocked_domains_.end()) {
1139 // Err on the side of caution, and assume that if a particular
1140 // domain shows up in the block map, it's there for a good
1141 // reason and don't let its presence there automatically expire.
1143 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1144 BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED,
1145 BLOCK_STATUS_MAX);
1147 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED;
1150 // Look at the timestamps of the recent GPU resets to see if there are
1151 // enough within the threshold which would cause us to blacklist all
1152 // domains. This doesn't need to be overly precise -- if time goes
1153 // backward due to a system clock adjustment, that's fine.
1155 // TODO(kbr): make this pay attention to the TDR thresholds in the
1156 // Windows registry, but make sure it continues to be testable.
1158 std::list<base::Time>::iterator iter = timestamps_of_gpu_resets_.begin();
1159 int num_resets_within_timeframe = 0;
1160 while (iter != timestamps_of_gpu_resets_.end()) {
1161 base::Time time = *iter;
1162 base::TimeDelta delta_t = at_time - time;
1164 // If this entry has "expired", just remove it.
1165 if (delta_t.InMilliseconds() > kBlockAllDomainsMs) {
1166 iter = timestamps_of_gpu_resets_.erase(iter);
1167 continue;
1170 ++num_resets_within_timeframe;
1171 ++iter;
1174 if (num_resets_within_timeframe >= kNumResetsWithinDuration) {
1175 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1176 BLOCK_STATUS_ALL_DOMAINS_BLOCKED,
1177 BLOCK_STATUS_MAX);
1179 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED;
1183 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1184 BLOCK_STATUS_NOT_BLOCKED,
1185 BLOCK_STATUS_MAX);
1187 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
1190 int64 GpuDataManagerImplPrivate::GetBlockAllDomainsDurationInMs() const {
1191 return kBlockAllDomainsMs;
1194 void GpuDataManagerImplPrivate::Notify3DAPIBlocked(const GURL& top_origin_url,
1195 int render_process_id,
1196 int render_frame_id,
1197 ThreeDAPIType requester) {
1198 GpuDataManagerImpl::UnlockedSession session(owner_);
1199 observer_list_->Notify(FROM_HERE, &GpuDataManagerObserver::DidBlock3DAPIs,
1200 top_origin_url, render_process_id, render_frame_id,
1201 requester);
1204 void GpuDataManagerImplPrivate::OnGpuProcessInitFailure() {
1205 gpu_process_accessible_ = false;
1206 gpu_info_.context_info_state = gpu::kCollectInfoFatalFailure;
1207 #if defined(OS_WIN)
1208 gpu_info_.dx_diagnostics_info_state = gpu::kCollectInfoFatalFailure;
1209 #endif
1210 complete_gpu_info_already_requested_ = true;
1211 // Some observers might be waiting.
1212 NotifyGpuInfoUpdate();
1215 } // namespace content