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. 4 5 #include "content/browser/gpu/gpu_data_manager_impl_private.h" 6 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 "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_util.h" 33 #include "ui/base/ui_base_switches.h" 34 #include "ui/gl/gl_implementation.h" 35 #include "ui/gl/gl_switches.h" 36 #include "ui/gl/gpu_switching_manager.h" 37 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 47 48 namespace content { 49 50 namespace { 51 52 enum GpuFeatureStatus { 53 kGpuFeatureEnabled = 0, 54 kGpuFeatureBlacklisted = 1, 55 kGpuFeatureDisabled = 2, // disabled by user but not blacklisted 56 kGpuFeatureNumStatus 57 }; 58 59 #if defined(OS_WIN) 60 61 enum WinSubVersion { 62 kWinOthers = 0, 63 kWinXP, 64 kWinVista, 65 kWin7, 66 kWin8, 67 kNumWinSubVersions 68 }; 69 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; 89 } 90 } 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; 101 } 102 return entry_index; 103 } 104 #endif // OS_WIN 105 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; 114 } 115 116 const base::CommandLine& command_line = 117 *base::CommandLine::ForCurrentProcess(); 118 bool disabled = false; 119 120 // Use entry 0 to capture the total number of times that data 121 // was recorded in this histogram in order to have a convenient 122 // denominator to compute blacklist percentages for the rest of the 123 // entries. 124 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry", 125 0, max_entry_id + 1); 126 127 if (blacklisted_features.size() != 0) { 128 std::vector<uint32> flag_entries; 129 blacklist->GetDecisionEntries(&flag_entries, disabled); 130 DCHECK_GT(flag_entries.size(), 0u); 131 for (size_t i = 0; i < flag_entries.size(); ++i) { 132 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry", 133 flag_entries[i], max_entry_id + 1); 134 } 135 } 136 137 // This counts how many users are affected by a disabled entry - this allows 138 // us to understand the impact of an entry before enable it. 139 std::vector<uint32> flag_disabled_entries; 140 disabled = true; 141 blacklist->GetDecisionEntries(&flag_disabled_entries, disabled); 142 for (uint32 disabled_entry : flag_disabled_entries) { 143 UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerDisabledEntry", 144 disabled_entry, max_entry_id + 1); 145 } 146 147 const gpu::GpuFeatureType kGpuFeatures[] = { 148 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS, 149 gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING, gpu::GPU_FEATURE_TYPE_WEBGL}; 150 const std::string kGpuBlacklistFeatureHistogramNames[] = { 151 "GPU.BlacklistFeatureTestResults.Accelerated2dCanvas", 152 "GPU.BlacklistFeatureTestResults.GpuCompositing", 153 "GPU.BlacklistFeatureTestResults.Webgl", }; 154 const bool kGpuFeatureUserFlags[] = { 155 command_line.HasSwitch(switches::kDisableAccelerated2dCanvas), 156 command_line.HasSwitch(switches::kDisableGpu), 157 command_line.HasSwitch(switches::kDisableExperimentalWebGL), }; 158 #if defined(OS_WIN) 159 const std::string kGpuBlacklistFeatureHistogramNamesWin[] = { 160 "GPU.BlacklistFeatureTestResultsWindows.Accelerated2dCanvas", 161 "GPU.BlacklistFeatureTestResultsWindows.GpuCompositing", 162 "GPU.BlacklistFeatureTestResultsWindows.Webgl", }; 163 #endif 164 const size_t kNumFeatures = 165 sizeof(kGpuFeatures) / sizeof(gpu::GpuFeatureType); 166 for (size_t i = 0; i < kNumFeatures; ++i) { 167 // We can't use UMA_HISTOGRAM_ENUMERATION here because the same name is 168 // expected if the macro is used within a loop. 169 GpuFeatureStatus value = kGpuFeatureEnabled; 170 if (blacklisted_features.count(kGpuFeatures[i])) 171 value = kGpuFeatureBlacklisted; 172 else if (kGpuFeatureUserFlags[i]) 173 value = kGpuFeatureDisabled; 174 base::HistogramBase* histogram_pointer = base::LinearHistogram::FactoryGet( 175 kGpuBlacklistFeatureHistogramNames[i], 176 1, kGpuFeatureNumStatus, kGpuFeatureNumStatus + 1, 177 base::HistogramBase::kUmaTargetedHistogramFlag); 178 histogram_pointer->Add(value); 179 #if defined(OS_WIN) 180 histogram_pointer = base::LinearHistogram::FactoryGet( 181 kGpuBlacklistFeatureHistogramNamesWin[i], 182 1, kNumWinSubVersions * kGpuFeatureNumStatus, 183 kNumWinSubVersions * kGpuFeatureNumStatus + 1, 184 base::HistogramBase::kUmaTargetedHistogramFlag); 185 histogram_pointer->Add(GetGpuBlacklistHistogramValueWin(value)); 186 #endif 187 } 188 189 UMA_HISTOGRAM_SPARSE_SLOWLY("GPU.GLResetNotificationStrategy", 190 gpu_info.gl_reset_notification_strategy); 191 } 192 193 // Combine the integers into a string, seperated by ','. 194 std::string IntSetToString(const std::set<int>& list) { 195 std::string rt; 196 for (std::set<int>::const_iterator it = list.begin(); 197 it != list.end(); ++it) { 198 if (!rt.empty()) 199 rt += ","; 200 rt += base::IntToString(*it); 201 } 202 return rt; 203 } 204 205 #if defined(OS_MACOSX) 206 void DisplayReconfigCallback(CGDirectDisplayID display, 207 CGDisplayChangeSummaryFlags flags, 208 void* gpu_data_manager) { 209 if (flags == kCGDisplayBeginConfigurationFlag) 210 return; // This call contains no information about the display change 211 212 GpuDataManagerImpl* manager = 213 reinterpret_cast<GpuDataManagerImpl*>(gpu_data_manager); 214 DCHECK(manager); 215 216 // Display change. 217 bool display_changed = false; 218 uint32_t displayCount; 219 CGGetActiveDisplayList(0, NULL, &displayCount); 220 if (displayCount != manager->GetDisplayCount()) { 221 manager->SetDisplayCount(displayCount); 222 display_changed = true; 223 } 224 225 // Gpu change. 226 bool gpu_changed = false; 227 if (flags & kCGDisplayAddFlag) { 228 uint32 vendor_id, device_id; 229 if (gpu::CollectGpuID(&vendor_id, &device_id) == gpu::kCollectInfoSuccess) { 230 gpu_changed = manager->UpdateActiveGpu(vendor_id, device_id); 231 } 232 } 233 234 if (display_changed || gpu_changed) 235 manager->HandleGpuSwitch(); 236 } 237 #endif // OS_MACOSX 238 239 // Block all domains' use of 3D APIs for this many milliseconds if 240 // approaching a threshold where system stability might be compromised. 241 const int64 kBlockAllDomainsMs = 10000; 242 const int kNumResetsWithinDuration = 1; 243 244 // Enums for UMA histograms. 245 enum BlockStatusHistogram { 246 BLOCK_STATUS_NOT_BLOCKED, 247 BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED, 248 BLOCK_STATUS_ALL_DOMAINS_BLOCKED, 249 BLOCK_STATUS_MAX 250 }; 251 252 } // namespace anonymous 253 254 void GpuDataManagerImplPrivate::InitializeForTesting( 255 const std::string& gpu_blacklist_json, 256 const gpu::GPUInfo& gpu_info) { 257 // This function is for testing only, so disable histograms. 258 update_histograms_ = false; 259 260 // Prevent all further initialization. 261 finalized_ = true; 262 263 InitializeImpl(gpu_blacklist_json, std::string(), gpu_info); 264 } 265 266 bool GpuDataManagerImplPrivate::IsFeatureBlacklisted(int feature) const { 267 #if defined(OS_CHROMEOS) 268 if (feature == gpu::GPU_FEATURE_TYPE_PANEL_FITTING && 269 base::CommandLine::ForCurrentProcess()->HasSwitch( 270 switches::kDisablePanelFitting)) { 271 return true; 272 } 273 #endif // OS_CHROMEOS 274 if (use_swiftshader_ || ShouldUseWarp()) { 275 // Skia's software rendering is probably more efficient than going through 276 // software emulation of the GPU, so use that. 277 if (feature == gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS) 278 return true; 279 return false; 280 } 281 282 return (blacklisted_features_.count(feature) == 1); 283 } 284 285 bool GpuDataManagerImplPrivate::IsDriverBugWorkaroundActive(int feature) const { 286 return (gpu_driver_bugs_.count(feature) == 1); 287 } 288 289 size_t GpuDataManagerImplPrivate::GetBlacklistedFeatureCount() const { 290 if (use_swiftshader_ || ShouldUseWarp()) 291 return 1; 292 return blacklisted_features_.size(); 293 } 294 295 void GpuDataManagerImplPrivate::SetDisplayCount(unsigned int display_count) { 296 display_count_ = display_count; 297 } 298 299 unsigned int GpuDataManagerImplPrivate::GetDisplayCount() const { 300 return display_count_; 301 } 302 303 gpu::GPUInfo GpuDataManagerImplPrivate::GetGPUInfo() const { 304 return gpu_info_; 305 } 306 307 void GpuDataManagerImplPrivate::GetGpuProcessHandles( 308 const GpuDataManager::GetGpuProcessHandlesCallback& callback) const { 309 GpuProcessHost::GetProcessHandles(callback); 310 } 311 312 bool GpuDataManagerImplPrivate::GpuAccessAllowed( 313 std::string* reason) const { 314 if (use_swiftshader_ || ShouldUseWarp()) 315 return true; 316 317 if (!gpu_process_accessible_) { 318 if (reason) { 319 *reason = "GPU process launch failed."; 320 } 321 return false; 322 } 323 324 if (card_blacklisted_) { 325 if (reason) { 326 *reason = "GPU access is disabled "; 327 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 328 if (command_line->HasSwitch(switches::kDisableGpu)) 329 *reason += "through commandline switch --disable-gpu."; 330 else 331 *reason += "in chrome://settings."; 332 } 333 return false; 334 } 335 336 // We only need to block GPU process if more features are disallowed other 337 // than those in the preliminary gpu feature flags because the latter work 338 // through renderer commandline switches. 339 std::set<int> features = preliminary_blacklisted_features_; 340 gpu::MergeFeatureSets(&features, blacklisted_features_); 341 if (features.size() > preliminary_blacklisted_features_.size()) { 342 if (reason) { 343 *reason = "Features are disabled upon full but not preliminary GPU info."; 344 } 345 return false; 346 } 347 348 if (blacklisted_features_.size() == gpu::NUMBER_OF_GPU_FEATURE_TYPES) { 349 // On Linux, we use cached GL strings to make blacklist decsions at browser 350 // startup time. We need to launch the GPU process to validate these 351 // strings even if all features are blacklisted. If all GPU features are 352 // disabled, the GPU process will only initialize GL bindings, create a GL 353 // context, and collect full GPU info. 354 #if !defined(OS_LINUX) 355 if (reason) { 356 *reason = "All GPU features are blacklisted."; 357 } 358 return false; 359 #endif 360 } 361 362 return true; 363 } 364 365 void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() { 366 if (complete_gpu_info_already_requested_ || IsCompleteGpuInfoAvailable()) 367 return; 368 complete_gpu_info_already_requested_ = true; 369 370 GpuProcessHost::SendOnIO( 371 #if defined(OS_WIN) 372 GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED, 373 #else 374 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, 375 #endif 376 CAUSE_FOR_GPU_LAUNCH_GPUDATAMANAGER_REQUESTCOMPLETEGPUINFOIFNEEDED, 377 new GpuMsg_CollectGraphicsInfo()); 378 } 379 380 bool GpuDataManagerImplPrivate::IsEssentialGpuInfoAvailable() const { 381 if (gpu_info_.basic_info_state == gpu::kCollectInfoNone || 382 gpu_info_.context_info_state == gpu::kCollectInfoNone) { 383 return false; 384 } 385 return true; 386 } 387 388 bool GpuDataManagerImplPrivate::IsCompleteGpuInfoAvailable() const { 389 #if defined(OS_WIN) 390 if (gpu_info_.dx_diagnostics_info_state == gpu::kCollectInfoNone) 391 return false; 392 #endif 393 return IsEssentialGpuInfoAvailable(); 394 } 395 396 void GpuDataManagerImplPrivate::RequestVideoMemoryUsageStatsUpdate() const { 397 GpuProcessHost::SendOnIO( 398 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, 399 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, 400 new GpuMsg_GetVideoMemoryUsageStats()); 401 } 402 403 bool GpuDataManagerImplPrivate::ShouldUseSwiftShader() const { 404 return use_swiftshader_; 405 } 406 407 void GpuDataManagerImplPrivate::RegisterSwiftShaderPath( 408 const base::FilePath& path) { 409 swiftshader_path_ = path; 410 EnableSwiftShaderIfNecessary(); 411 } 412 413 bool GpuDataManagerImplPrivate::ShouldUseWarp() const { 414 return use_warp_ || 415 CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseWarp); 416 } 417 418 void GpuDataManagerImplPrivate::AddObserver(GpuDataManagerObserver* observer) { 419 GpuDataManagerImpl::UnlockedSession session(owner_); 420 observer_list_->AddObserver(observer); 421 } 422 423 void GpuDataManagerImplPrivate::RemoveObserver( 424 GpuDataManagerObserver* observer) { 425 GpuDataManagerImpl::UnlockedSession session(owner_); 426 observer_list_->RemoveObserver(observer); 427 } 428 429 void GpuDataManagerImplPrivate::UnblockDomainFrom3DAPIs(const GURL& url) { 430 // This method must do two things: 431 // 432 // 1. If the specific domain is blocked, then unblock it. 433 // 434 // 2. Reset our notion of how many GPU resets have occurred recently. 435 // This is necessary even if the specific domain was blocked. 436 // Otherwise, if we call Are3DAPIsBlocked with the same domain right 437 // after unblocking it, it will probably still be blocked because of 438 // the recent GPU reset caused by that domain. 439 // 440 // These policies could be refined, but at a certain point the behavior 441 // will become difficult to explain. 442 std::string domain = GetDomainFromURL(url); 443 444 blocked_domains_.erase(domain); 445 timestamps_of_gpu_resets_.clear(); 446 } 447 448 void GpuDataManagerImplPrivate::DisableGpuWatchdog() { 449 GpuProcessHost::SendOnIO( 450 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, 451 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, 452 new GpuMsg_DisableWatchdog); 453 } 454 455 void GpuDataManagerImplPrivate::SetGLStrings(const std::string& gl_vendor, 456 const std::string& gl_renderer, 457 const std::string& gl_version) { 458 if (gl_vendor.empty() && gl_renderer.empty() && gl_version.empty()) 459 return; 460 461 // If GPUInfo already got GL strings, do nothing. This is for the rare 462 // situation where GPU process collected GL strings before this call. 463 if (!gpu_info_.gl_vendor.empty() || 464 !gpu_info_.gl_renderer.empty() || 465 !gpu_info_.gl_version.empty()) 466 return; 467 468 gpu::GPUInfo gpu_info = gpu_info_; 469 470 gpu_info.gl_vendor = gl_vendor; 471 gpu_info.gl_renderer = gl_renderer; 472 gpu_info.gl_version = gl_version; 473 474 gpu::CollectDriverInfoGL(&gpu_info); 475 476 UpdateGpuInfo(gpu_info); 477 UpdateGpuSwitchingManager(gpu_info); 478 UpdatePreliminaryBlacklistedFeatures(); 479 } 480 481 void GpuDataManagerImplPrivate::GetGLStrings(std::string* gl_vendor, 482 std::string* gl_renderer, 483 std::string* gl_version) { 484 DCHECK(gl_vendor && gl_renderer && gl_version); 485 486 *gl_vendor = gpu_info_.gl_vendor; 487 *gl_renderer = gpu_info_.gl_renderer; 488 *gl_version = gpu_info_.gl_version; 489 } 490 491 void GpuDataManagerImplPrivate::Initialize() { 492 TRACE_EVENT0("startup", "GpuDataManagerImpl::Initialize"); 493 if (finalized_) { 494 DVLOG(0) << "GpuDataManagerImpl marked as finalized; skipping Initialize"; 495 return; 496 } 497 498 const base::CommandLine* command_line = 499 base::CommandLine::ForCurrentProcess(); 500 if (command_line->HasSwitch(switches::kSkipGpuDataLoading)) 501 return; 502 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; 513 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); 521 } 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 528 } 529 #endif // ARCH_CPU_X86_FAMILY 530 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; 536 } 537 if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) { 538 gpu_driver_bug_list_string = gpu::kGpuDriverBugListJson; 539 } 540 InitializeImpl(gpu_blacklist_string, 541 gpu_driver_bug_list_string, 542 gpu_info); 543 } 544 545 void GpuDataManagerImplPrivate::UpdateGpuInfoHelper() { 546 GetContentClient()->SetGpuInfo(gpu_info_); 547 548 if (gpu_blacklist_) { 549 std::set<int> features = gpu_blacklist_->MakeDecision( 550 gpu::GpuControlList::kOsAny, std::string(), gpu_info_); 551 if (update_histograms_) 552 UpdateStats(gpu_info_, gpu_blacklist_.get(), features); 553 554 UpdateBlacklistedFeatures(features); 555 } 556 if (gpu_driver_bug_list_) { 557 gpu_driver_bugs_ = gpu_driver_bug_list_->MakeDecision( 558 gpu::GpuControlList::kOsAny, std::string(), gpu_info_); 559 } 560 gpu::GpuDriverBugList::AppendWorkaroundsFromCommandLine( 561 &gpu_driver_bugs_, *base::CommandLine::ForCurrentProcess()); 562 563 // We have to update GpuFeatureType before notify all the observers. 564 NotifyGpuInfoUpdate(); 565 } 566 567 void GpuDataManagerImplPrivate::UpdateGpuInfo(const gpu::GPUInfo& gpu_info) { 568 // No further update of gpu_info if falling back to SwiftShader. 569 if (use_swiftshader_ || ShouldUseWarp()) 570 return; 571 572 gpu::MergeGPUInfo(&gpu_info_, gpu_info); 573 if (IsCompleteGpuInfoAvailable()) 574 complete_gpu_info_already_requested_ = true; 575 576 UpdateGpuInfoHelper(); 577 } 578 579 void GpuDataManagerImplPrivate::UpdateVideoMemoryUsageStats( 580 const GPUVideoMemoryUsageStats& video_memory_usage_stats) { 581 GpuDataManagerImpl::UnlockedSession session(owner_); 582 observer_list_->Notify(&GpuDataManagerObserver::OnVideoMemoryUsageStatsUpdate, 583 video_memory_usage_stats); 584 } 585 586 void GpuDataManagerImplPrivate::AppendRendererCommandLine( 587 base::CommandLine* command_line) const { 588 DCHECK(command_line); 589 590 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) && 591 !command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) 592 command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode); 593 #if defined(ENABLE_WEBRTC) 594 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE) && 595 !command_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) 596 command_line->AppendSwitch(switches::kDisableWebRtcHWEncoding); 597 #endif 598 599 #if defined(USE_AURA) 600 if (!CanUseGpuBrowserCompositor()) 601 command_line->AppendSwitch(switches::kDisableGpuCompositing); 602 #endif 603 } 604 605 void GpuDataManagerImplPrivate::AppendGpuCommandLine( 606 base::CommandLine* command_line) const { 607 DCHECK(command_line); 608 609 std::string use_gl = 610 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 611 switches::kUseGL); 612 base::FilePath swiftshader_path = 613 base::CommandLine::ForCurrentProcess()->GetSwitchValuePath( 614 switches::kSwiftShaderPath); 615 if (gpu_driver_bugs_.find(gpu::DISABLE_D3D11) != gpu_driver_bugs_.end()) 616 command_line->AppendSwitch(switches::kDisableD3D11); 617 if (use_swiftshader_) { 618 command_line->AppendSwitchASCII(switches::kUseGL, "swiftshader"); 619 if (swiftshader_path.empty()) 620 swiftshader_path = swiftshader_path_; 621 } else if ((IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL) || 622 IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING) || 623 IsFeatureBlacklisted( 624 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)) && 625 (use_gl == "any")) { 626 command_line->AppendSwitchASCII( 627 switches::kUseGL, gfx::kGLImplementationOSMesaName); 628 } else if (!use_gl.empty()) { 629 command_line->AppendSwitchASCII(switches::kUseGL, use_gl); 630 } 631 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) 632 command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "true"); 633 else 634 command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "false"); 635 636 if (!swiftshader_path.empty()) { 637 command_line->AppendSwitchPath(switches::kSwiftShaderPath, 638 swiftshader_path); 639 } 640 641 if (!gpu_driver_bugs_.empty()) { 642 command_line->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds, 643 IntSetToString(gpu_driver_bugs_)); 644 } 645 646 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) && 647 !command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) { 648 command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode); 649 } 650 #if defined(ENABLE_WEBRTC) 651 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE) && 652 !command_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) { 653 command_line->AppendSwitch(switches::kDisableWebRtcHWEncoding); 654 } 655 #endif 656 657 // Pass GPU and driver information to GPU process. We try to avoid full GPU 658 // info collection at GPU process startup, but we need gpu vendor_id, 659 // device_id, driver_vendor, driver_version for deciding whether we need to 660 // collect full info (on Linux) and for crash reporting purpose. 661 command_line->AppendSwitchASCII(switches::kGpuVendorID, 662 base::StringPrintf("0x%04x", gpu_info_.gpu.vendor_id)); 663 command_line->AppendSwitchASCII(switches::kGpuDeviceID, 664 base::StringPrintf("0x%04x", gpu_info_.gpu.device_id)); 665 command_line->AppendSwitchASCII(switches::kGpuDriverVendor, 666 gpu_info_.driver_vendor); 667 command_line->AppendSwitchASCII(switches::kGpuDriverVersion, 668 gpu_info_.driver_version); 669 670 if (ShouldUseWarp()) 671 command_line->AppendSwitch(switches::kUseWarp); 672 } 673 674 void GpuDataManagerImplPrivate::AppendPluginCommandLine( 675 base::CommandLine* command_line) const { 676 DCHECK(command_line); 677 678 #if defined(OS_MACOSX) 679 // TODO(jbauman): Add proper blacklist support for core animation plugins so 680 // special-casing this video card won't be necessary. See 681 // http://crbug.com/134015 682 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING)) { 683 if (!command_line->HasSwitch( 684 switches::kDisableCoreAnimationPlugins)) 685 command_line->AppendSwitch( 686 switches::kDisableCoreAnimationPlugins); 687 } 688 #endif 689 } 690 691 void GpuDataManagerImplPrivate::UpdateRendererWebPrefs( 692 WebPreferences* prefs) const { 693 DCHECK(prefs); 694 695 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL)) { 696 prefs->experimental_webgl_enabled = false; 697 prefs->pepper_3d_enabled = false; 698 } 699 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH3D)) 700 prefs->flash_3d_enabled = false; 701 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D)) { 702 prefs->flash_stage3d_enabled = false; 703 prefs->flash_stage3d_baseline_enabled = false; 704 } 705 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE)) 706 prefs->flash_stage3d_baseline_enabled = false; 707 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)) 708 prefs->accelerated_2d_canvas_enabled = false; 709 if (IsDriverBugWorkaroundActive(gpu::DISABLE_MULTISAMPLING) || 710 (IsDriverBugWorkaroundActive(gpu::DISABLE_MULTIMONITOR_MULTISAMPLING) && 711 display_count_ > 1)) 712 prefs->gl_multisampling_enabled = false; 713 714 #if defined(USE_AURA) 715 if (!CanUseGpuBrowserCompositor()) { 716 prefs->accelerated_2d_canvas_enabled = false; 717 prefs->pepper_3d_enabled = false; 718 } 719 #endif 720 721 if (!IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) && 722 !base::CommandLine::ForCurrentProcess()->HasSwitch( 723 switches::kDisableAcceleratedVideoDecode)) { 724 prefs->pepper_accelerated_video_decode_enabled = true; 725 } 726 } 727 728 void GpuDataManagerImplPrivate::DisableHardwareAcceleration() { 729 card_blacklisted_ = true; 730 731 for (int i = 0; i < gpu::NUMBER_OF_GPU_FEATURE_TYPES; ++i) 732 blacklisted_features_.insert(i); 733 734 EnableWarpIfNecessary(); 735 EnableSwiftShaderIfNecessary(); 736 NotifyGpuInfoUpdate(); 737 } 738 739 std::string GpuDataManagerImplPrivate::GetBlacklistVersion() const { 740 if (gpu_blacklist_) 741 return gpu_blacklist_->version(); 742 return "0"; 743 } 744 745 std::string GpuDataManagerImplPrivate::GetDriverBugListVersion() const { 746 if (gpu_driver_bug_list_) 747 return gpu_driver_bug_list_->version(); 748 return "0"; 749 } 750 751 void GpuDataManagerImplPrivate::GetBlacklistReasons( 752 base::ListValue* reasons) const { 753 if (gpu_blacklist_) 754 gpu_blacklist_->GetReasons(reasons, "disabledFeatures"); 755 if (gpu_driver_bug_list_) 756 gpu_driver_bug_list_->GetReasons(reasons, "workarounds"); 757 } 758 759 void GpuDataManagerImplPrivate::GetDriverBugWorkarounds( 760 base::ListValue* workarounds) const { 761 for (std::set<int>::const_iterator it = gpu_driver_bugs_.begin(); 762 it != gpu_driver_bugs_.end(); ++it) { 763 workarounds->AppendString( 764 gpu::GpuDriverBugWorkaroundTypeToString( 765 static_cast<gpu::GpuDriverBugWorkaroundType>(*it))); 766 } 767 } 768 769 void GpuDataManagerImplPrivate::AddLogMessage( 770 int level, const std::string& header, const std::string& message) { 771 log_messages_.push_back(LogMessage(level, header, message)); 772 } 773 774 void GpuDataManagerImplPrivate::ProcessCrashed( 775 base::TerminationStatus exit_code) { 776 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 777 // Unretained is ok, because it's posted to UI thread, the thread 778 // where the singleton GpuDataManagerImpl lives until the end. 779 BrowserThread::PostTask( 780 BrowserThread::UI, 781 FROM_HERE, 782 base::Bind(&GpuDataManagerImpl::ProcessCrashed, 783 base::Unretained(owner_), 784 exit_code)); 785 return; 786 } 787 { 788 gpu_info_.process_crash_count = GpuProcessHost::gpu_crash_count(); 789 GpuDataManagerImpl::UnlockedSession session(owner_); 790 observer_list_->Notify( 791 &GpuDataManagerObserver::OnGpuProcessCrashed, exit_code); 792 } 793 } 794 795 base::ListValue* GpuDataManagerImplPrivate::GetLogMessages() const { 796 base::ListValue* value = new base::ListValue; 797 for (size_t ii = 0; ii < log_messages_.size(); ++ii) { 798 base::DictionaryValue* dict = new base::DictionaryValue(); 799 dict->SetInteger("level", log_messages_[ii].level); 800 dict->SetString("header", log_messages_[ii].header); 801 dict->SetString("message", log_messages_[ii].message); 802 value->Append(dict); 803 } 804 return value; 805 } 806 807 void GpuDataManagerImplPrivate::HandleGpuSwitch() { 808 GpuDataManagerImpl::UnlockedSession session(owner_); 809 observer_list_->Notify(&GpuDataManagerObserver::OnGpuSwitching); 810 } 811 812 bool GpuDataManagerImplPrivate::UpdateActiveGpu( 813 uint32 vendor_id, uint32 device_id) { 814 if (gpu_info_.gpu.vendor_id == vendor_id && 815 gpu_info_.gpu.device_id == device_id) { 816 // The primary GPU is active. 817 if (gpu_info_.gpu.active) 818 return false; 819 gpu_info_.gpu.active = true; 820 for (size_t ii = 0; ii < gpu_info_.secondary_gpus.size(); ++ii) 821 gpu_info_.secondary_gpus[ii].active = false; 822 } else { 823 // A secondary GPU is active. 824 for (size_t ii = 0; ii < gpu_info_.secondary_gpus.size(); ++ii) { 825 if (gpu_info_.secondary_gpus[ii].vendor_id == vendor_id && 826 gpu_info_.secondary_gpus[ii].device_id == device_id) { 827 if (gpu_info_.secondary_gpus[ii].active) 828 return false; 829 gpu_info_.secondary_gpus[ii].active = true; 830 } else { 831 gpu_info_.secondary_gpus[ii].active = false; 832 } 833 } 834 gpu_info_.gpu.active = false; 835 } 836 UpdateGpuInfoHelper(); 837 return true; 838 } 839 840 bool GpuDataManagerImplPrivate::CanUseGpuBrowserCompositor() const { 841 if (CommandLine::ForCurrentProcess()->HasSwitch( 842 switches::kDisableGpuCompositing)) 843 return false; 844 if (ShouldUseWarp()) 845 return true; 846 if (ShouldUseSwiftShader()) 847 return false; 848 if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING)) 849 return false; 850 return true; 851 } 852 853 void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIs( 854 const GURL& url, GpuDataManagerImpl::DomainGuilt guilt) { 855 BlockDomainFrom3DAPIsAtTime(url, guilt, base::Time::Now()); 856 } 857 858 bool GpuDataManagerImplPrivate::Are3DAPIsBlocked(const GURL& url, 859 int render_process_id, 860 int render_view_id, 861 ThreeDAPIType requester) { 862 bool blocked = Are3DAPIsBlockedAtTime(url, base::Time::Now()) != 863 GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED; 864 if (blocked) { 865 // Unretained is ok, because it's posted to UI thread, the thread 866 // where the singleton GpuDataManagerImpl lives until the end. 867 BrowserThread::PostTask( 868 BrowserThread::UI, FROM_HERE, 869 base::Bind(&GpuDataManagerImpl::Notify3DAPIBlocked, 870 base::Unretained(owner_), url, render_process_id, 871 render_view_id, requester)); 872 } 873 874 return blocked; 875 } 876 877 void GpuDataManagerImplPrivate::DisableDomainBlockingFor3DAPIsForTesting() { 878 domain_blocking_enabled_ = false; 879 } 880 881 // static 882 GpuDataManagerImplPrivate* GpuDataManagerImplPrivate::Create( 883 GpuDataManagerImpl* owner) { 884 return new GpuDataManagerImplPrivate(owner); 885 } 886 887 GpuDataManagerImplPrivate::GpuDataManagerImplPrivate( 888 GpuDataManagerImpl* owner) 889 : complete_gpu_info_already_requested_(false), 890 observer_list_(new GpuDataManagerObserverList), 891 use_swiftshader_(false), 892 use_warp_(false), 893 card_blacklisted_(false), 894 update_histograms_(true), 895 window_count_(0), 896 domain_blocking_enabled_(true), 897 owner_(owner), 898 display_count_(0), 899 gpu_process_accessible_(true), 900 finalized_(false) { 901 DCHECK(owner_); 902 const base::CommandLine* command_line = 903 base::CommandLine::ForCurrentProcess(); 904 if (command_line->HasSwitch(switches::kDisableGpu)) 905 DisableHardwareAcceleration(); 906 907 #if defined(OS_MACOSX) 908 CGGetActiveDisplayList (0, NULL, &display_count_); 909 CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback, owner_); 910 #endif // OS_MACOSX 911 912 // For testing only. 913 if (command_line->HasSwitch(switches::kDisableDomainBlockingFor3DAPIs)) { 914 domain_blocking_enabled_ = false; 915 } 916 } 917 918 GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() { 919 #if defined(OS_MACOSX) 920 CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback, owner_); 921 #endif 922 } 923 924 void GpuDataManagerImplPrivate::InitializeImpl( 925 const std::string& gpu_blacklist_json, 926 const std::string& gpu_driver_bug_list_json, 927 const gpu::GPUInfo& gpu_info) { 928 const bool log_gpu_control_list_decisions = 929 base::CommandLine::ForCurrentProcess()->HasSwitch( 930 switches::kLogGpuControlListDecisions); 931 932 if (!gpu_blacklist_json.empty()) { 933 gpu_blacklist_.reset(gpu::GpuBlacklist::Create()); 934 if (log_gpu_control_list_decisions) 935 gpu_blacklist_->enable_control_list_logging("gpu_blacklist"); 936 bool success = gpu_blacklist_->LoadList( 937 gpu_blacklist_json, gpu::GpuControlList::kCurrentOsOnly); 938 DCHECK(success); 939 } 940 if (!gpu_driver_bug_list_json.empty()) { 941 gpu_driver_bug_list_.reset(gpu::GpuDriverBugList::Create()); 942 if (log_gpu_control_list_decisions) 943 gpu_driver_bug_list_->enable_control_list_logging("gpu_driver_bug_list"); 944 bool success = gpu_driver_bug_list_->LoadList( 945 gpu_driver_bug_list_json, gpu::GpuControlList::kCurrentOsOnly); 946 DCHECK(success); 947 } 948 949 gpu_info_ = gpu_info; 950 UpdateGpuInfo(gpu_info); 951 UpdateGpuSwitchingManager(gpu_info); 952 UpdatePreliminaryBlacklistedFeatures(); 953 } 954 955 void GpuDataManagerImplPrivate::UpdateBlacklistedFeatures( 956 const std::set<int>& features) { 957 blacklisted_features_ = features; 958 959 // Force disable using the GPU for these features, even if they would 960 // otherwise be allowed. 961 if (card_blacklisted_) { 962 blacklisted_features_.insert(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING); 963 blacklisted_features_.insert(gpu::GPU_FEATURE_TYPE_WEBGL); 964 } 965 966 EnableWarpIfNecessary(); 967 EnableSwiftShaderIfNecessary(); 968 } 969 970 void GpuDataManagerImplPrivate::UpdatePreliminaryBlacklistedFeatures() { 971 preliminary_blacklisted_features_ = blacklisted_features_; 972 } 973 974 void GpuDataManagerImplPrivate::UpdateGpuSwitchingManager( 975 const gpu::GPUInfo& gpu_info) { 976 ui::GpuSwitchingManager::GetInstance()->SetGpuCount( 977 gpu_info.secondary_gpus.size() + 1); 978 979 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) { 980 if (gpu_driver_bugs_.count(gpu::FORCE_DISCRETE_GPU) == 1) 981 ui::GpuSwitchingManager::GetInstance()->ForceUseOfDiscreteGpu(); 982 else if (gpu_driver_bugs_.count(gpu::FORCE_INTEGRATED_GPU) == 1) 983 ui::GpuSwitchingManager::GetInstance()->ForceUseOfIntegratedGpu(); 984 } 985 } 986 987 void GpuDataManagerImplPrivate::NotifyGpuInfoUpdate() { 988 observer_list_->Notify(&GpuDataManagerObserver::OnGpuInfoUpdate); 989 } 990 991 void GpuDataManagerImplPrivate::EnableSwiftShaderIfNecessary() { 992 if (ShouldUseWarp()) 993 return; 994 995 if (!GpuAccessAllowed(NULL) || 996 blacklisted_features_.count(gpu::GPU_FEATURE_TYPE_WEBGL)) { 997 if (!swiftshader_path_.empty() && 998 !base::CommandLine::ForCurrentProcess()->HasSwitch( 999 switches::kDisableSoftwareRasterizer)) 1000 use_swiftshader_ = true; 1001 } 1002 } 1003 1004 void GpuDataManagerImplPrivate::EnableWarpIfNecessary() { 1005 #if defined(OS_WIN) 1006 if (use_warp_) 1007 return; 1008 // We should only use WARP if we are unable to use the regular GPU for 1009 // compositing, and if we in Metro mode. 1010 use_warp_ = 1011 CommandLine::ForCurrentProcess()->HasSwitch(switches::kViewerConnect) && 1012 !CanUseGpuBrowserCompositor(); 1013 #endif 1014 } 1015 1016 void GpuDataManagerImplPrivate::ForceWarpModeForTesting() { 1017 use_warp_ = true; 1018 } 1019 1020 std::string GpuDataManagerImplPrivate::GetDomainFromURL( 1021 const GURL& url) const { 1022 // For the moment, we just use the host, or its IP address, as the 1023 // entry in the set, rather than trying to figure out the top-level 1024 // domain. This does mean that a.foo.com and b.foo.com will be 1025 // treated independently in the blocking of a given domain, but it 1026 // would require a third-party library to reliably figure out the 1027 // top-level domain from a URL. 1028 if (!url.has_host()) { 1029 return std::string(); 1030 } 1031 1032 return url.host(); 1033 } 1034 1035 void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIsAtTime( 1036 const GURL& url, 1037 GpuDataManagerImpl::DomainGuilt guilt, 1038 base::Time at_time) { 1039 if (!domain_blocking_enabled_) 1040 return; 1041 1042 std::string domain = GetDomainFromURL(url); 1043 1044 DomainBlockEntry& entry = blocked_domains_[domain]; 1045 entry.last_guilt = guilt; 1046 timestamps_of_gpu_resets_.push_back(at_time); 1047 } 1048 1049 GpuDataManagerImpl::DomainBlockStatus 1050 GpuDataManagerImplPrivate::Are3DAPIsBlockedAtTime( 1051 const GURL& url, base::Time at_time) const { 1052 if (!domain_blocking_enabled_) 1053 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED; 1054 1055 // Note: adjusting the policies in this code will almost certainly 1056 // require adjusting the associated unit tests. 1057 std::string domain = GetDomainFromURL(url); 1058 1059 DomainBlockMap::const_iterator iter = blocked_domains_.find(domain); 1060 if (iter != blocked_domains_.end()) { 1061 // Err on the side of caution, and assume that if a particular 1062 // domain shows up in the block map, it's there for a good 1063 // reason and don't let its presence there automatically expire. 1064 1065 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs", 1066 BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED, 1067 BLOCK_STATUS_MAX); 1068 1069 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED; 1070 } 1071 1072 // Look at the timestamps of the recent GPU resets to see if there are 1073 // enough within the threshold which would cause us to blacklist all 1074 // domains. This doesn't need to be overly precise -- if time goes 1075 // backward due to a system clock adjustment, that's fine. 1076 // 1077 // TODO(kbr): make this pay attention to the TDR thresholds in the 1078 // Windows registry, but make sure it continues to be testable. 1079 { 1080 std::list<base::Time>::iterator iter = timestamps_of_gpu_resets_.begin(); 1081 int num_resets_within_timeframe = 0; 1082 while (iter != timestamps_of_gpu_resets_.end()) { 1083 base::Time time = *iter; 1084 base::TimeDelta delta_t = at_time - time; 1085 1086 // If this entry has "expired", just remove it. 1087 if (delta_t.InMilliseconds() > kBlockAllDomainsMs) { 1088 iter = timestamps_of_gpu_resets_.erase(iter); 1089 continue; 1090 } 1091 1092 ++num_resets_within_timeframe; 1093 ++iter; 1094 } 1095 1096 if (num_resets_within_timeframe >= kNumResetsWithinDuration) { 1097 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs", 1098 BLOCK_STATUS_ALL_DOMAINS_BLOCKED, 1099 BLOCK_STATUS_MAX); 1100 1101 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED; 1102 } 1103 } 1104 1105 UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs", 1106 BLOCK_STATUS_NOT_BLOCKED, 1107 BLOCK_STATUS_MAX); 1108 1109 return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED; 1110 } 1111 1112 int64 GpuDataManagerImplPrivate::GetBlockAllDomainsDurationInMs() const { 1113 return kBlockAllDomainsMs; 1114 } 1115 1116 void GpuDataManagerImplPrivate::Notify3DAPIBlocked(const GURL& url, 1117 int render_process_id, 1118 int render_view_id, 1119 ThreeDAPIType requester) { 1120 GpuDataManagerImpl::UnlockedSession session(owner_); 1121 observer_list_->Notify(&GpuDataManagerObserver::DidBlock3DAPIs, 1122 url, render_process_id, render_view_id, requester); 1123 } 1124 1125 void GpuDataManagerImplPrivate::OnGpuProcessInitFailure() { 1126 gpu_process_accessible_ = false; 1127 gpu_info_.context_info_state = gpu::kCollectInfoFatalFailure; 1128 #if defined(OS_WIN) 1129 gpu_info_.dx_diagnostics_info_state = gpu::kCollectInfoFatalFailure; 1130 #endif 1131 complete_gpu_info_already_requested_ = true; 1132 // Some observers might be waiting. 1133 NotifyGpuInfoUpdate(); 1134 } 1135 1136 } // namespace content 1137