| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/gpu/gpu_data_manager_impl.h" | 5 #include "content/browser/gpu/gpu_data_manager_impl.h" |
| 6 | 6 |
| 7 #if defined(OS_MACOSX) | 7 #if defined(OS_MACOSX) |
| 8 #include <ApplicationServices/ApplicationServices.h> | 8 #include <ApplicationServices/ApplicationServices.h> |
| 9 #endif // OS_MACOSX | 9 #endif // OS_MACOSX |
| 10 | 10 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 void* gpu_data_manager) { | 62 void* gpu_data_manager) { |
| 63 if (flags & kCGDisplayAddFlag) { | 63 if (flags & kCGDisplayAddFlag) { |
| 64 GpuDataManagerImpl* manager = | 64 GpuDataManagerImpl* manager = |
| 65 reinterpret_cast<GpuDataManagerImpl*>(gpu_data_manager); | 65 reinterpret_cast<GpuDataManagerImpl*>(gpu_data_manager); |
| 66 DCHECK(manager); | 66 DCHECK(manager); |
| 67 manager->HandleGpuSwitch(); | 67 manager->HandleGpuSwitch(); |
| 68 } | 68 } |
| 69 } | 69 } |
| 70 #endif // OS_MACOSX | 70 #endif // OS_MACOSX |
| 71 | 71 |
| 72 // Block all domains' use of 3D APIs for this many milliseconds if |
| 73 // approaching a threshold where system stability might be compromised. |
| 74 const int64 kBlockAllDomainsMs = 10000; |
| 75 const int kNumResetsWithinDuration = 1; |
| 76 |
| 72 } // namespace anonymous | 77 } // namespace anonymous |
| 73 | 78 |
| 74 // static | 79 // static |
| 75 GpuDataManager* GpuDataManager::GetInstance() { | 80 GpuDataManager* GpuDataManager::GetInstance() { |
| 76 return GpuDataManagerImpl::GetInstance(); | 81 return GpuDataManagerImpl::GetInstance(); |
| 77 } | 82 } |
| 78 | 83 |
| 79 // static | 84 // static |
| 80 GpuDataManagerImpl* GpuDataManagerImpl::GetInstance() { | 85 GpuDataManagerImpl* GpuDataManagerImpl::GetInstance() { |
| 81 return Singleton<GpuDataManagerImpl>::get(); | 86 return Singleton<GpuDataManagerImpl>::get(); |
| 82 } | 87 } |
| 83 | 88 |
| 84 GpuDataManagerImpl::GpuDataManagerImpl() | 89 GpuDataManagerImpl::GpuDataManagerImpl() |
| 85 : complete_gpu_info_already_requested_(false), | 90 : complete_gpu_info_already_requested_(false), |
| 86 blacklisted_features_(GPU_FEATURE_TYPE_UNKNOWN), | 91 blacklisted_features_(GPU_FEATURE_TYPE_UNKNOWN), |
| 87 preliminary_blacklisted_features_(GPU_FEATURE_TYPE_UNKNOWN), | 92 preliminary_blacklisted_features_(GPU_FEATURE_TYPE_UNKNOWN), |
| 88 gpu_switching_(GPU_SWITCHING_OPTION_AUTOMATIC), | 93 gpu_switching_(GPU_SWITCHING_OPTION_AUTOMATIC), |
| 89 observer_list_(new GpuDataManagerObserverList), | 94 observer_list_(new GpuDataManagerObserverList), |
| 90 software_rendering_(false), | 95 software_rendering_(false), |
| 91 card_blacklisted_(false), | 96 card_blacklisted_(false), |
| 92 update_histograms_(true), | 97 update_histograms_(true), |
| 93 window_count_(0) { | 98 window_count_(0), |
| 99 domain_blocking_enabled_(true) { |
| 94 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 100 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 95 if (command_line->HasSwitch(switches::kDisableAcceleratedCompositing)) { | 101 if (command_line->HasSwitch(switches::kDisableAcceleratedCompositing)) { |
| 96 command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas); | 102 command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas); |
| 97 command_line->AppendSwitch(switches::kDisableAcceleratedLayers); | 103 command_line->AppendSwitch(switches::kDisableAcceleratedLayers); |
| 98 } | 104 } |
| 99 if (command_line->HasSwitch(switches::kDisableGpu)) | 105 if (command_line->HasSwitch(switches::kDisableGpu)) |
| 100 BlacklistCard(); | 106 BlacklistCard(); |
| 101 if (command_line->HasSwitch(switches::kGpuSwitching)) { | 107 if (command_line->HasSwitch(switches::kGpuSwitching)) { |
| 102 std::string option_string = command_line->GetSwitchValueASCII( | 108 std::string option_string = command_line->GetSwitchValueASCII( |
| 103 switches::kGpuSwitching); | 109 switches::kGpuSwitching); |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, | 341 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, |
| 336 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, | 342 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, |
| 337 new GpuMsg_SetVideoMemoryWindowCount(count)); | 343 new GpuMsg_SetVideoMemoryWindowCount(count)); |
| 338 } | 344 } |
| 339 | 345 |
| 340 uint32 GpuDataManagerImpl::GetWindowCount() const { | 346 uint32 GpuDataManagerImpl::GetWindowCount() const { |
| 341 base::AutoLock auto_lock(gpu_info_lock_); | 347 base::AutoLock auto_lock(gpu_info_lock_); |
| 342 return window_count_; | 348 return window_count_; |
| 343 } | 349 } |
| 344 | 350 |
| 351 void GpuDataManagerImpl::UnblockDomainFrom3DAPIs(const GURL& url) { |
| 352 // This method must do two things: |
| 353 // |
| 354 // 1. If the specific domain is blocked, then unblock it. |
| 355 // |
| 356 // 2. Reset our notion of how many GPU resets have occurred recently. |
| 357 // This is necessary even if the specific domain was blocked. |
| 358 // Otherwise, if we call Are3DAPIsBlocked with the same domain right |
| 359 // after unblocking it, it will probably still be blocked because of |
| 360 // the recent GPU reset caused by that domain. |
| 361 // |
| 362 // These policies could be refined, but at a certain point the behavior |
| 363 // will become difficult to explain. |
| 364 std::string domain = GetDomainFromURL(url); |
| 365 |
| 366 base::AutoLock auto_lock(gpu_info_lock_); |
| 367 blocked_domains_.erase(domain); |
| 368 timestamps_of_gpu_resets_.clear(); |
| 369 } |
| 370 |
| 371 void GpuDataManagerImpl::DisableDomainBlockingFor3DAPIsForTesting() { |
| 372 domain_blocking_enabled_ = false; |
| 373 } |
| 374 |
| 345 void GpuDataManagerImpl::AppendRendererCommandLine( | 375 void GpuDataManagerImpl::AppendRendererCommandLine( |
| 346 CommandLine* command_line) const { | 376 CommandLine* command_line) const { |
| 347 DCHECK(command_line); | 377 DCHECK(command_line); |
| 348 | 378 |
| 349 uint32 flags = GetBlacklistedFeatures(); | 379 uint32 flags = GetBlacklistedFeatures(); |
| 350 if ((flags & GPU_FEATURE_TYPE_WEBGL)) { | 380 if ((flags & GPU_FEATURE_TYPE_WEBGL)) { |
| 351 #if !defined(OS_ANDROID) | 381 #if !defined(OS_ANDROID) |
| 352 if (!command_line->HasSwitch(switches::kDisableExperimentalWebGL)) | 382 if (!command_line->HasSwitch(switches::kDisableExperimentalWebGL)) |
| 353 command_line->AppendSwitch(switches::kDisableExperimentalWebGL); | 383 command_line->AppendSwitch(switches::kDisableExperimentalWebGL); |
| 354 #endif | 384 #endif |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 if (command_line->HasSwitch(switches::kDisableImageTransportSurface)) | 494 if (command_line->HasSwitch(switches::kDisableImageTransportSurface)) |
| 465 return false; | 495 return false; |
| 466 uint32 flags = GetBlacklistedFeatures(); | 496 uint32 flags = GetBlacklistedFeatures(); |
| 467 if (flags & GPU_FEATURE_TYPE_TEXTURE_SHARING) | 497 if (flags & GPU_FEATURE_TYPE_TEXTURE_SHARING) |
| 468 return false; | 498 return false; |
| 469 | 499 |
| 470 return true; | 500 return true; |
| 471 } | 501 } |
| 472 #endif | 502 #endif |
| 473 | 503 |
| 504 void GpuDataManagerImpl::BlockDomainFrom3DAPIs( |
| 505 const GURL& url, DomainGuilt guilt) { |
| 506 BlockDomainFrom3DAPIsAtTime(url, guilt, base::Time::Now()); |
| 507 } |
| 508 |
| 509 GpuDataManagerImpl::DomainBlockStatus |
| 510 GpuDataManagerImpl::Are3DAPIsBlocked(const GURL& url) const { |
| 511 return Are3DAPIsBlockedAtTime(url, base::Time::Now()); |
| 512 } |
| 513 |
| 474 void GpuDataManagerImpl::AppendPluginCommandLine( | 514 void GpuDataManagerImpl::AppendPluginCommandLine( |
| 475 CommandLine* command_line) const { | 515 CommandLine* command_line) const { |
| 476 DCHECK(command_line); | 516 DCHECK(command_line); |
| 477 | 517 |
| 478 #if defined(OS_MACOSX) | 518 #if defined(OS_MACOSX) |
| 479 uint32 flags = GetBlacklistedFeatures(); | 519 uint32 flags = GetBlacklistedFeatures(); |
| 480 // TODO(jbauman): Add proper blacklist support for core animation plugins so | 520 // TODO(jbauman): Add proper blacklist support for core animation plugins so |
| 481 // special-casing this video card won't be necessary. See | 521 // special-casing this video card won't be necessary. See |
| 482 // http://crbug.com/134015 | 522 // http://crbug.com/134015 |
| 483 if ((flags & GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) || | 523 if ((flags & GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) || |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 | 605 |
| 566 void GpuDataManagerImpl::BlacklistCard() { | 606 void GpuDataManagerImpl::BlacklistCard() { |
| 567 card_blacklisted_ = true; | 607 card_blacklisted_ = true; |
| 568 | 608 |
| 569 blacklisted_features_ = GPU_FEATURE_TYPE_ALL; | 609 blacklisted_features_ = GPU_FEATURE_TYPE_ALL; |
| 570 | 610 |
| 571 EnableSoftwareRenderingIfNecessary(); | 611 EnableSoftwareRenderingIfNecessary(); |
| 572 NotifyGpuInfoUpdate(); | 612 NotifyGpuInfoUpdate(); |
| 573 } | 613 } |
| 574 | 614 |
| 615 std::string GpuDataManagerImpl::GetDomainFromURL(const GURL& url) const { |
| 616 // For the moment, we just use the host, or its IP address, as the |
| 617 // entry in the set, rather than trying to figure out the top-level |
| 618 // domain. This does mean that a.foo.com and b.foo.com will be |
| 619 // treated independently in the blocking of a given domain, but it |
| 620 // would require a third-party library to reliably figure out the |
| 621 // top-level domain from a URL. |
| 622 if (!url.has_host()) { |
| 623 return std::string(); |
| 624 } |
| 625 |
| 626 return url.host(); |
| 627 } |
| 628 |
| 629 void GpuDataManagerImpl::BlockDomainFrom3DAPIsAtTime( |
| 630 const GURL& url, DomainGuilt guilt, base::Time at_time) { |
| 631 if (!domain_blocking_enabled_) |
| 632 return; |
| 633 |
| 634 std::string domain = GetDomainFromURL(url); |
| 635 |
| 636 base::AutoLock auto_lock(gpu_info_lock_); |
| 637 DomainBlockEntry& entry = blocked_domains_[domain]; |
| 638 entry.last_guilt = guilt; |
| 639 timestamps_of_gpu_resets_.push_back(at_time); |
| 640 } |
| 641 |
| 642 GpuDataManagerImpl::DomainBlockStatus |
| 643 GpuDataManagerImpl::Are3DAPIsBlockedAtTime( |
| 644 const GURL& url, base::Time at_time) const { |
| 645 if (!domain_blocking_enabled_) |
| 646 return DOMAIN_BLOCK_STATUS_NOT_BLOCKED; |
| 647 |
| 648 // Note: adjusting the policies in this code will almost certainly |
| 649 // require adjusting the associated unit tests. |
| 650 std::string domain = GetDomainFromURL(url); |
| 651 |
| 652 base::AutoLock auto_lock(gpu_info_lock_); |
| 653 { |
| 654 DomainBlockMap::const_iterator iter = blocked_domains_.find(domain); |
| 655 if (iter != blocked_domains_.end()) { |
| 656 // Err on the side of caution, and assume that if a particular |
| 657 // domain shows up in the block map, it's there for a good |
| 658 // reason and don't let its presence there automatically expire. |
| 659 return DOMAIN_BLOCK_STATUS_BLOCKED; |
| 660 } |
| 661 } |
| 662 |
| 663 // Look at the timestamps of the recent GPU resets to see if there are |
| 664 // enough within the threshold which would cause us to blacklist all |
| 665 // domains. This doesn't need to be overly precise -- if time goes |
| 666 // backward due to a system clock adjustment, that's fine. |
| 667 // |
| 668 // TODO(kbr): make this pay attention to the TDR thresholds in the |
| 669 // Windows registry, but make sure it continues to be testable. |
| 670 std::list<base::Time>::iterator iter = timestamps_of_gpu_resets_.begin(); |
| 671 int num_resets_within_timeframe = 0; |
| 672 while (iter != timestamps_of_gpu_resets_.end()) { |
| 673 base::Time time = *iter; |
| 674 base::TimeDelta delta_t = at_time - time; |
| 675 |
| 676 // If this entry has "expired", just remove it. |
| 677 if (delta_t.InMilliseconds() > kBlockAllDomainsMs) { |
| 678 iter = timestamps_of_gpu_resets_.erase(iter); |
| 679 continue; |
| 680 } |
| 681 |
| 682 ++num_resets_within_timeframe; |
| 683 ++iter; |
| 684 } |
| 685 |
| 686 if (num_resets_within_timeframe >= kNumResetsWithinDuration) { |
| 687 return DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED; |
| 688 } |
| 689 |
| 690 return DOMAIN_BLOCK_STATUS_NOT_BLOCKED; |
| 691 } |
| 692 |
| 693 int64 GpuDataManagerImpl::GetBlockAllDomainsDurationInMs() const { |
| 694 return kBlockAllDomainsMs; |
| 695 } |
| 696 |
| 575 } // namespace content | 697 } // namespace content |
| OLD | NEW |