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