Added ability to specify disabled extensions in the GPU Workarounds.
[chromium-blink-merge.git] / content / browser / gpu / gpu_data_manager_impl_private.cc
blob3d50a3b85bffcf9b066532b836f3346ae71d0252
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;
103 return entry_index;
105 #endif // OS_WIN
107 // Send UMA histograms about the enabled features and GPU properties.
108 void UpdateStats(const gpu::GPUInfo& gpu_info,
109 const gpu::GpuBlacklist* blacklist,
110 const std::set<int>& blacklisted_features) {
111 uint32 max_entry_id = blacklist->max_entry_id();
112 if (max_entry_id == 0) {
113 // GPU Blacklist was not loaded. No need to go further.
114 return;
117 const base::CommandLine& command_line =
118 *base::CommandLine::ForCurrentProcess();
119 bool disabled = false;
121 // Use entry 0 to capture the total number of times that data
122 // was recorded in this histogram in order to have a convenient
123 // denominator to compute blacklist percentages for the rest of the
124 // entries.
125 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry",
126 0, max_entry_id + 1);
128 if (blacklisted_features.size() != 0) {
129 std::vector<uint32> flag_entries;
130 blacklist->GetDecisionEntries(&flag_entries, disabled);
131 DCHECK_GT(flag_entries.size(), 0u);
132 for (size_t i = 0; i < flag_entries.size(); ++i) {
133 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry",
134 flag_entries[i], max_entry_id + 1);
138 // This counts how many users are affected by a disabled entry - this allows
139 // us to understand the impact of an entry before enable it.
140 std::vector<uint32> flag_disabled_entries;
141 disabled = true;
142 blacklist->GetDecisionEntries(&flag_disabled_entries, disabled);
143 for (uint32 disabled_entry : flag_disabled_entries) {
144 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerDisabledEntry",
145 disabled_entry, max_entry_id + 1);
148 const gpu::GpuFeatureType kGpuFeatures[] = {
149 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS,
150 gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING, gpu::GPU_FEATURE_TYPE_WEBGL};
151 const std::string kGpuBlacklistFeatureHistogramNames[] = {
152 "GPU.BlacklistFeatureTestResults.Accelerated2dCanvas",
153 "GPU.BlacklistFeatureTestResults.GpuCompositing",
154 "GPU.BlacklistFeatureTestResults.Webgl", };
155 const bool kGpuFeatureUserFlags[] = {
156 command_line.HasSwitch(switches::kDisableAccelerated2dCanvas),
157 command_line.HasSwitch(switches::kDisableGpu),
158 command_line.HasSwitch(switches::kDisableExperimentalWebGL), };
159 #if defined(OS_WIN)
160 const std::string kGpuBlacklistFeatureHistogramNamesWin[] = {
161 "GPU.BlacklistFeatureTestResultsWindows.Accelerated2dCanvas",
162 "GPU.BlacklistFeatureTestResultsWindows.GpuCompositing",
163 "GPU.BlacklistFeatureTestResultsWindows.Webgl", };
164 #endif
165 const size_t kNumFeatures =
166 sizeof(kGpuFeatures) / sizeof(gpu::GpuFeatureType);
167 for (size_t i = 0; i < kNumFeatures; ++i) {
168 // We can't use UMA_HISTOGRAM_ENUMERATION here because the same name is
169 // expected if the macro is used within a loop.
170 GpuFeatureStatus value = kGpuFeatureEnabled;
171 if (blacklisted_features.count(kGpuFeatures[i]))
172 value = kGpuFeatureBlacklisted;
173 else if (kGpuFeatureUserFlags[i])
174 value = kGpuFeatureDisabled;
175 base::HistogramBase* histogram_pointer = base::LinearHistogram::FactoryGet(
176 kGpuBlacklistFeatureHistogramNames[i],
177 1, kGpuFeatureNumStatus, kGpuFeatureNumStatus + 1,
178 base::HistogramBase::kUmaTargetedHistogramFlag);
179 histogram_pointer->Add(value);
180 #if defined(OS_WIN)
181 histogram_pointer = base::LinearHistogram::FactoryGet(
182 kGpuBlacklistFeatureHistogramNamesWin[i],
183 1, kNumWinSubVersions * kGpuFeatureNumStatus,
184 kNumWinSubVersions * kGpuFeatureNumStatus + 1,
185 base::HistogramBase::kUmaTargetedHistogramFlag);
186 histogram_pointer->Add(GetGpuBlacklistHistogramValueWin(value));
187 #endif
190 UMA_HISTOGRAM_SPARSE_SLOWLY("GPU.GLResetNotificationStrategy",
191 gpu_info.gl_reset_notification_strategy);
194 // Combine the integers into a string, seperated by ','.
195 std::string IntSetToString(const std::set<int>& list) {
196 std::string rt;
197 for (std::set<int>::const_iterator it = list.begin();
198 it != list.end(); ++it) {
199 if (!rt.empty())
200 rt += ",";
201 rt += base::IntToString(*it);
203 return rt;
206 #if defined(OS_MACOSX)
207 void DisplayReconfigCallback(CGDirectDisplayID display,
208 CGDisplayChangeSummaryFlags flags,
209 void* gpu_data_manager) {
210 if (flags == kCGDisplayBeginConfigurationFlag)
211 return; // This call contains no information about the display change
213 GpuDataManagerImpl* manager =
214 reinterpret_cast<GpuDataManagerImpl*>(gpu_data_manager);
215 DCHECK(manager);
217 // Display change.
218 bool display_changed = false;
219 uint32_t displayCount;
220 CGGetActiveDisplayList(0, NULL, &displayCount);
221 if (displayCount != manager->GetDisplayCount()) {
222 manager->SetDisplayCount(displayCount);
223 display_changed = true;
226 // Gpu change.
227 bool gpu_changed = false;
228 if (flags & kCGDisplayAddFlag) {
229 uint32 vendor_id, device_id;
230 if (gpu::CollectGpuID(&vendor_id, &device_id) == gpu::kCollectInfoSuccess) {
231 gpu_changed = manager->UpdateActiveGpu(vendor_id, device_id);
235 if (display_changed || gpu_changed)
236 manager->HandleGpuSwitch();
238 #endif // OS_MACOSX
240 // Block all domains' use of 3D APIs for this many milliseconds if
241 // approaching a threshold where system stability might be compromised.
242 const int64 kBlockAllDomainsMs = 10000;
243 const int kNumResetsWithinDuration = 1;
245 // Enums for UMA histograms.
246 enum BlockStatusHistogram {
247 BLOCK_STATUS_NOT_BLOCKED,
248 BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED,
249 BLOCK_STATUS_ALL_DOMAINS_BLOCKED,
250 BLOCK_STATUS_MAX
253 } // namespace anonymous
255 void GpuDataManagerImplPrivate::InitializeForTesting(
256 const std::string& gpu_blacklist_json,
257 const gpu::GPUInfo& gpu_info) {
258 // This function is for testing only, so disable histograms.
259 update_histograms_ = false;
261 // Prevent all further initialization.
262 finalized_ = true;
264 InitializeImpl(gpu_blacklist_json, std::string(), gpu_info);
267 bool GpuDataManagerImplPrivate::IsFeatureBlacklisted(int feature) const {
268 #if defined(OS_CHROMEOS)
269 if (feature == gpu::GPU_FEATURE_TYPE_PANEL_FITTING &&
270 base::CommandLine::ForCurrentProcess()->HasSwitch(
271 switches::kDisablePanelFitting)) {
272 return true;
274 #endif // OS_CHROMEOS
275 if (use_swiftshader_ || ShouldUseWarp()) {
276 // Skia's software rendering is probably more efficient than going through
277 // software emulation of the GPU, so use that.
278 if (feature == gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)
279 return true;
280 return false;
283 return (blacklisted_features_.count(feature) == 1);
286 bool GpuDataManagerImplPrivate::IsDriverBugWorkaroundActive(int feature) const {
287 return (gpu_driver_bugs_.count(feature) == 1);
290 size_t GpuDataManagerImplPrivate::GetBlacklistedFeatureCount() const {
291 if (use_swiftshader_ || ShouldUseWarp())
292 return 1;
293 return blacklisted_features_.size();
296 void GpuDataManagerImplPrivate::SetDisplayCount(unsigned int display_count) {
297 display_count_ = display_count;
300 unsigned int GpuDataManagerImplPrivate::GetDisplayCount() const {
301 return display_count_;
304 gpu::GPUInfo GpuDataManagerImplPrivate::GetGPUInfo() const {
305 return gpu_info_;
308 void GpuDataManagerImplPrivate::GetGpuProcessHandles(
309 const GpuDataManager::GetGpuProcessHandlesCallback& callback) const {
310 GpuProcessHost::GetProcessHandles(callback);
313 bool GpuDataManagerImplPrivate::GpuAccessAllowed(
314 std::string* reason) const {
315 if (use_swiftshader_ || ShouldUseWarp())
316 return true;
318 if (!gpu_process_accessible_) {
319 if (reason) {
320 *reason = "GPU process launch failed.";
322 return false;
325 if (card_blacklisted_) {
326 if (reason) {
327 *reason = "GPU access is disabled ";
328 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
329 if (command_line->HasSwitch(switches::kDisableGpu))
330 *reason += "through commandline switch --disable-gpu.";
331 else
332 *reason += "in chrome://settings.";
334 return false;
337 // We only need to block GPU process if more features are disallowed other
338 // than those in the preliminary gpu feature flags because the latter work
339 // through renderer commandline switches.
340 std::set<int> features = preliminary_blacklisted_features_;
341 gpu::MergeFeatureSets(&features, blacklisted_features_);
342 if (features.size() > preliminary_blacklisted_features_.size()) {
343 if (reason) {
344 *reason = "Features are disabled upon full but not preliminary GPU info.";
346 return false;
349 if (blacklisted_features_.size() == gpu::NUMBER_OF_GPU_FEATURE_TYPES) {
350 // On Linux, we use cached GL strings to make blacklist decsions at browser
351 // startup time. We need to launch the GPU process to validate these
352 // strings even if all features are blacklisted. If all GPU features are
353 // disabled, the GPU process will only initialize GL bindings, create a GL
354 // context, and collect full GPU info.
355 #if !defined(OS_LINUX)
356 if (reason) {
357 *reason = "All GPU features are blacklisted.";
359 return false;
360 #endif
363 return true;
366 void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
367 if (complete_gpu_info_already_requested_ || IsCompleteGpuInfoAvailable())
368 return;
369 complete_gpu_info_already_requested_ = true;
371 GpuProcessHost::SendOnIO(
372 #if defined(OS_WIN)
373 GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED,
374 #else
375 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
376 #endif
377 CAUSE_FOR_GPU_LAUNCH_GPUDATAMANAGER_REQUESTCOMPLETEGPUINFOIFNEEDED,
378 new GpuMsg_CollectGraphicsInfo());
381 bool GpuDataManagerImplPrivate::IsEssentialGpuInfoAvailable() const {
382 if (gpu_info_.basic_info_state == gpu::kCollectInfoNone ||
383 gpu_info_.context_info_state == gpu::kCollectInfoNone) {
384 return false;
386 return true;
389 bool GpuDataManagerImplPrivate::IsCompleteGpuInfoAvailable() const {
390 #if defined(OS_WIN)
391 if (gpu_info_.dx_diagnostics_info_state == gpu::kCollectInfoNone)
392 return false;
393 #endif
394 return IsEssentialGpuInfoAvailable();
397 void GpuDataManagerImplPrivate::RequestVideoMemoryUsageStatsUpdate() const {
398 GpuProcessHost::SendOnIO(
399 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
400 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
401 new GpuMsg_GetVideoMemoryUsageStats());
404 bool GpuDataManagerImplPrivate::ShouldUseSwiftShader() const {
405 return use_swiftshader_;
408 void GpuDataManagerImplPrivate::RegisterSwiftShaderPath(
409 const base::FilePath& path) {
410 swiftshader_path_ = path;
411 EnableSwiftShaderIfNecessary();
414 bool GpuDataManagerImplPrivate::ShouldUseWarp() const {
415 return use_warp_ ||
416 base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseWarp);
419 void GpuDataManagerImplPrivate::AddObserver(GpuDataManagerObserver* observer) {
420 GpuDataManagerImpl::UnlockedSession session(owner_);
421 observer_list_->AddObserver(observer);
424 void GpuDataManagerImplPrivate::RemoveObserver(
425 GpuDataManagerObserver* observer) {
426 GpuDataManagerImpl::UnlockedSession session(owner_);
427 observer_list_->RemoveObserver(observer);
430 void GpuDataManagerImplPrivate::UnblockDomainFrom3DAPIs(const GURL& url) {
431 // This method must do two things:
433 // 1. If the specific domain is blocked, then unblock it.
435 // 2. Reset our notion of how many GPU resets have occurred recently.
436 // This is necessary even if the specific domain was blocked.
437 // Otherwise, if we call Are3DAPIsBlocked with the same domain right
438 // after unblocking it, it will probably still be blocked because of
439 // the recent GPU reset caused by that domain.
441 // These policies could be refined, but at a certain point the behavior
442 // will become difficult to explain.
443 std::string domain = GetDomainFromURL(url);
445 blocked_domains_.erase(domain);
446 timestamps_of_gpu_resets_.clear();
449 void GpuDataManagerImplPrivate::DisableGpuWatchdog() {
450 GpuProcessHost::SendOnIO(
451 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
452 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
453 new GpuMsg_DisableWatchdog);
456 void GpuDataManagerImplPrivate::SetGLStrings(const std::string& gl_vendor,
457 const std::string& gl_renderer,
458 const std::string& gl_version) {
459 if (gl_vendor.empty() && gl_renderer.empty() && gl_version.empty())
460 return;
462 // If GPUInfo already got GL strings, do nothing. This is for the rare
463 // situation where GPU process collected GL strings before this call.
464 if (!gpu_info_.gl_vendor.empty() ||
465 !gpu_info_.gl_renderer.empty() ||
466 !gpu_info_.gl_version.empty())
467 return;
469 gpu::GPUInfo gpu_info = gpu_info_;
471 gpu_info.gl_vendor = gl_vendor;
472 gpu_info.gl_renderer = gl_renderer;
473 gpu_info.gl_version = gl_version;
475 gpu::CollectDriverInfoGL(&gpu_info);
477 UpdateGpuInfo(gpu_info);
478 UpdateGpuSwitchingManager(gpu_info);
479 UpdatePreliminaryBlacklistedFeatures();
482 void GpuDataManagerImplPrivate::GetGLStrings(std::string* gl_vendor,
483 std::string* gl_renderer,
484 std::string* gl_version) {
485 DCHECK(gl_vendor && gl_renderer && gl_version);
487 *gl_vendor = gpu_info_.gl_vendor;
488 *gl_renderer = gpu_info_.gl_renderer;
489 *gl_version = gpu_info_.gl_version;
492 void GpuDataManagerImplPrivate::Initialize() {
493 TRACE_EVENT0("startup", "GpuDataManagerImpl::Initialize");
494 if (finalized_) {
495 DVLOG(0) << "GpuDataManagerImpl marked as finalized; skipping Initialize";
496 return;
499 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
500 if (command_line->HasSwitch(switches::kSkipGpuDataLoading))
501 return;
503 gpu::GPUInfo gpu_info;
504 if (command_line->GetSwitchValueASCII(
505 switches::kUseGL) == gfx::kGLImplementationOSMesaName) {
506 // If using the OSMesa GL implementation, use fake vendor and device ids to
507 // make sure it never gets blacklisted. This is better than simply
508 // cancelling GPUInfo gathering as it allows us to proceed with loading the
509 // blacklist below which may have non-device specific entries we want to
510 // apply anyways (e.g., OS version blacklisting).
511 gpu_info.gpu.vendor_id = 0xffff;
512 gpu_info.gpu.device_id = 0xffff;
514 // Also declare the driver_vendor to be osmesa to be able to specify
515 // exceptions based on driver_vendor==osmesa for some blacklist rules.
516 gpu_info.driver_vendor = gfx::kGLImplementationOSMesaName;
517 } else {
518 TRACE_EVENT0("startup",
519 "GpuDataManagerImpl::Initialize:CollectBasicGraphicsInfo");
520 gpu::CollectBasicGraphicsInfo(&gpu_info);
522 #if defined(ARCH_CPU_X86_FAMILY)
523 if (!gpu_info.gpu.vendor_id || !gpu_info.gpu.device_id) {
524 gpu_info.context_info_state = gpu::kCollectInfoNonFatalFailure;
525 #if defined(OS_WIN)
526 gpu_info.dx_diagnostics_info_state = gpu::kCollectInfoNonFatalFailure;
527 #endif // OS_WIN
529 #endif // ARCH_CPU_X86_FAMILY
531 std::string gpu_blacklist_string;
532 std::string gpu_driver_bug_list_string;
533 if (!command_line->HasSwitch(switches::kIgnoreGpuBlacklist) &&
534 !command_line->HasSwitch(switches::kUseGpuInTests)) {
535 gpu_blacklist_string = gpu::kSoftwareRenderingListJson;
537 if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
538 gpu_driver_bug_list_string = gpu::kGpuDriverBugListJson;
540 InitializeImpl(gpu_blacklist_string,
541 gpu_driver_bug_list_string,
542 gpu_info);
544 if (command_line->HasSwitch(switches::kSingleProcess) ||
545 command_line->HasSwitch(switches::kInProcessGPU)) {
546 command_line->AppendSwitch(switches::kDisableGpuWatchdog);
547 AppendGpuCommandLine(command_line);
551 void GpuDataManagerImplPrivate::UpdateGpuInfoHelper() {
552 GetContentClient()->SetGpuInfo(gpu_info_);
554 if (gpu_blacklist_) {
555 std::set<int> features = gpu_blacklist_->MakeDecision(
556 gpu::GpuControlList::kOsAny, std::string(), gpu_info_);
557 if (update_histograms_)
558 UpdateStats(gpu_info_, gpu_blacklist_.get(), features);
560 UpdateBlacklistedFeatures(features);
562 if (gpu_driver_bug_list_) {
563 gpu_driver_bugs_ = gpu_driver_bug_list_->MakeDecision(
564 gpu::GpuControlList::kOsAny, std::string(), gpu_info_);
566 disabled_extensions_ =
567 JoinString(gpu_driver_bug_list_->GetDisabledExtensions(), ' ');
569 gpu::GpuDriverBugList::AppendWorkaroundsFromCommandLine(
570 &gpu_driver_bugs_, *base::CommandLine::ForCurrentProcess());
572 // We have to update GpuFeatureType before notify all the observers.
573 NotifyGpuInfoUpdate();
576 void GpuDataManagerImplPrivate::UpdateGpuInfo(const gpu::GPUInfo& gpu_info) {
577 // No further update of gpu_info if falling back to SwiftShader.
578 if (use_swiftshader_ || ShouldUseWarp())
579 return;
581 bool was_info_available = IsCompleteGpuInfoAvailable();
582 gpu::MergeGPUInfo(&gpu_info_, gpu_info);
583 if (IsCompleteGpuInfoAvailable()) {
584 complete_gpu_info_already_requested_ = true;
585 } else if (was_info_available) {
586 // Allow future requests to go through properly.
587 complete_gpu_info_already_requested_ = false;
590 UpdateGpuInfoHelper();
593 void GpuDataManagerImplPrivate::UpdateVideoMemoryUsageStats(
594 const GPUVideoMemoryUsageStats& video_memory_usage_stats) {
595 GpuDataManagerImpl::UnlockedSession session(owner_);
596 observer_list_->Notify(FROM_HERE,
597 &GpuDataManagerObserver::OnVideoMemoryUsageStatsUpdate,
598 video_memory_usage_stats);
601 void GpuDataManagerImplPrivate::AppendRendererCommandLine(
602 base::CommandLine* command_line) const {
603 DCHECK(command_line);
605 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) &&
606 !command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode))
607 command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
608 #if defined(ENABLE_WEBRTC)
609 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE) &&
610 !command_line->HasSwitch(switches::kDisableWebRtcHWEncoding))
611 command_line->AppendSwitch(switches::kDisableWebRtcHWEncoding);
612 #endif
614 #if defined(USE_AURA)
615 if (!CanUseGpuBrowserCompositor())
616 command_line->AppendSwitch(switches::kDisableGpuCompositing);
617 #endif
620 void GpuDataManagerImplPrivate::AppendGpuCommandLine(
621 base::CommandLine* command_line) const {
622 DCHECK(command_line);
624 std::string use_gl =
625 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
626 switches::kUseGL);
627 base::FilePath swiftshader_path =
628 base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
629 switches::kSwiftShaderPath);
630 if (gpu_driver_bugs_.find(gpu::DISABLE_D3D11) != gpu_driver_bugs_.end())
631 command_line->AppendSwitch(switches::kDisableD3D11);
632 if (use_swiftshader_) {
633 command_line->AppendSwitchASCII(switches::kUseGL, "swiftshader");
634 if (swiftshader_path.empty())
635 swiftshader_path = swiftshader_path_;
636 } else if ((IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL) ||
637 IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING) ||
638 IsFeatureBlacklisted(
639 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)) &&
640 (use_gl == "any")) {
641 command_line->AppendSwitchASCII(
642 switches::kUseGL, gfx::kGLImplementationOSMesaName);
643 } else if (!use_gl.empty()) {
644 command_line->AppendSwitchASCII(switches::kUseGL, use_gl);
646 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus())
647 command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "true");
648 else
649 command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "false");
651 if (!swiftshader_path.empty()) {
652 command_line->AppendSwitchPath(switches::kSwiftShaderPath,
653 swiftshader_path);
656 if (!gpu_driver_bugs_.empty()) {
657 command_line->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds,
658 IntSetToString(gpu_driver_bugs_));
661 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) &&
662 !command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) {
663 command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
665 #if defined(ENABLE_WEBRTC)
666 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE) &&
667 !command_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) {
668 command_line->AppendSwitch(switches::kDisableWebRtcHWEncoding);
670 #endif
672 // Pass GPU and driver information to GPU process. We try to avoid full GPU
673 // info collection at GPU process startup, but we need gpu vendor_id,
674 // device_id, driver_vendor, driver_version for deciding whether we need to
675 // collect full info (on Linux) and for crash reporting purpose.
676 command_line->AppendSwitchASCII(switches::kGpuVendorID,
677 base::StringPrintf("0x%04x", gpu_info_.gpu.vendor_id));
678 command_line->AppendSwitchASCII(switches::kGpuDeviceID,
679 base::StringPrintf("0x%04x", gpu_info_.gpu.device_id));
680 command_line->AppendSwitchASCII(switches::kGpuDriverVendor,
681 gpu_info_.driver_vendor);
682 command_line->AppendSwitchASCII(switches::kGpuDriverVersion,
683 gpu_info_.driver_version);
685 if (ShouldUseWarp())
686 command_line->AppendSwitch(switches::kUseWarp);
689 void GpuDataManagerImplPrivate::AppendPluginCommandLine(
690 base::CommandLine* command_line) const {
691 DCHECK(command_line);
693 #if defined(OS_MACOSX)
694 // TODO(jbauman): Add proper blacklist support for core animation plugins so
695 // special-casing this video card won't be necessary. See
696 // http://crbug.com/134015
697 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING)) {
698 if (!command_line->HasSwitch(
699 switches::kDisableCoreAnimationPlugins))
700 command_line->AppendSwitch(
701 switches::kDisableCoreAnimationPlugins);
703 #endif
706 void GpuDataManagerImplPrivate::UpdateRendererWebPrefs(
707 WebPreferences* prefs) const {
708 DCHECK(prefs);
710 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL)) {
711 prefs->experimental_webgl_enabled = false;
712 prefs->pepper_3d_enabled = false;
714 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH3D))
715 prefs->flash_3d_enabled = false;
716 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D)) {
717 prefs->flash_stage3d_enabled = false;
718 prefs->flash_stage3d_baseline_enabled = false;
720 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE))
721 prefs->flash_stage3d_baseline_enabled = false;
722 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS))
723 prefs->accelerated_2d_canvas_enabled = false;
724 // TODO(senorblanco): The renderer shouldn't have an extra setting
725 // for this, but should rely on extension availability.
726 // Note that |gl_multisampling_enabled| only affects the decoder's
727 // default framebuffer allocation, which does not support
728 // multisampled_render_to_texture, only msaa with explicit resolve.
729 if (IsDriverBugWorkaroundActive(
730 gpu::DISABLE_CHROMIUM_FRAMEBUFFER_MULTISAMPLE) ||
731 (IsDriverBugWorkaroundActive(gpu::DISABLE_MULTIMONITOR_MULTISAMPLING) &&
732 display_count_ > 1))
733 prefs->gl_multisampling_enabled = false;
735 #if defined(USE_AURA)
736 if (!CanUseGpuBrowserCompositor()) {
737 prefs->accelerated_2d_canvas_enabled = false;
738 prefs->pepper_3d_enabled = false;
740 #endif
742 if (!IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) &&
743 !base::CommandLine::ForCurrentProcess()->HasSwitch(
744 switches::kDisableAcceleratedVideoDecode)) {
745 prefs->pepper_accelerated_video_decode_enabled = true;
749 void GpuDataManagerImplPrivate::DisableHardwareAcceleration() {
750 card_blacklisted_ = true;
752 for (int i = 0; i < gpu::NUMBER_OF_GPU_FEATURE_TYPES; ++i)
753 blacklisted_features_.insert(i);
755 EnableWarpIfNecessary();
756 EnableSwiftShaderIfNecessary();
757 NotifyGpuInfoUpdate();
760 std::string GpuDataManagerImplPrivate::GetBlacklistVersion() const {
761 if (gpu_blacklist_)
762 return gpu_blacklist_->version();
763 return "0";
766 std::string GpuDataManagerImplPrivate::GetDriverBugListVersion() const {
767 if (gpu_driver_bug_list_)
768 return gpu_driver_bug_list_->version();
769 return "0";
772 void GpuDataManagerImplPrivate::GetBlacklistReasons(
773 base::ListValue* reasons) const {
774 if (gpu_blacklist_)
775 gpu_blacklist_->GetReasons(reasons, "disabledFeatures");
776 if (gpu_driver_bug_list_)
777 gpu_driver_bug_list_->GetReasons(reasons, "workarounds");
780 std::vector<std::string>
781 GpuDataManagerImplPrivate::GetDriverBugWorkarounds() const {
782 std::vector<std::string> workarounds;
783 for (std::set<int>::const_iterator it = gpu_driver_bugs_.begin();
784 it != gpu_driver_bugs_.end(); ++it) {
785 workarounds.push_back(
786 gpu::GpuDriverBugWorkaroundTypeToString(
787 static_cast<gpu::GpuDriverBugWorkaroundType>(*it)));
789 return workarounds;
792 void GpuDataManagerImplPrivate::AddLogMessage(
793 int level, const std::string& header, const std::string& message) {
794 log_messages_.push_back(LogMessage(level, header, message));
797 void GpuDataManagerImplPrivate::ProcessCrashed(
798 base::TerminationStatus exit_code) {
799 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
800 // Unretained is ok, because it's posted to UI thread, the thread
801 // where the singleton GpuDataManagerImpl lives until the end.
802 BrowserThread::PostTask(
803 BrowserThread::UI,
804 FROM_HERE,
805 base::Bind(&GpuDataManagerImpl::ProcessCrashed,
806 base::Unretained(owner_),
807 exit_code));
808 return;
811 gpu_info_.process_crash_count = GpuProcessHost::gpu_crash_count();
812 GpuDataManagerImpl::UnlockedSession session(owner_);
813 observer_list_->Notify(
814 FROM_HERE, &GpuDataManagerObserver::OnGpuProcessCrashed, exit_code);
818 base::ListValue* GpuDataManagerImplPrivate::GetLogMessages() const {
819 base::ListValue* value = new base::ListValue;
820 for (size_t ii = 0; ii < log_messages_.size(); ++ii) {
821 base::DictionaryValue* dict = new base::DictionaryValue();
822 dict->SetInteger("level", log_messages_[ii].level);
823 dict->SetString("header", log_messages_[ii].header);
824 dict->SetString("message", log_messages_[ii].message);
825 value->Append(dict);
827 return value;
830 void GpuDataManagerImplPrivate::HandleGpuSwitch() {
831 GpuDataManagerImpl::UnlockedSession session(owner_);
832 // Notify observers in the browser process.
833 ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched();
834 // Pass the notification to the GPU process to notify observers there.
835 GpuProcessHost::SendOnIO(
836 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
837 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
838 new GpuMsg_GpuSwitched);
841 bool GpuDataManagerImplPrivate::UpdateActiveGpu(
842 uint32 vendor_id, uint32 device_id) {
843 if (gpu_info_.gpu.vendor_id == vendor_id &&
844 gpu_info_.gpu.device_id == device_id) {
845 // The primary GPU is active.
846 if (gpu_info_.gpu.active)
847 return false;
848 gpu_info_.gpu.active = true;
849 for (size_t ii = 0; ii < gpu_info_.secondary_gpus.size(); ++ii)
850 gpu_info_.secondary_gpus[ii].active = false;
851 } else {
852 // A secondary GPU is active.
853 for (size_t ii = 0; ii < gpu_info_.secondary_gpus.size(); ++ii) {
854 if (gpu_info_.secondary_gpus[ii].vendor_id == vendor_id &&
855 gpu_info_.secondary_gpus[ii].device_id == device_id) {
856 if (gpu_info_.secondary_gpus[ii].active)
857 return false;
858 gpu_info_.secondary_gpus[ii].active = true;
859 } else {
860 gpu_info_.secondary_gpus[ii].active = false;
863 gpu_info_.gpu.active = false;
865 UpdateGpuInfoHelper();
866 return true;
869 bool GpuDataManagerImplPrivate::CanUseGpuBrowserCompositor() const {
870 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
871 switches::kDisableGpuCompositing))
872 return false;
873 if (ShouldUseWarp())
874 return true;
875 if (ShouldUseSwiftShader())
876 return false;
877 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING))
878 return false;
879 return true;
882 void GpuDataManagerImplPrivate::GetDisabledExtensions(
883 std::string* disabled_extensions) const {
884 DCHECK(disabled_extensions);
886 *disabled_extensions = disabled_extensions_;
889 void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIs(
890 const GURL& url, GpuDataManagerImpl::DomainGuilt guilt) {
891 BlockDomainFrom3DAPIsAtTime(url, guilt, base::Time::Now());
894 bool GpuDataManagerImplPrivate::Are3DAPIsBlocked(const GURL& url,
895 int render_process_id,
896 int render_view_id,
897 ThreeDAPIType requester) {
898 bool blocked = Are3DAPIsBlockedAtTime(url, base::Time::Now()) !=
899 GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
900 if (blocked) {
901 // Unretained is ok, because it's posted to UI thread, the thread
902 // where the singleton GpuDataManagerImpl lives until the end.
903 BrowserThread::PostTask(
904 BrowserThread::UI, FROM_HERE,
905 base::Bind(&GpuDataManagerImpl::Notify3DAPIBlocked,
906 base::Unretained(owner_), url, render_process_id,
907 render_view_id, requester));
910 return blocked;
913 void GpuDataManagerImplPrivate::DisableDomainBlockingFor3DAPIsForTesting() {
914 domain_blocking_enabled_ = false;
917 // static
918 GpuDataManagerImplPrivate* GpuDataManagerImplPrivate::Create(
919 GpuDataManagerImpl* owner) {
920 return new GpuDataManagerImplPrivate(owner);
923 GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(
924 GpuDataManagerImpl* owner)
925 : complete_gpu_info_already_requested_(false),
926 observer_list_(new GpuDataManagerObserverList),
927 use_swiftshader_(false),
928 use_warp_(false),
929 card_blacklisted_(false),
930 update_histograms_(true),
931 window_count_(0),
932 domain_blocking_enabled_(true),
933 owner_(owner),
934 display_count_(0),
935 gpu_process_accessible_(true),
936 finalized_(false) {
937 DCHECK(owner_);
938 const base::CommandLine* command_line =
939 base::CommandLine::ForCurrentProcess();
940 if (command_line->HasSwitch(switches::kDisableGpu))
941 DisableHardwareAcceleration();
943 #if defined(OS_MACOSX)
944 CGGetActiveDisplayList (0, NULL, &display_count_);
945 CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback, owner_);
946 #endif // OS_MACOSX
948 // For testing only.
949 if (command_line->HasSwitch(switches::kDisableDomainBlockingFor3DAPIs)) {
950 domain_blocking_enabled_ = false;
954 GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() {
955 #if defined(OS_MACOSX)
956 CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback, owner_);
957 #endif
960 void GpuDataManagerImplPrivate::InitializeImpl(
961 const std::string& gpu_blacklist_json,
962 const std::string& gpu_driver_bug_list_json,
963 const gpu::GPUInfo& gpu_info) {
964 const bool log_gpu_control_list_decisions =
965 base::CommandLine::ForCurrentProcess()->HasSwitch(
966 switches::kLogGpuControlListDecisions);
968 if (!gpu_blacklist_json.empty()) {
969 gpu_blacklist_.reset(gpu::GpuBlacklist::Create());
970 if (log_gpu_control_list_decisions)
971 gpu_blacklist_->enable_control_list_logging("gpu_blacklist");
972 bool success = gpu_blacklist_->LoadList(
973 gpu_blacklist_json, gpu::GpuControlList::kCurrentOsOnly);
974 DCHECK(success);
976 if (!gpu_driver_bug_list_json.empty()) {
977 gpu_driver_bug_list_.reset(gpu::GpuDriverBugList::Create());
978 if (log_gpu_control_list_decisions)
979 gpu_driver_bug_list_->enable_control_list_logging("gpu_driver_bug_list");
980 bool success = gpu_driver_bug_list_->LoadList(
981 gpu_driver_bug_list_json, gpu::GpuControlList::kCurrentOsOnly);
982 DCHECK(success);
985 gpu_info_ = gpu_info;
986 UpdateGpuInfo(gpu_info);
987 UpdateGpuSwitchingManager(gpu_info);
988 UpdatePreliminaryBlacklistedFeatures();
991 void GpuDataManagerImplPrivate::UpdateBlacklistedFeatures(
992 const std::set<int>& features) {
993 blacklisted_features_ = features;
995 // Force disable using the GPU for these features, even if they would
996 // otherwise be allowed.
997 if (card_blacklisted_) {
998 blacklisted_features_.insert(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING);
999 blacklisted_features_.insert(gpu::GPU_FEATURE_TYPE_WEBGL);
1002 EnableWarpIfNecessary();
1003 EnableSwiftShaderIfNecessary();
1006 void GpuDataManagerImplPrivate::UpdatePreliminaryBlacklistedFeatures() {
1007 preliminary_blacklisted_features_ = blacklisted_features_;
1010 void GpuDataManagerImplPrivate::UpdateGpuSwitchingManager(
1011 const gpu::GPUInfo& gpu_info) {
1012 ui::GpuSwitchingManager::GetInstance()->SetGpuCount(
1013 gpu_info.secondary_gpus.size() + 1);
1015 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) {
1016 if (gpu_driver_bugs_.count(gpu::FORCE_DISCRETE_GPU) == 1)
1017 ui::GpuSwitchingManager::GetInstance()->ForceUseOfDiscreteGpu();
1018 else if (gpu_driver_bugs_.count(gpu::FORCE_INTEGRATED_GPU) == 1)
1019 ui::GpuSwitchingManager::GetInstance()->ForceUseOfIntegratedGpu();
1023 void GpuDataManagerImplPrivate::NotifyGpuInfoUpdate() {
1024 observer_list_->Notify(FROM_HERE, &GpuDataManagerObserver::OnGpuInfoUpdate);
1027 void GpuDataManagerImplPrivate::EnableSwiftShaderIfNecessary() {
1028 if (ShouldUseWarp())
1029 return;
1031 if (!GpuAccessAllowed(NULL) ||
1032 blacklisted_features_.count(gpu::GPU_FEATURE_TYPE_WEBGL)) {
1033 if (!swiftshader_path_.empty() &&
1034 !base::CommandLine::ForCurrentProcess()->HasSwitch(
1035 switches::kDisableSoftwareRasterizer))
1036 use_swiftshader_ = true;
1040 void GpuDataManagerImplPrivate::EnableWarpIfNecessary() {
1041 #if defined(OS_WIN)
1042 if (use_warp_)
1043 return;
1044 // We should only use WARP if we are unable to use the regular GPU for
1045 // compositing, and if we in Metro mode.
1046 use_warp_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
1047 switches::kViewerConnect) &&
1048 !CanUseGpuBrowserCompositor();
1049 #endif
1052 void GpuDataManagerImplPrivate::ForceWarpModeForTesting() {
1053 use_warp_ = true;
1056 std::string GpuDataManagerImplPrivate::GetDomainFromURL(
1057 const GURL& url) const {
1058 // For the moment, we just use the host, or its IP address, as the
1059 // entry in the set, rather than trying to figure out the top-level
1060 // domain. This does mean that a.foo.com and b.foo.com will be
1061 // treated independently in the blocking of a given domain, but it
1062 // would require a third-party library to reliably figure out the
1063 // top-level domain from a URL.
1064 if (!url.has_host()) {
1065 return std::string();
1068 return url.host();
1071 void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIsAtTime(
1072 const GURL& url,
1073 GpuDataManagerImpl::DomainGuilt guilt,
1074 base::Time at_time) {
1075 if (!domain_blocking_enabled_)
1076 return;
1078 std::string domain = GetDomainFromURL(url);
1080 DomainBlockEntry& entry = blocked_domains_[domain];
1081 entry.last_guilt = guilt;
1082 timestamps_of_gpu_resets_.push_back(at_time);
1085 GpuDataManagerImpl::DomainBlockStatus
1086 GpuDataManagerImplPrivate::Are3DAPIsBlockedAtTime(
1087 const GURL& url, base::Time at_time) const {
1088 if (!domain_blocking_enabled_)
1089 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
1091 // Note: adjusting the policies in this code will almost certainly
1092 // require adjusting the associated unit tests.
1093 std::string domain = GetDomainFromURL(url);
1095 DomainBlockMap::const_iterator iter = blocked_domains_.find(domain);
1096 if (iter != blocked_domains_.end()) {
1097 // Err on the side of caution, and assume that if a particular
1098 // domain shows up in the block map, it's there for a good
1099 // reason and don't let its presence there automatically expire.
1101 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1102 BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED,
1103 BLOCK_STATUS_MAX);
1105 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED;
1108 // Look at the timestamps of the recent GPU resets to see if there are
1109 // enough within the threshold which would cause us to blacklist all
1110 // domains. This doesn't need to be overly precise -- if time goes
1111 // backward due to a system clock adjustment, that's fine.
1113 // TODO(kbr): make this pay attention to the TDR thresholds in the
1114 // Windows registry, but make sure it continues to be testable.
1116 std::list<base::Time>::iterator iter = timestamps_of_gpu_resets_.begin();
1117 int num_resets_within_timeframe = 0;
1118 while (iter != timestamps_of_gpu_resets_.end()) {
1119 base::Time time = *iter;
1120 base::TimeDelta delta_t = at_time - time;
1122 // If this entry has "expired", just remove it.
1123 if (delta_t.InMilliseconds() > kBlockAllDomainsMs) {
1124 iter = timestamps_of_gpu_resets_.erase(iter);
1125 continue;
1128 ++num_resets_within_timeframe;
1129 ++iter;
1132 if (num_resets_within_timeframe >= kNumResetsWithinDuration) {
1133 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1134 BLOCK_STATUS_ALL_DOMAINS_BLOCKED,
1135 BLOCK_STATUS_MAX);
1137 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED;
1141 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs",
1142 BLOCK_STATUS_NOT_BLOCKED,
1143 BLOCK_STATUS_MAX);
1145 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED;
1148 int64 GpuDataManagerImplPrivate::GetBlockAllDomainsDurationInMs() const {
1149 return kBlockAllDomainsMs;
1152 void GpuDataManagerImplPrivate::Notify3DAPIBlocked(const GURL& url,
1153 int render_process_id,
1154 int render_view_id,
1155 ThreeDAPIType requester) {
1156 GpuDataManagerImpl::UnlockedSession session(owner_);
1157 observer_list_->Notify(FROM_HERE, &GpuDataManagerObserver::DidBlock3DAPIs,
1158 url, render_process_id, render_view_id, requester);
1161 void GpuDataManagerImplPrivate::OnGpuProcessInitFailure() {
1162 gpu_process_accessible_ = false;
1163 gpu_info_.context_info_state = gpu::kCollectInfoFatalFailure;
1164 #if defined(OS_WIN)
1165 gpu_info_.dx_diagnostics_info_state = gpu::kCollectInfoFatalFailure;
1166 #endif
1167 complete_gpu_info_already_requested_ = true;
1168 // Some observers might be waiting.
1169 NotifyGpuInfoUpdate();
1172 } // namespace content