Chromium Code Reviews| 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 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 333 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, | 339 GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, |
| 334 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, | 340 CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, |
| 335 new GpuMsg_SetVideoMemoryWindowCount(count)); | 341 new GpuMsg_SetVideoMemoryWindowCount(count)); |
| 336 } | 342 } |
| 337 | 343 |
| 338 uint32 GpuDataManagerImpl::GetWindowCount() const { | 344 uint32 GpuDataManagerImpl::GetWindowCount() const { |
| 339 base::AutoLock auto_lock(gpu_info_lock_); | 345 base::AutoLock auto_lock(gpu_info_lock_); |
| 340 return window_count_; | 346 return window_count_; |
| 341 } | 347 } |
| 342 | 348 |
| 349 void GpuDataManagerImpl::BlockDomainFrom3DAPIs( | |
| 350 const GURL& url, DomainGuilt guilt) { | |
| 351 BlockDomainFrom3DAPIsAtTime(url, guilt, base::Time::Now()); | |
| 352 } | |
| 353 | |
| 354 GpuDataManager::DomainBlockStatus | |
| 355 GpuDataManagerImpl::Are3DAPIsBlocked( | |
| 356 const GURL& url) const { | |
|
Zhenyao Mo
2012/11/14 16:35:58
nit: you don't need to put this in a new line.
Ken Russell (switch to Gerrit)
2012/11/14 19:09:13
Done.
| |
| 357 return Are3DAPIsBlockedAtTime(url, base::Time::Now()); | |
| 358 } | |
| 359 | |
| 360 void GpuDataManagerImpl::UnblockDomainFrom3DAPIs(const GURL& url) { | |
| 361 // This method must do two things: | |
| 362 // | |
| 363 // 1. If the specific domain is blocked, then unblock it. | |
| 364 // | |
| 365 // 2. Reset our notion of how many GPU resets have occurred recently. | |
| 366 // This is necessary even if the specific domain was blocked. | |
| 367 // Otherwise, if we call Are3DAPIsBlocked with the same domain right | |
| 368 // after unblocking it, it will probably still be blocked because of | |
| 369 // the recent GPU reset caused by that domain. | |
| 370 // | |
| 371 // These policies could be refined, but at a certain point the behavior | |
| 372 // will become difficult to explain. | |
| 373 std::string domain = GetDomainFromURL(url); | |
| 374 | |
| 375 base::AutoLock auto_lock(gpu_info_lock_); | |
| 376 blocked_domains_.erase(domain); | |
| 377 timestamps_of_gpu_resets_.clear(); | |
| 378 } | |
| 379 | |
| 380 void GpuDataManagerImpl::DisableDomainBlockingFor3DAPIsForTesting() { | |
| 381 domain_blocking_enabled_ = false; | |
| 382 } | |
| 383 | |
| 343 void GpuDataManagerImpl::AppendRendererCommandLine( | 384 void GpuDataManagerImpl::AppendRendererCommandLine( |
| 344 CommandLine* command_line) const { | 385 CommandLine* command_line) const { |
| 345 DCHECK(command_line); | 386 DCHECK(command_line); |
| 346 | 387 |
| 347 uint32 flags = GetBlacklistedFeatures(); | 388 uint32 flags = GetBlacklistedFeatures(); |
| 348 if ((flags & GPU_FEATURE_TYPE_WEBGL)) { | 389 if ((flags & GPU_FEATURE_TYPE_WEBGL)) { |
| 349 #if !defined(OS_ANDROID) | 390 #if !defined(OS_ANDROID) |
| 350 if (!command_line->HasSwitch(switches::kDisableExperimentalWebGL)) | 391 if (!command_line->HasSwitch(switches::kDisableExperimentalWebGL)) |
| 351 command_line->AppendSwitch(switches::kDisableExperimentalWebGL); | 392 command_line->AppendSwitch(switches::kDisableExperimentalWebGL); |
| 352 #endif | 393 #endif |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 560 | 601 |
| 561 void GpuDataManagerImpl::BlacklistCard() { | 602 void GpuDataManagerImpl::BlacklistCard() { |
| 562 card_blacklisted_ = true; | 603 card_blacklisted_ = true; |
| 563 | 604 |
| 564 blacklisted_features_ = GPU_FEATURE_TYPE_ALL; | 605 blacklisted_features_ = GPU_FEATURE_TYPE_ALL; |
| 565 | 606 |
| 566 EnableSoftwareRenderingIfNecessary(); | 607 EnableSoftwareRenderingIfNecessary(); |
| 567 NotifyGpuInfoUpdate(); | 608 NotifyGpuInfoUpdate(); |
| 568 } | 609 } |
| 569 | 610 |
| 611 std::string GpuDataManagerImpl::GetDomainFromURL(const GURL& url) const { | |
| 612 // For the moment, we just use the host, or its IP address, as the | |
| 613 // entry in the set, rather than trying to figure out the top-level | |
| 614 // domain. This does mean that a.foo.com and b.foo.com will be | |
| 615 // treated independently in the blocking of a given domain, but it | |
| 616 // would require a third-party library to reliably figure out the | |
| 617 // top-level domain from a URL. | |
| 618 if (!url.has_host()) { | |
| 619 return std::string(); | |
| 620 } | |
| 621 | |
| 622 return url.host(); | |
| 623 } | |
| 624 | |
| 625 void GpuDataManagerImpl::BlockDomainFrom3DAPIsAtTime( | |
| 626 const GURL& url, DomainGuilt guilt, base::Time at_time) { | |
| 627 if (!domain_blocking_enabled_) | |
| 628 return; | |
| 629 | |
| 630 std::string domain = GetDomainFromURL(url); | |
| 631 | |
| 632 base::AutoLock auto_lock(gpu_info_lock_); | |
| 633 DomainBlockEntry& entry = blocked_domains_[domain]; | |
| 634 entry.last_guilt = guilt; | |
| 635 timestamps_of_gpu_resets_.push_back(at_time); | |
| 636 } | |
| 637 | |
| 638 GpuDataManager::DomainBlockStatus GpuDataManagerImpl::Are3DAPIsBlockedAtTime( | |
| 639 const GURL& url, base::Time at_time) const { | |
| 640 if (!domain_blocking_enabled_) | |
| 641 return kNotBlocked; | |
| 642 | |
| 643 // Note: adjusting the policies in this code will almost certainly | |
| 644 // require adjusting the associated unit tests. | |
| 645 std::string domain = GetDomainFromURL(url); | |
| 646 | |
| 647 base::AutoLock auto_lock(gpu_info_lock_); | |
| 648 { | |
| 649 DomainBlockMap::const_iterator iter = blocked_domains_.find(domain); | |
| 650 if (iter != blocked_domains_.end()) { | |
| 651 // Err on the side of caution, and assume that if a particular | |
| 652 // domain shows up in the block map, it's there for a good | |
| 653 // reason and don't let its presence there automatically expire. | |
| 654 return kDomainBlocked; | |
| 655 } | |
| 656 } | |
| 657 | |
| 658 // Look at the timestamps of the recent GPU resets to see if there are | |
| 659 // enough within the threshold which would cause us to blacklist all | |
| 660 // domains. This doesn't need to be overly precise -- if time goes | |
| 661 // backward due to a system clock adjustment, that's fine. | |
| 662 // | |
| 663 // TODO(kbr): make this pay attention to the TDR thresholds in the | |
| 664 // Windows registry, but make sure it continues to be testable. | |
| 665 std::list<base::Time>::iterator iter = timestamps_of_gpu_resets_.begin(); | |
| 666 int num_resets_within_timeframe = 0; | |
| 667 while (iter != timestamps_of_gpu_resets_.end()) { | |
| 668 base::Time time = *iter; | |
| 669 base::TimeDelta delta_t = at_time - time; | |
| 670 | |
| 671 // If this entry has "expired", just remove it. | |
| 672 if (delta_t.InMilliseconds() > kBlockAllDomainsMs) { | |
| 673 iter = timestamps_of_gpu_resets_.erase(iter); | |
| 674 continue; | |
| 675 } | |
| 676 | |
| 677 ++num_resets_within_timeframe; | |
| 678 ++iter; | |
| 679 } | |
| 680 | |
| 681 if (num_resets_within_timeframe >= kNumResetsWithinDuration) { | |
| 682 return kAllDomainsBlocked; | |
| 683 } | |
| 684 | |
| 685 return kNotBlocked; | |
| 686 } | |
| 687 | |
| 688 int64 GpuDataManagerImpl::GetBlockAllDomainsDurationInMs() const { | |
| 689 return kBlockAllDomainsMs; | |
| 690 } | |
| 691 | |
| 570 } // namespace content | 692 } // namespace content |
| OLD | NEW |