diff options
author | zea@chromium.org <zea@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-14 22:30:23 +0000 |
---|---|---|
committer | zea@chromium.org <zea@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-14 22:30:23 +0000 |
commit | dd5c84f39e4855d94faea8ad6b353bcf16ef4515 (patch) | |
tree | 2c3cb6a089f1b0b90329bdb08c1a1f5445b2ab8a | |
parent | 3de7a5ddcea8b3948d8f28d87c07666390ff02d7 (diff) | |
download | chromium_src-dd5c84f39e4855d94faea8ad6b353bcf16ef4515.zip chromium_src-dd5c84f39e4855d94faea8ad6b353bcf16ef4515.tar.gz chromium_src-dd5c84f39e4855d94faea8ad6b353bcf16ef4515.tar.bz2 |
Revert "Refactor GpuDataManagerImpl to make it thread-safe."
Breaks compile on Linux ChromiumOS Builder
http://build.chromium.org/p/chromium.chromiumos/builders/Linux%20ChromiumOS%20Builder/builds/42709/steps/compile/logs/stdio#error1
TBR=zmo@google.com
BUG=232556
Review URL: https://codereview.chromium.org/15175004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@200087 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | content/browser/gpu/gpu_data_manager_impl.cc | 919 | ||||
-rw-r--r-- | content/browser/gpu/gpu_data_manager_impl.h | 165 | ||||
-rw-r--r-- | content/browser/gpu/gpu_data_manager_impl_private.cc | 925 | ||||
-rw-r--r-- | content/browser/gpu/gpu_data_manager_impl_private.h | 239 | ||||
-rw-r--r-- | content/browser/gpu/gpu_data_manager_impl_unittest.cc (renamed from content/browser/gpu/gpu_data_manager_impl_private_unittest.cc) | 190 | ||||
-rw-r--r-- | content/browser/gpu/gpu_internals_ui.cc | 19 | ||||
-rw-r--r-- | content/content_browser.gypi | 2 | ||||
-rw-r--r-- | content/content_tests.gypi | 2 | ||||
-rw-r--r-- | content/public/browser/gpu_data_manager_observer.h | 3 |
9 files changed, 1050 insertions, 1414 deletions
diff --git a/content/browser/gpu/gpu_data_manager_impl.cc b/content/browser/gpu/gpu_data_manager_impl.cc index f53094e..89aa36b 100644 --- a/content/browser/gpu/gpu_data_manager_impl.cc +++ b/content/browser/gpu/gpu_data_manager_impl.cc @@ -1,12 +1,105 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "content/browser/gpu/gpu_data_manager_impl.h" -#include "content/browser/gpu/gpu_data_manager_impl_private.h" +#if defined(OS_MACOSX) +#include <ApplicationServices/ApplicationServices.h> +#endif // OS_MACOSX + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/command_line.h" +#include "base/debug/trace_event.h" +#include "base/metrics/field_trial.h" +#include "base/metrics/histogram.h" +#include "base/stringprintf.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_piece.h" +#include "base/sys_info.h" +#include "base/values.h" +#include "base/version.h" +#include "content/browser/gpu/gpu_process_host.h" +#include "content/browser/gpu/gpu_util.h" +#include "content/common/gpu/gpu_messages.h" +#include "content/gpu/gpu_info_collector.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/gpu_data_manager_observer.h" +#include "content/public/common/content_client.h" +#include "content/public/common/content_constants.h" +#include "content/public/common/content_switches.h" +#include "content/public/common/gpu_feature_type.h" +#include "gpu/command_buffer/service/gpu_switches.h" +#include "grit/content_resources.h" +#include "ui/base/ui_base_switches.h" +#include "ui/gl/gl_implementation.h" +#include "ui/gl/gl_switches.h" +#include "ui/gl/gpu_switching_manager.h" +#include "webkit/glue/webpreferences.h" +#include "webkit/plugins/plugin_switches.h" + +#if defined(OS_WIN) +#include "base/win/windows_version.h" +#endif namespace content { +namespace { + +// Strip out the non-digital info; if after that, we get an empty string, +// return "0". +std::string ProcessVersionString(const std::string& raw_string) { + const std::string valid_set = "0123456789."; + size_t start_pos = raw_string.find_first_of(valid_set); + if (start_pos == std::string::npos) + return "0"; + size_t end_pos = raw_string.find_first_not_of(raw_string, start_pos); + std::string version_string = raw_string.substr( + start_pos, end_pos - start_pos); + if (version_string.empty()) + return "0"; + return version_string; +} + +// Combine the integers into a string, seperated by ','. +std::string IntSetToString(const std::set<int>& list) { + std::string rt; + for (std::set<int>::const_iterator it = list.begin(); + it != list.end(); ++it) { + if (!rt.empty()) + rt += ","; + rt += base::IntToString(*it); + } + return rt; +} + +#if defined(OS_MACOSX) +void DisplayReconfigCallback(CGDirectDisplayID display, + CGDisplayChangeSummaryFlags flags, + void* gpu_data_manager) { + if (flags & kCGDisplayAddFlag) { + GpuDataManagerImpl* manager = + reinterpret_cast<GpuDataManagerImpl*>(gpu_data_manager); + DCHECK(manager); + manager->HandleGpuSwitch(); + } +} +#endif // OS_MACOSX + +// Block all domains' use of 3D APIs for this many milliseconds if +// approaching a threshold where system stability might be compromised. +const int64 kBlockAllDomainsMs = 10000; +const int kNumResetsWithinDuration = 1; + +// Enums for UMA histograms. +enum BlockStatusHistogram { + BLOCK_STATUS_NOT_BLOCKED, + BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED, + BLOCK_STATUS_ALL_DOMAINS_BLOCKED, + BLOCK_STATUS_MAX +}; + +} // namespace anonymous // static GpuDataManager* GpuDataManager::GetInstance() { @@ -19,223 +112,839 @@ GpuDataManagerImpl* GpuDataManagerImpl::GetInstance() { } void GpuDataManagerImpl::InitializeForTesting( - const std::string& gpu_blacklist_json, const GPUInfo& gpu_info) { - base::AutoLock auto_lock(lock_); - private_->InitializeForTesting(gpu_blacklist_json, gpu_info); + const std::string& gpu_blacklist_json, + const GPUInfo& gpu_info) { + // This function is for testing only, so disable histograms. + update_histograms_ = false; + + InitializeImpl(gpu_blacklist_json, std::string(), std::string(), gpu_info); } bool GpuDataManagerImpl::IsFeatureBlacklisted(int feature) const { - base::AutoLock auto_lock(lock_); - return private_->IsFeatureBlacklisted(feature); + if (use_swiftshader_) { + // Skia's software rendering is probably more efficient than going through + // software emulation of the GPU, so use that. + if (feature == GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS) + return true; + return false; + } + + return (blacklisted_features_.count(feature) == 1); +} + +size_t GpuDataManagerImpl::GetBlacklistedFeatureCount() const { + if (use_swiftshader_) + return 1; + return blacklisted_features_.size(); +} + +void GpuDataManagerImpl::AddGpuSwitchCallback( + const GpuSwitchCallback& callback) { + gpu_switch_callbacks_.push_back(callback); +} + +void GpuDataManagerImpl::RemoveGpuSwitchCallback( + const GpuSwitchCallback& callback) { + for (size_t i = 0; i < gpu_switch_callbacks_.size(); i++) { + if (gpu_switch_callbacks_[i].Equals(callback)) { + gpu_switch_callbacks_.erase(gpu_switch_callbacks_.begin() + i); + return; + } + } } GPUInfo GpuDataManagerImpl::GetGPUInfo() const { - base::AutoLock auto_lock(lock_); - return private_->GetGPUInfo(); + GPUInfo gpu_info; + { + base::AutoLock auto_lock(gpu_info_lock_); + gpu_info = gpu_info_; + } + return gpu_info; } void GpuDataManagerImpl::GetGpuProcessHandles( const GetGpuProcessHandlesCallback& callback) const { - base::AutoLock auto_lock(lock_); - private_->GetGpuProcessHandles(callback); + GpuProcessHost::GetProcessHandles(callback); } bool GpuDataManagerImpl::GpuAccessAllowed(std::string* reason) const { - base::AutoLock auto_lock(lock_); - return private_->GpuAccessAllowed(reason); + if (use_swiftshader_) + return true; + + if (!gpu_info_.gpu_accessible) { + if (reason) { + *reason = "GPU process launch failed."; + } + return false; + } + + if (card_blacklisted_) { + if (reason) { + *reason = "GPU access is disabled "; + CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kDisableGpu)) + *reason += "through commandline switch --disable-gpu."; + else + *reason += "in chrome://settings."; + } + return false; + } + + // We only need to block GPU process if more features are disallowed other + // than those in the preliminary gpu feature flags because the latter work + // through renderer commandline switches. + std::set<int> features = preliminary_blacklisted_features_; + MergeFeatureSets(&features, blacklisted_features_); + if (features.size() > preliminary_blacklisted_features_.size()) { + if (reason) { + *reason = "Features are disabled upon full but not preliminary GPU info."; + } + return false; + } + + if (blacklisted_features_.size() == NUMBER_OF_GPU_FEATURE_TYPES) { + // On Linux, we use cached GL strings to make blacklist decsions at browser + // startup time. We need to launch the GPU process to validate these + // strings even if all features are blacklisted. If all GPU features are + // disabled, the GPU process will only initialize GL bindings, create a GL + // context, and collect full GPU info. +#if !defined(OS_LINUX) + if (reason) { + *reason = "All GPU features are blacklisted."; + } + return false; +#endif + } + + return true; } void GpuDataManagerImpl::RequestCompleteGpuInfoIfNeeded() { - base::AutoLock auto_lock(lock_); - private_->RequestCompleteGpuInfoIfNeeded(); + if (complete_gpu_info_already_requested_ || gpu_info_.finalized) + return; + complete_gpu_info_already_requested_ = true; + + GpuProcessHost::SendOnIO( +#if defined(OS_WIN) + GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED, +#else + GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, +#endif + CAUSE_FOR_GPU_LAUNCH_GPUDATAMANAGER_REQUESTCOMPLETEGPUINFOIFNEEDED, + new GpuMsg_CollectGraphicsInfo()); } bool GpuDataManagerImpl::IsCompleteGpuInfoAvailable() const { - base::AutoLock auto_lock(lock_); - return private_->IsCompleteGpuInfoAvailable(); + return gpu_info_.finalized; } void GpuDataManagerImpl::RequestVideoMemoryUsageStatsUpdate() const { - base::AutoLock auto_lock(lock_); - private_->RequestVideoMemoryUsageStatsUpdate(); + GpuProcessHost::SendOnIO( + GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, + CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, + new GpuMsg_GetVideoMemoryUsageStats()); } bool GpuDataManagerImpl::ShouldUseSwiftShader() const { - base::AutoLock auto_lock(lock_); - return private_->ShouldUseSwiftShader(); + return use_swiftshader_; } -void GpuDataManagerImpl::RegisterSwiftShaderPath( - const base::FilePath& path) { - base::AutoLock auto_lock(lock_); - private_->RegisterSwiftShaderPath(path); +void GpuDataManagerImpl::RegisterSwiftShaderPath(const base::FilePath& path) { + swiftshader_path_ = path; + EnableSwiftShaderIfNecessary(); } -void GpuDataManagerImpl::AddObserver( - GpuDataManagerObserver* observer) { - base::AutoLock auto_lock(lock_); - private_->AddObserver(observer); +void GpuDataManagerImpl::AddObserver(GpuDataManagerObserver* observer) { + observer_list_->AddObserver(observer); } -void GpuDataManagerImpl::RemoveObserver( - GpuDataManagerObserver* observer) { - base::AutoLock auto_lock(lock_); - private_->RemoveObserver(observer); +void GpuDataManagerImpl::RemoveObserver(GpuDataManagerObserver* observer) { + observer_list_->RemoveObserver(observer); } void GpuDataManagerImpl::UnblockDomainFrom3DAPIs(const GURL& url) { - base::AutoLock auto_lock(lock_); - private_->UnblockDomainFrom3DAPIs(url); + // This method must do two things: + // + // 1. If the specific domain is blocked, then unblock it. + // + // 2. Reset our notion of how many GPU resets have occurred recently. + // This is necessary even if the specific domain was blocked. + // Otherwise, if we call Are3DAPIsBlocked with the same domain right + // after unblocking it, it will probably still be blocked because of + // the recent GPU reset caused by that domain. + // + // These policies could be refined, but at a certain point the behavior + // will become difficult to explain. + std::string domain = GetDomainFromURL(url); + + base::AutoLock auto_lock(gpu_info_lock_); + blocked_domains_.erase(domain); + timestamps_of_gpu_resets_.clear(); } void GpuDataManagerImpl::DisableGpuWatchdog() { - base::AutoLock auto_lock(lock_); - private_->DisableGpuWatchdog(); + GpuProcessHost::SendOnIO( + GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, + CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, + new GpuMsg_DisableWatchdog); } void GpuDataManagerImpl::SetGLStrings(const std::string& gl_vendor, const std::string& gl_renderer, const std::string& gl_version) { - base::AutoLock auto_lock(lock_); - private_->SetGLStrings(gl_vendor, gl_renderer, gl_version); + if (gl_vendor.empty() && gl_renderer.empty() && gl_version.empty()) + return; + + GPUInfo gpu_info; + { + base::AutoLock auto_lock(gpu_info_lock_); + // If GPUInfo already got GL strings, do nothing. This is for the rare + // situation where GPU process collected GL strings before this call. + if (!gpu_info_.gl_vendor.empty() || + !gpu_info_.gl_renderer.empty() || + !gpu_info_.gl_version_string.empty()) + return; + gpu_info = gpu_info_; + } + + gpu_info.gl_vendor = gl_vendor; + gpu_info.gl_renderer = gl_renderer; + gpu_info.gl_version_string = gl_version; + + gpu_info_collector::CollectDriverInfoGL(&gpu_info); + + UpdateGpuInfo(gpu_info); + UpdateGpuSwitchingManager(gpu_info); + UpdatePreliminaryBlacklistedFeatures(); } void GpuDataManagerImpl::GetGLStrings(std::string* gl_vendor, std::string* gl_renderer, std::string* gl_version) { - base::AutoLock auto_lock(lock_); - private_->GetGLStrings(gl_vendor, gl_renderer, gl_version); -} + DCHECK(gl_vendor && gl_renderer && gl_version); -void GpuDataManagerImpl::DisableHardwareAcceleration() { - base::AutoLock auto_lock(lock_); - private_->DisableHardwareAcceleration(); + base::AutoLock auto_lock(gpu_info_lock_); + *gl_vendor = gpu_info_.gl_vendor; + *gl_renderer = gpu_info_.gl_renderer; + *gl_version = gpu_info_.gl_version_string; } + void GpuDataManagerImpl::Initialize() { - base::AutoLock auto_lock(lock_); - private_->Initialize(); + TRACE_EVENT0("startup", "GpuDataManagerImpl::Initialize"); + CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kSkipGpuDataLoading)) + return; + + GPUInfo gpu_info; + { + TRACE_EVENT0("startup", + "GpuDataManagerImpl::Initialize:CollectBasicGraphicsInfo"); + gpu_info_collector::CollectBasicGraphicsInfo(&gpu_info); + } +#if defined(ARCH_CPU_X86_FAMILY) + if (!gpu_info.gpu.vendor_id || !gpu_info.gpu.device_id) + gpu_info.finalized = true; +#endif + + std::string gpu_blacklist_string; + std::string gpu_switching_list_string; + std::string gpu_driver_bug_list_string; + if (!command_line->HasSwitch(switches::kIgnoreGpuBlacklist)) { + const base::StringPiece gpu_blacklist_json = + GetContentClient()->GetDataResource( + IDR_GPU_BLACKLIST, ui::SCALE_FACTOR_NONE); + gpu_blacklist_string = gpu_blacklist_json.as_string(); + const base::StringPiece gpu_switching_list_json = + GetContentClient()->GetDataResource( + IDR_GPU_SWITCHING_LIST, ui::SCALE_FACTOR_NONE); + gpu_switching_list_string = gpu_switching_list_json.as_string(); + } + if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) { + const base::StringPiece gpu_driver_bug_list_json = + GetContentClient()->GetDataResource( + IDR_GPU_DRIVER_BUG_LIST, ui::SCALE_FACTOR_NONE); + gpu_driver_bug_list_string = gpu_driver_bug_list_json.as_string(); + } + InitializeImpl(gpu_blacklist_string, + gpu_switching_list_string, + gpu_driver_bug_list_string, + gpu_info); + // We pass down the list to GPU command buffer through commandline + // switches at GPU process launch. However, in situations where we don't + // have a GPU process, we append the browser process commandline. + if (command_line->HasSwitch(switches::kSingleProcess) || + command_line->HasSwitch(switches::kInProcessGPU)) { + if (!gpu_driver_bugs_.empty()) { + command_line->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds, + IntSetToString(gpu_driver_bugs_)); + } + } } void GpuDataManagerImpl::UpdateGpuInfo(const GPUInfo& gpu_info) { - base::AutoLock auto_lock(lock_); - private_->UpdateGpuInfo(gpu_info); + // No further update of gpu_info if falling back to SwiftShader. + if (use_swiftshader_) + return; + + GPUInfo my_gpu_info; + { + base::AutoLock auto_lock(gpu_info_lock_); + gpu_info_collector::MergeGPUInfo(&gpu_info_, gpu_info); + complete_gpu_info_already_requested_ = + complete_gpu_info_already_requested_ || gpu_info_.finalized; + my_gpu_info = gpu_info_; + } + + GetContentClient()->SetGpuInfo(my_gpu_info); + + if (gpu_blacklist_) { + std::set<int> features = gpu_blacklist_->MakeDecision( + GpuControlList::kOsAny, std::string(), my_gpu_info); + if (update_histograms_) + UpdateStats(gpu_blacklist_.get(), features); + + UpdateBlacklistedFeatures(features); + } + if (gpu_switching_list_) { + std::set<int> option = gpu_switching_list_->MakeDecision( + GpuControlList::kOsAny, std::string(), my_gpu_info); + if (option.size() == 1) { + // Blacklist decision should not overwrite commandline switch from users. + CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (!command_line->HasSwitch(switches::kGpuSwitching)) + gpu_switching_ = static_cast<GpuSwitchingOption>(*(option.begin())); + } + } + if (gpu_driver_bug_list_) + gpu_driver_bugs_ = gpu_driver_bug_list_->MakeDecision( + GpuControlList::kOsAny, std::string(), my_gpu_info); + + // We have to update GpuFeatureType before notify all the observers. + NotifyGpuInfoUpdate(); } void GpuDataManagerImpl::UpdateVideoMemoryUsageStats( const GPUVideoMemoryUsageStats& video_memory_usage_stats) { - base::AutoLock auto_lock(lock_); - private_->UpdateVideoMemoryUsageStats(video_memory_usage_stats); + observer_list_->Notify(&GpuDataManagerObserver::OnVideoMemoryUsageStatsUpdate, + video_memory_usage_stats); } void GpuDataManagerImpl::AppendRendererCommandLine( CommandLine* command_line) const { - base::AutoLock auto_lock(lock_); - private_->AppendRendererCommandLine(command_line); + DCHECK(command_line); + + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_WEBGL)) { +#if !defined(OS_ANDROID) + if (!command_line->HasSwitch(switches::kDisableExperimentalWebGL)) + command_line->AppendSwitch(switches::kDisableExperimentalWebGL); +#endif + if (!command_line->HasSwitch(switches::kDisablePepper3d)) + command_line->AppendSwitch(switches::kDisablePepper3d); + } + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_MULTISAMPLING) && + !command_line->HasSwitch(switches::kDisableGLMultisampling)) + command_line->AppendSwitch(switches::kDisableGLMultisampling); + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) && + !command_line->HasSwitch(switches::kDisableAcceleratedCompositing)) + command_line->AppendSwitch(switches::kDisableAcceleratedCompositing); + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS) && + !command_line->HasSwitch(switches::kDisableAccelerated2dCanvas)) + command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas); + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) && + !command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) + command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode); + if (ShouldUseSwiftShader()) + command_line->AppendSwitch(switches::kDisableFlashFullscreen3d); } void GpuDataManagerImpl::AppendGpuCommandLine( CommandLine* command_line) const { - base::AutoLock auto_lock(lock_); - private_->AppendGpuCommandLine(command_line); + DCHECK(command_line); + + std::string use_gl = + CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL); + base::FilePath swiftshader_path = + CommandLine::ForCurrentProcess()->GetSwitchValuePath( + switches::kSwiftShaderPath); + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_MULTISAMPLING) && + !command_line->HasSwitch(switches::kDisableGLMultisampling)) + command_line->AppendSwitch(switches::kDisableGLMultisampling); + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_TEXTURE_SHARING)) + command_line->AppendSwitch(switches::kDisableImageTransportSurface); + + if (use_swiftshader_) { + command_line->AppendSwitchASCII(switches::kUseGL, "swiftshader"); + if (swiftshader_path.empty()) + swiftshader_path = swiftshader_path_; + } else if ((IsFeatureBlacklisted(GPU_FEATURE_TYPE_WEBGL) || + IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) || + IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)) && + (use_gl == "any")) { + command_line->AppendSwitchASCII( + switches::kUseGL, gfx::kGLImplementationOSMesaName); + } else if (!use_gl.empty()) { + command_line->AppendSwitchASCII(switches::kUseGL, use_gl); + } + if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) { + command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "true"); + switch (gpu_switching_) { + case GPU_SWITCHING_OPTION_FORCE_DISCRETE: + command_line->AppendSwitchASCII(switches::kGpuSwitching, + switches::kGpuSwitchingOptionNameForceDiscrete); + break; + case GPU_SWITCHING_OPTION_FORCE_INTEGRATED: + command_line->AppendSwitchASCII(switches::kGpuSwitching, + switches::kGpuSwitchingOptionNameForceIntegrated); + break; + case GPU_SWITCHING_OPTION_AUTOMATIC: + case GPU_SWITCHING_OPTION_UNKNOWN: + break; + } + } else { + command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "false"); + } + + if (!swiftshader_path.empty()) + command_line->AppendSwitchPath(switches::kSwiftShaderPath, + swiftshader_path); + + if (!gpu_driver_bugs_.empty()) { + command_line->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds, + IntSetToString(gpu_driver_bugs_)); + } + +#if defined(OS_WIN) + // DisplayLink 7.1 and earlier can cause the GPU process to crash on startup. + // http://crbug.com/177611 + // Thinkpad USB Port Replicator driver causes GPU process to crash when the + // sandbox is enabled. http://crbug.com/181665. + if ((gpu_info_.display_link_version.IsValid() + && gpu_info_.display_link_version.IsOlderThan("7.2")) || + gpu_info_.lenovo_dcute) { + command_line->AppendSwitch(switches::kReduceGpuSandbox); + } +#endif + + { + base::AutoLock auto_lock(gpu_info_lock_); + if (gpu_info_.optimus) + command_line->AppendSwitch(switches::kReduceGpuSandbox); + if (gpu_info_.amd_switchable) { + // The image transport surface currently doesn't work with AMD Dynamic + // Switchable graphics. + command_line->AppendSwitch(switches::kReduceGpuSandbox); + command_line->AppendSwitch(switches::kDisableImageTransportSurface); + } + // Pass GPU and driver information to GPU process. We try to avoid full GPU + // info collection at GPU process startup, but we need gpu vendor_id, + // device_id, driver_vendor, driver_version for deciding whether we need to + // collect full info (on Linux) and for crash reporting purpose. + command_line->AppendSwitchASCII(switches::kGpuVendorID, + base::StringPrintf("0x%04x", gpu_info_.gpu.vendor_id)); + command_line->AppendSwitchASCII(switches::kGpuDeviceID, + base::StringPrintf("0x%04x", gpu_info_.gpu.device_id)); + command_line->AppendSwitchASCII(switches::kGpuDriverVendor, + gpu_info_.driver_vendor); + command_line->AppendSwitchASCII(switches::kGpuDriverVersion, + gpu_info_.driver_version); + } } void GpuDataManagerImpl::AppendPluginCommandLine( CommandLine* command_line) const { - base::AutoLock auto_lock(lock_); - private_->AppendPluginCommandLine(command_line); + DCHECK(command_line); + +#if defined(OS_MACOSX) + // TODO(jbauman): Add proper blacklist support for core animation plugins so + // special-casing this video card won't be necessary. See + // http://crbug.com/134015 + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) || + CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableAcceleratedCompositing)) { + if (!command_line->HasSwitch( + switches::kDisableCoreAnimationPlugins)) + command_line->AppendSwitch( + switches::kDisableCoreAnimationPlugins); + } +#endif } -void GpuDataManagerImpl::UpdateRendererWebPrefs( - WebPreferences* prefs) const { - base::AutoLock auto_lock(lock_); - private_->UpdateRendererWebPrefs(prefs); +void GpuDataManagerImpl::UpdateRendererWebPrefs(WebPreferences* prefs) const { + DCHECK(prefs); + + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING)) + prefs->accelerated_compositing_enabled = false; + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_WEBGL)) + prefs->experimental_webgl_enabled = false; + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_FLASH3D)) + prefs->flash_3d_enabled = false; + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_FLASH_STAGE3D)) { + prefs->flash_stage3d_enabled = false; + prefs->flash_stage3d_baseline_enabled = false; + } + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE)) + prefs->flash_stage3d_baseline_enabled = false; + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)) + prefs->accelerated_2d_canvas_enabled = false; + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_MULTISAMPLING)) + prefs->gl_multisampling_enabled = false; + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_3D_CSS)) { + prefs->accelerated_compositing_for_3d_transforms_enabled = false; + prefs->accelerated_compositing_for_animation_enabled = false; + } + if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_VIDEO)) + prefs->accelerated_compositing_for_video_enabled = false; + + // Accelerated video and animation are slower than regular when using + // SwiftShader. 3D CSS may also be too slow to be worthwhile. + if (ShouldUseSwiftShader()) { + prefs->accelerated_compositing_for_video_enabled = false; + prefs->accelerated_compositing_for_animation_enabled = false; + prefs->accelerated_compositing_for_3d_transforms_enabled = false; + prefs->accelerated_compositing_for_plugins_enabled = false; + } } GpuSwitchingOption GpuDataManagerImpl::GetGpuSwitchingOption() const { - base::AutoLock auto_lock(lock_); - return private_->GetGpuSwitchingOption(); + if (!ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) + return GPU_SWITCHING_OPTION_UNKNOWN; + return gpu_switching_; } -std::string GpuDataManagerImpl::GetBlacklistVersion() const { - base::AutoLock auto_lock(lock_); - return private_->GetBlacklistVersion(); -} +void GpuDataManagerImpl::DisableHardwareAcceleration() { + card_blacklisted_ = true; -base::ListValue* GpuDataManagerImpl::GetBlacklistReasons() const { - base::AutoLock auto_lock(lock_); - return private_->GetBlacklistReasons(); + for (int i = 0; i < NUMBER_OF_GPU_FEATURE_TYPES; ++i) + blacklisted_features_.insert(i); + + EnableSwiftShaderIfNecessary(); + NotifyGpuInfoUpdate(); } -void GpuDataManagerImpl::AddLogMessage(int level, - const std::string& header, - const std::string& message) { - base::AutoLock auto_lock(lock_); - private_->AddLogMessage(level, header, message); +std::string GpuDataManagerImpl::GetBlacklistVersion() const { + if (gpu_blacklist_) + return gpu_blacklist_->version(); + return "0"; } -void GpuDataManagerImpl::ProcessCrashed( - base::TerminationStatus exit_code) { - base::AutoLock auto_lock(lock_); - private_->ProcessCrashed(exit_code); +base::ListValue* GpuDataManagerImpl::GetBlacklistReasons() const { + ListValue* reasons = new ListValue(); + if (gpu_blacklist_) + gpu_blacklist_->GetReasons(reasons); + return reasons; +} + +void GpuDataManagerImpl::AddLogMessage( + int level, const std::string& header, const std::string& message) { + base::AutoLock auto_lock(log_messages_lock_); + DictionaryValue* dict = new DictionaryValue(); + dict->SetInteger("level", level); + dict->SetString("header", header); + dict->SetString("message", message); + log_messages_.Append(dict); +} + +void GpuDataManagerImpl::ProcessCrashed(base::TerminationStatus exit_code) { + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { + BrowserThread::PostTask(BrowserThread::UI, + FROM_HERE, + base::Bind(&GpuDataManagerImpl::ProcessCrashed, + base::Unretained(this), + exit_code)); + return; + } + observer_list_->Notify(&GpuDataManagerObserver::OnGpuProcessCrashed, + exit_code); } base::ListValue* GpuDataManagerImpl::GetLogMessages() const { - base::AutoLock auto_lock(lock_); - return private_->GetLogMessages(); + base::ListValue* value; + { + base::AutoLock auto_lock(log_messages_lock_); + value = log_messages_.DeepCopy(); + } + return value; } void GpuDataManagerImpl::HandleGpuSwitch() { - base::AutoLock auto_lock(lock_); - private_->HandleGpuSwitch(); + complete_gpu_info_already_requested_ = false; + gpu_info_.finalized = false; + for (size_t i = 0; i < gpu_switch_callbacks_.size(); ++i) + gpu_switch_callbacks_[i].Run(); } #if defined(OS_WIN) bool GpuDataManagerImpl::IsUsingAcceleratedSurface() const { - base::AutoLock auto_lock(lock_); - return private_->IsUsingAcceleratedSurface(); + if (base::win::GetVersion() < base::win::VERSION_VISTA) + return false; + + if (gpu_info_.amd_switchable) + return false; + if (use_swiftshader_) + return false; + CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kDisableImageTransportSurface)) + return false; + return !IsFeatureBlacklisted(GPU_FEATURE_TYPE_TEXTURE_SHARING); } #endif void GpuDataManagerImpl::BlockDomainFrom3DAPIs( const GURL& url, DomainGuilt guilt) { - base::AutoLock auto_lock(lock_); - private_->BlockDomainFrom3DAPIs(url, guilt); + BlockDomainFrom3DAPIsAtTime(url, guilt, base::Time::Now()); } bool GpuDataManagerImpl::Are3DAPIsBlocked(const GURL& url, int render_process_id, int render_view_id, ThreeDAPIType requester) { - base::AutoLock auto_lock(lock_); - return private_->Are3DAPIsBlocked( - url, render_process_id, render_view_id, requester); + bool blocked = Are3DAPIsBlockedAtTime(url, base::Time::Now()) != + GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED; + if (blocked) { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&GpuDataManagerImpl::Notify3DAPIBlocked, + base::Unretained(this), url, render_process_id, + render_view_id, requester)); + } + + return blocked; } void GpuDataManagerImpl::DisableDomainBlockingFor3DAPIsForTesting() { - base::AutoLock auto_lock(lock_); - private_->DisableDomainBlockingFor3DAPIsForTesting(); + domain_blocking_enabled_ = false; } -size_t GpuDataManagerImpl::GetBlacklistedFeatureCount() const { - base::AutoLock auto_lock(lock_); - return private_->GetBlacklistedFeatureCount(); +GpuDataManagerImpl::GpuDataManagerImpl() + : complete_gpu_info_already_requested_(false), + gpu_switching_(GPU_SWITCHING_OPTION_AUTOMATIC), + observer_list_(new GpuDataManagerObserverList), + use_swiftshader_(false), + card_blacklisted_(false), + update_histograms_(true), + window_count_(0), + domain_blocking_enabled_(true) { + CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kDisableAcceleratedCompositing)) { + command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas); + command_line->AppendSwitch(switches::kDisableAcceleratedLayers); + } + if (command_line->HasSwitch(switches::kDisableGpu)) + DisableHardwareAcceleration(); + if (command_line->HasSwitch(switches::kGpuSwitching)) { + std::string option_string = command_line->GetSwitchValueASCII( + switches::kGpuSwitching); + GpuSwitchingOption option = StringToGpuSwitchingOption(option_string); + if (option != GPU_SWITCHING_OPTION_UNKNOWN) + gpu_switching_ = option; + } + +#if defined(OS_MACOSX) + CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback, this); +#endif // OS_MACOSX } -void GpuDataManagerImpl::Notify3DAPIBlocked(const GURL& url, - int render_process_id, - int render_view_id, - ThreeDAPIType requester) { - base::AutoLock auto_lock(lock_); - private_->Notify3DAPIBlocked( - url, render_process_id, render_view_id, requester); +GpuDataManagerImpl::~GpuDataManagerImpl() { +#if defined(OS_MACOSX) + CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback, this); +#endif } -GpuDataManagerImpl::GpuDataManagerImpl() - : private_(GpuDataManagerImplPrivate::Create(this)) { +void GpuDataManagerImpl::InitializeImpl( + const std::string& gpu_blacklist_json, + const std::string& gpu_switching_list_json, + const std::string& gpu_driver_bug_list_json, + const GPUInfo& gpu_info) { + std::string browser_version_string = ProcessVersionString( + GetContentClient()->GetProduct()); + CHECK(!browser_version_string.empty()); + + if (!gpu_blacklist_json.empty()) { + gpu_blacklist_.reset(GpuBlacklist::Create()); + gpu_blacklist_->LoadList( + browser_version_string, gpu_blacklist_json, + GpuControlList::kCurrentOsOnly); + } + if (!gpu_switching_list_json.empty()) { + gpu_switching_list_.reset(GpuSwitchingList::Create()); + gpu_switching_list_->LoadList( + browser_version_string, gpu_switching_list_json, + GpuControlList::kCurrentOsOnly); + } + if (!gpu_driver_bug_list_json.empty()) { + gpu_driver_bug_list_.reset(GpuDriverBugList::Create()); + gpu_driver_bug_list_->LoadList( + browser_version_string, gpu_driver_bug_list_json, + GpuControlList::kCurrentOsOnly); + } + + { + base::AutoLock auto_lock(gpu_info_lock_); + gpu_info_ = gpu_info; + } + UpdateGpuInfo(gpu_info); + UpdateGpuSwitchingManager(gpu_info); + UpdatePreliminaryBlacklistedFeatures(); +} + +void GpuDataManagerImpl::UpdateBlacklistedFeatures( + const std::set<int>& features) { + CommandLine* command_line = CommandLine::ForCurrentProcess(); + blacklisted_features_ = features; + + // Force disable using the GPU for these features, even if they would + // otherwise be allowed. + if (card_blacklisted_ || + command_line->HasSwitch(switches::kBlacklistAcceleratedCompositing)) { + blacklisted_features_.insert(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING); + } + if (card_blacklisted_ || + command_line->HasSwitch(switches::kBlacklistWebGL)) { + blacklisted_features_.insert(GPU_FEATURE_TYPE_WEBGL); + } + + EnableSwiftShaderIfNecessary(); +} + +void GpuDataManagerImpl::UpdatePreliminaryBlacklistedFeatures() { + preliminary_blacklisted_features_ = blacklisted_features_; +} + +void GpuDataManagerImpl::UpdateGpuSwitchingManager(const GPUInfo& gpu_info) { + ui::GpuSwitchingManager::GetInstance()->SetGpuCount( + gpu_info.secondary_gpus.size() + 1); + + if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) { + switch (gpu_switching_) { + case GPU_SWITCHING_OPTION_FORCE_DISCRETE: + ui::GpuSwitchingManager::GetInstance()->ForceUseOfDiscreteGpu(); + break; + case GPU_SWITCHING_OPTION_FORCE_INTEGRATED: + ui::GpuSwitchingManager::GetInstance()->ForceUseOfIntegratedGpu(); + break; + case GPU_SWITCHING_OPTION_AUTOMATIC: + case GPU_SWITCHING_OPTION_UNKNOWN: + break; + } + } +} + +void GpuDataManagerImpl::NotifyGpuInfoUpdate() { + observer_list_->Notify(&GpuDataManagerObserver::OnGpuInfoUpdate); +} + +void GpuDataManagerImpl::EnableSwiftShaderIfNecessary() { + if (!GpuAccessAllowed(NULL) || + blacklisted_features_.count(GPU_FEATURE_TYPE_WEBGL)) { + if (!swiftshader_path_.empty() && + !CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableSoftwareRasterizer)) + use_swiftshader_ = true; + } +} + +std::string GpuDataManagerImpl::GetDomainFromURL(const GURL& url) const { + // For the moment, we just use the host, or its IP address, as the + // entry in the set, rather than trying to figure out the top-level + // domain. This does mean that a.foo.com and b.foo.com will be + // treated independently in the blocking of a given domain, but it + // would require a third-party library to reliably figure out the + // top-level domain from a URL. + if (!url.has_host()) { + return std::string(); + } + + return url.host(); +} + +void GpuDataManagerImpl::BlockDomainFrom3DAPIsAtTime( + const GURL& url, DomainGuilt guilt, base::Time at_time) { + if (!domain_blocking_enabled_) + return; + + std::string domain = GetDomainFromURL(url); + + base::AutoLock auto_lock(gpu_info_lock_); + DomainBlockEntry& entry = blocked_domains_[domain]; + entry.last_guilt = guilt; + timestamps_of_gpu_resets_.push_back(at_time); +} + +GpuDataManagerImpl::DomainBlockStatus +GpuDataManagerImpl::Are3DAPIsBlockedAtTime( + const GURL& url, base::Time at_time) const { + if (!domain_blocking_enabled_) + return DOMAIN_BLOCK_STATUS_NOT_BLOCKED; + + // Note: adjusting the policies in this code will almost certainly + // require adjusting the associated unit tests. + std::string domain = GetDomainFromURL(url); + + base::AutoLock auto_lock(gpu_info_lock_); + { + DomainBlockMap::const_iterator iter = blocked_domains_.find(domain); + if (iter != blocked_domains_.end()) { + // Err on the side of caution, and assume that if a particular + // domain shows up in the block map, it's there for a good + // reason and don't let its presence there automatically expire. + + UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs", + BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED, + BLOCK_STATUS_MAX); + + return DOMAIN_BLOCK_STATUS_BLOCKED; + } + } + + // Look at the timestamps of the recent GPU resets to see if there are + // enough within the threshold which would cause us to blacklist all + // domains. This doesn't need to be overly precise -- if time goes + // backward due to a system clock adjustment, that's fine. + // + // TODO(kbr): make this pay attention to the TDR thresholds in the + // Windows registry, but make sure it continues to be testable. + std::list<base::Time>::iterator iter = timestamps_of_gpu_resets_.begin(); + int num_resets_within_timeframe = 0; + while (iter != timestamps_of_gpu_resets_.end()) { + base::Time time = *iter; + base::TimeDelta delta_t = at_time - time; + + // If this entry has "expired", just remove it. + if (delta_t.InMilliseconds() > kBlockAllDomainsMs) { + iter = timestamps_of_gpu_resets_.erase(iter); + continue; + } + + ++num_resets_within_timeframe; + ++iter; + } + + if (num_resets_within_timeframe >= kNumResetsWithinDuration) { + UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs", + BLOCK_STATUS_ALL_DOMAINS_BLOCKED, + BLOCK_STATUS_MAX); + + return DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED; + } + + UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs", + BLOCK_STATUS_NOT_BLOCKED, + BLOCK_STATUS_MAX); + + return DOMAIN_BLOCK_STATUS_NOT_BLOCKED; +} + +int64 GpuDataManagerImpl::GetBlockAllDomainsDurationInMs() const { + return kBlockAllDomainsMs; } -GpuDataManagerImpl::~GpuDataManagerImpl() { +void GpuDataManagerImpl::Notify3DAPIBlocked(const GURL& url, + int render_process_id, + int render_view_id, + ThreeDAPIType requester) { + observer_list_->Notify(&GpuDataManagerObserver::DidBlock3DAPIs, + url, render_process_id, render_view_id, requester); } } // namespace content diff --git a/content/browser/gpu/gpu_data_manager_impl.h b/content/browser/gpu/gpu_data_manager_impl.h index 32ff23b..5fa8780 100644 --- a/content/browser/gpu/gpu_data_manager_impl.h +++ b/content/browser/gpu/gpu_data_manager_impl.h @@ -1,22 +1,30 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CONTENT_BROWSER_GPU_GPU_DATA_MANAGER_IMPL_H_ #define CONTENT_BROWSER_GPU_GPU_DATA_MANAGER_IMPL_H_ +#include <list> +#include <map> +#include <set> #include <string> +#include <vector> +#include "base/callback.h" #include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/gtest_prod_util.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" +#include "base/memory/ref_counted.h" #include "base/memory/singleton.h" +#include "base/observer_list_threadsafe.h" #include "base/process_util.h" #include "base/synchronization/lock.h" #include "base/time.h" #include "base/values.h" +#include "content/browser/gpu/gpu_blacklist.h" +#include "content/browser/gpu/gpu_driver_bug_list.h" +#include "content/browser/gpu/gpu_switching_list.h" #include "content/public/browser/gpu_data_manager.h" #include "content/public/common/gpu_info.h" #include "content/public/common/gpu_memory_stats.h" @@ -29,8 +37,6 @@ struct WebPreferences; namespace content { -class GpuDataManagerImplPrivate; - class CONTENT_EXPORT GpuDataManagerImpl : public NON_EXPORTED_BASE(GpuDataManager) { public: @@ -157,48 +163,133 @@ class CONTENT_EXPORT GpuDataManagerImpl // Disables domain blocking for 3D APIs. For use only in tests. void DisableDomainBlockingFor3DAPIsForTesting(); - void Notify3DAPIBlocked(const GURL& url, - int render_process_id, - int render_view_id, - ThreeDAPIType requester); - // Get number of features being blacklisted. size_t GetBlacklistedFeatureCount() const; + typedef base::Callback<void()> GpuSwitchCallback; + + // Add and remove gpu switch callback. + void AddGpuSwitchCallback(const GpuSwitchCallback& callback); + void RemoveGpuSwitchCallback(const GpuSwitchCallback& callback); + private: - friend class GpuDataManagerImplPrivate; - friend class GpuDataManagerImplPrivateTest; + struct DomainBlockEntry { + DomainGuilt last_guilt; + }; + + typedef std::map<std::string, DomainBlockEntry> DomainBlockMap; + + typedef ObserverListThreadSafe<GpuDataManagerObserver> + GpuDataManagerObserverList; + + friend class GpuDataManagerImplTest; friend struct DefaultSingletonTraits<GpuDataManagerImpl>; - // It's similar to AutoUnlock, but we want to make it a no-op - // if the owner GpuDataManagerImpl is null. - // This should only be used by GpuDataManagerImplPrivate where - // callbacks are called, during which re-entering - // GpuDataManagerImpl is possible. - class UnlockedSession { - public: - explicit UnlockedSession(GpuDataManagerImpl* owner) - : owner_(owner) { - DCHECK(owner_); - owner_->lock_.AssertAcquired(); - owner_->lock_.Release(); - } - - ~UnlockedSession() { - DCHECK(owner_); - owner_->lock_.Acquire(); - } - - private: - GpuDataManagerImpl* owner_; - DISALLOW_COPY_AND_ASSIGN(UnlockedSession); - }; + FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, GpuSideBlacklisting); + FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, GpuSideExceptions); + FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, + DisableHardwareAcceleration); + FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, SwiftShaderRendering); + FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, SwiftShaderRendering2); + FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, GpuInfoUpdate); + FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, + NoGpuInfoUpdateWithSwiftShader); + FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, + GPUVideoMemoryUsageStatsUpdate); + FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, + BlockAllDomainsFrom3DAPIs); + FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, + UnblockGuiltyDomainFrom3DAPIs); + FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, + UnblockDomainOfUnknownGuiltFrom3DAPIs); + FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, + UnblockOtherDomainFrom3DAPIs); + FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, + UnblockThisDomainFrom3DAPIs); + FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, GpuDriverBugListSingle); + FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplTest, GpuDriverBugListMultiple); GpuDataManagerImpl(); virtual ~GpuDataManagerImpl(); - mutable base::Lock lock_; - scoped_ptr<GpuDataManagerImplPrivate> private_; + void InitializeImpl(const std::string& gpu_blacklist_json, + const std::string& gpu_switching_list_json, + const std::string& gpu_driver_bug_list_json, + const GPUInfo& gpu_info); + + void UpdateBlacklistedFeatures(const std::set<int>& features); + + // This should only be called once at initialization time, when preliminary + // gpu info is collected. + void UpdatePreliminaryBlacklistedFeatures(); + + // Update the GPU switching status. + // This should only be called once at initialization time. + void UpdateGpuSwitchingManager(const GPUInfo& gpu_info); + + // Notify all observers whenever there is a GPU info update. + void NotifyGpuInfoUpdate(); + + // Try to switch to SwiftShader rendering, if possible and necessary. + void EnableSwiftShaderIfNecessary(); + + // Helper to extract the domain from a given URL. + std::string GetDomainFromURL(const GURL& url) const; + + // Implementation functions for blocking of 3D graphics APIs, used + // for unit testing. + void BlockDomainFrom3DAPIsAtTime( + const GURL& url, DomainGuilt guilt, base::Time at_time); + DomainBlockStatus Are3DAPIsBlockedAtTime( + const GURL& url, base::Time at_time) const; + int64 GetBlockAllDomainsDurationInMs() const; + + void Notify3DAPIBlocked(const GURL& url, + int render_process_id, + int render_view_id, + ThreeDAPIType requester); + + bool complete_gpu_info_already_requested_; + + std::set<int> blacklisted_features_; + std::set<int> preliminary_blacklisted_features_; + + GpuSwitchingOption gpu_switching_; + + std::set<int> gpu_driver_bugs_; + + GPUInfo gpu_info_; + mutable base::Lock gpu_info_lock_; + + scoped_ptr<GpuBlacklist> gpu_blacklist_; + scoped_ptr<GpuSwitchingList> gpu_switching_list_; + scoped_ptr<GpuDriverBugList> gpu_driver_bug_list_; + + const scoped_refptr<GpuDataManagerObserverList> observer_list_; + + ListValue log_messages_; + mutable base::Lock log_messages_lock_; + + bool use_swiftshader_; + + base::FilePath swiftshader_path_; + + // Current card force-blacklisted due to GPU crashes, or disabled through + // the --disable-gpu commandline switch. + bool card_blacklisted_; + + // We disable histogram stuff in testing, especially in unit tests because + // they cause random failures. + bool update_histograms_; + + // Number of currently open windows, to be used in gpu memory allocation. + int window_count_; + + DomainBlockMap blocked_domains_; + mutable std::list<base::Time> timestamps_of_gpu_resets_; + bool domain_blocking_enabled_; + + std::vector<GpuSwitchCallback> gpu_switch_callbacks_; DISALLOW_COPY_AND_ASSIGN(GpuDataManagerImpl); }; diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc deleted file mode 100644 index 2d9f360..0000000 --- a/content/browser/gpu/gpu_data_manager_impl_private.cc +++ /dev/null @@ -1,925 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/gpu/gpu_data_manager_impl_private.h" - -#if defined(OS_MACOSX) -#include <ApplicationServices/ApplicationServices.h> -#endif // OS_MACOSX - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/command_line.h" -#include "base/debug/trace_event.h" -#include "base/metrics/field_trial.h" -#include "base/metrics/histogram.h" -#include "base/stringprintf.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" -#include "base/sys_info.h" -#include "base/version.h" -#include "content/browser/gpu/gpu_process_host.h" -#include "content/browser/gpu/gpu_util.h" -#include "content/common/gpu/gpu_messages.h" -#include "content/gpu/gpu_info_collector.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/gpu_data_manager_observer.h" -#include "content/public/common/content_client.h" -#include "content/public/common/content_constants.h" -#include "content/public/common/content_switches.h" -#include "content/public/common/gpu_feature_type.h" -#include "gpu/command_buffer/service/gpu_switches.h" -#include "grit/content_resources.h" -#include "ui/base/ui_base_switches.h" -#include "ui/gl/gl_implementation.h" -#include "ui/gl/gl_switches.h" -#include "ui/gl/gpu_switching_manager.h" -#include "webkit/glue/webpreferences.h" -#include "webkit/plugins/plugin_switches.h" - -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#endif - -namespace content { -namespace { - -// Strip out the non-digital info; if after that, we get an empty string, -// return "0". -std::string ProcessVersionString(const std::string& raw_string) { - const std::string valid_set = "0123456789."; - size_t start_pos = raw_string.find_first_of(valid_set); - if (start_pos == std::string::npos) - return "0"; - size_t end_pos = raw_string.find_first_not_of(raw_string, start_pos); - std::string version_string = raw_string.substr( - start_pos, end_pos - start_pos); - if (version_string.empty()) - return "0"; - return version_string; -} - -// Combine the integers into a string, seperated by ','. -std::string IntSetToString(const std::set<int>& list) { - std::string rt; - for (std::set<int>::const_iterator it = list.begin(); - it != list.end(); ++it) { - if (!rt.empty()) - rt += ","; - rt += base::IntToString(*it); - } - return rt; -} - -#if defined(OS_MACOSX) -void DisplayReconfigCallback(CGDirectDisplayID display, - CGDisplayChangeSummaryFlags flags, - void* gpu_data_manager) { - if (flags & kCGDisplayAddFlag) { - GpuDataManagerImpl* manager = - reinterpret_cast<GpuDataManagerImpl*>(gpu_data_manager); - DCHECK(manager); - manager->HandleGpuSwitch(); - } -} -#endif // OS_MACOSX - -// Block all domains' use of 3D APIs for this many milliseconds if -// approaching a threshold where system stability might be compromised. -const int64 kBlockAllDomainsMs = 10000; -const int kNumResetsWithinDuration = 1; - -// Enums for UMA histograms. -enum BlockStatusHistogram { - BLOCK_STATUS_NOT_BLOCKED, - BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED, - BLOCK_STATUS_ALL_DOMAINS_BLOCKED, - BLOCK_STATUS_MAX -}; - -} // namespace anonymous - -void GpuDataManagerImplPrivate::InitializeForTesting( - const std::string& gpu_blacklist_json, - const GPUInfo& gpu_info) { - // This function is for testing only, so disable histograms. - update_histograms_ = false; - - InitializeImpl(gpu_blacklist_json, std::string(), std::string(), gpu_info); -} - -bool GpuDataManagerImplPrivate::IsFeatureBlacklisted(int feature) const { - if (use_swiftshader_) { - // Skia's software rendering is probably more efficient than going through - // software emulation of the GPU, so use that. - if (feature == GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS) - return true; - return false; - } - - return (blacklisted_features_.count(feature) == 1); -} - -size_t GpuDataManagerImplPrivate::GetBlacklistedFeatureCount() const { - if (use_swiftshader_) - return 1; - return blacklisted_features_.size(); -} - -GPUInfo GpuDataManagerImplPrivate::GetGPUInfo() const { - return gpu_info_; -} - -void GpuDataManagerImplPrivate::GetGpuProcessHandles( - const GpuDataManager::GetGpuProcessHandlesCallback& callback) const { - GpuProcessHost::GetProcessHandles(callback); -} - -bool GpuDataManagerImplPrivate::GpuAccessAllowed( - std::string* reason) const { - if (use_swiftshader_) - return true; - - if (!gpu_info_.gpu_accessible) { - if (reason) { - *reason = "GPU process launch failed."; - } - return false; - } - - if (card_blacklisted_) { - if (reason) { - *reason = "GPU access is disabled "; - CommandLine* command_line = CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kDisableGpu)) - *reason += "through commandline switch --disable-gpu."; - else - *reason += "in chrome://settings."; - } - return false; - } - - // We only need to block GPU process if more features are disallowed other - // than those in the preliminary gpu feature flags because the latter work - // through renderer commandline switches. - std::set<int> features = preliminary_blacklisted_features_; - MergeFeatureSets(&features, blacklisted_features_); - if (features.size() > preliminary_blacklisted_features_.size()) { - if (reason) { - *reason = "Features are disabled upon full but not preliminary GPU info."; - } - return false; - } - - if (blacklisted_features_.size() == NUMBER_OF_GPU_FEATURE_TYPES) { - // On Linux, we use cached GL strings to make blacklist decsions at browser - // startup time. We need to launch the GPU process to validate these - // strings even if all features are blacklisted. If all GPU features are - // disabled, the GPU process will only initialize GL bindings, create a GL - // context, and collect full GPU info. -#if !defined(OS_LINUX) - if (reason) { - *reason = "All GPU features are blacklisted."; - } - return false; -#endif - } - - return true; -} - -void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() { - if (complete_gpu_info_already_requested_ || gpu_info_.finalized) - return; - complete_gpu_info_already_requested_ = true; - - GpuProcessHost::SendOnIO( -#if defined(OS_WIN) - GpuProcessHost::GPU_PROCESS_KIND_UNSANDBOXED, -#else - GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, -#endif - CAUSE_FOR_GPU_LAUNCH_GPUDATAMANAGER_REQUESTCOMPLETEGPUINFOIFNEEDED, - new GpuMsg_CollectGraphicsInfo()); -} - -bool GpuDataManagerImplPrivate::IsCompleteGpuInfoAvailable() const { - return gpu_info_.finalized; -} - -void GpuDataManagerImplPrivate::RequestVideoMemoryUsageStatsUpdate() const { - GpuProcessHost::SendOnIO( - GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, - CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, - new GpuMsg_GetVideoMemoryUsageStats()); -} - -bool GpuDataManagerImplPrivate::ShouldUseSwiftShader() const { - return use_swiftshader_; -} - -void GpuDataManagerImplPrivate::RegisterSwiftShaderPath( - const base::FilePath& path) { - swiftshader_path_ = path; - EnableSwiftShaderIfNecessary(); -} - -void GpuDataManagerImplPrivate::AddObserver(GpuDataManagerObserver* observer) { - GpuDataManagerImpl::UnlockedSession session(owner_); - observer_list_->AddObserver(observer); -} - -void GpuDataManagerImplPrivate::RemoveObserver( - GpuDataManagerObserver* observer) { - GpuDataManagerImpl::UnlockedSession session(owner_); - observer_list_->RemoveObserver(observer); -} - -void GpuDataManagerImplPrivate::UnblockDomainFrom3DAPIs(const GURL& url) { - // This method must do two things: - // - // 1. If the specific domain is blocked, then unblock it. - // - // 2. Reset our notion of how many GPU resets have occurred recently. - // This is necessary even if the specific domain was blocked. - // Otherwise, if we call Are3DAPIsBlocked with the same domain right - // after unblocking it, it will probably still be blocked because of - // the recent GPU reset caused by that domain. - // - // These policies could be refined, but at a certain point the behavior - // will become difficult to explain. - std::string domain = GetDomainFromURL(url); - - blocked_domains_.erase(domain); - timestamps_of_gpu_resets_.clear(); -} - -void GpuDataManagerImplPrivate::DisableGpuWatchdog() { - GpuProcessHost::SendOnIO( - GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, - CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, - new GpuMsg_DisableWatchdog); -} - -void GpuDataManagerImplPrivate::SetGLStrings(const std::string& gl_vendor, - const std::string& gl_renderer, - const std::string& gl_version) { - if (gl_vendor.empty() && gl_renderer.empty() && gl_version.empty()) - return; - - // If GPUInfo already got GL strings, do nothing. This is for the rare - // situation where GPU process collected GL strings before this call. - if (!gpu_info_.gl_vendor.empty() || - !gpu_info_.gl_renderer.empty() || - !gpu_info_.gl_version_string.empty()) - return; - - GPUInfo gpu_info = gpu_info_; - - gpu_info.gl_vendor = gl_vendor; - gpu_info.gl_renderer = gl_renderer; - gpu_info.gl_version_string = gl_version; - - gpu_info_collector::CollectDriverInfoGL(&gpu_info); - - UpdateGpuInfo(gpu_info); - UpdateGpuSwitchingManager(gpu_info); - UpdatePreliminaryBlacklistedFeatures(); -} - -void GpuDataManagerImplPrivate::GetGLStrings(std::string* gl_vendor, - std::string* gl_renderer, - std::string* gl_version) { - DCHECK(gl_vendor && gl_renderer && gl_version); - - *gl_vendor = gpu_info_.gl_vendor; - *gl_renderer = gpu_info_.gl_renderer; - *gl_version = gpu_info_.gl_version_string; -} - -void GpuDataManagerImplPrivate::Initialize() { - TRACE_EVENT0("startup", "GpuDataManagerImpl::Initialize"); - CommandLine* command_line = CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kSkipGpuDataLoading)) - return; - - GPUInfo gpu_info; - { - TRACE_EVENT0("startup", - "GpuDataManagerImpl::Initialize:CollectBasicGraphicsInfo"); - gpu_info_collector::CollectBasicGraphicsInfo(&gpu_info); - } -#if defined(ARCH_CPU_X86_FAMILY) - if (!gpu_info.gpu.vendor_id || !gpu_info.gpu.device_id) - gpu_info.finalized = true; -#endif - - std::string gpu_blacklist_string; - std::string gpu_switching_list_string; - std::string gpu_driver_bug_list_string; - if (!command_line->HasSwitch(switches::kIgnoreGpuBlacklist)) { - const base::StringPiece gpu_blacklist_json = - GetContentClient()->GetDataResource( - IDR_GPU_BLACKLIST, ui::SCALE_FACTOR_NONE); - gpu_blacklist_string = gpu_blacklist_json.as_string(); - const base::StringPiece gpu_switching_list_json = - GetContentClient()->GetDataResource( - IDR_GPU_SWITCHING_LIST, ui::SCALE_FACTOR_NONE); - gpu_switching_list_string = gpu_switching_list_json.as_string(); - } - if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) { - const base::StringPiece gpu_driver_bug_list_json = - GetContentClient()->GetDataResource( - IDR_GPU_DRIVER_BUG_LIST, ui::SCALE_FACTOR_NONE); - gpu_driver_bug_list_string = gpu_driver_bug_list_json.as_string(); - } - InitializeImpl(gpu_blacklist_string, - gpu_switching_list_string, - gpu_driver_bug_list_string, - gpu_info); - // We pass down the list to GPU command buffer through commandline - // switches at GPU process launch. However, in situations where we don't - // have a GPU process, we append the browser process commandline. - if (command_line->HasSwitch(switches::kSingleProcess) || - command_line->HasSwitch(switches::kInProcessGPU)) { - if (!gpu_driver_bugs_.empty()) { - command_line->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds, - IntSetToString(gpu_driver_bugs_)); - } - } -} - -void GpuDataManagerImplPrivate::UpdateGpuInfo(const GPUInfo& gpu_info) { - // No further update of gpu_info if falling back to SwiftShader. - if (use_swiftshader_) - return; - - gpu_info_collector::MergeGPUInfo(&gpu_info_, gpu_info); - complete_gpu_info_already_requested_ = - complete_gpu_info_already_requested_ || gpu_info_.finalized; - - GetContentClient()->SetGpuInfo(gpu_info_); - - if (gpu_blacklist_) { - std::set<int> features = gpu_blacklist_->MakeDecision( - GpuControlList::kOsAny, std::string(), gpu_info_); - if (update_histograms_) - UpdateStats(gpu_blacklist_.get(), features); - - UpdateBlacklistedFeatures(features); - } - if (gpu_switching_list_) { - std::set<int> option = gpu_switching_list_->MakeDecision( - GpuControlList::kOsAny, std::string(), gpu_info_); - if (option.size() == 1) { - // Blacklist decision should not overwrite commandline switch from users. - CommandLine* command_line = CommandLine::ForCurrentProcess(); - if (!command_line->HasSwitch(switches::kGpuSwitching)) - gpu_switching_ = static_cast<GpuSwitchingOption>(*(option.begin())); - } - } - if (gpu_driver_bug_list_) - gpu_driver_bugs_ = gpu_driver_bug_list_->MakeDecision( - GpuControlList::kOsAny, std::string(), gpu_info_); - - // We have to update GpuFeatureType before notify all the observers. - NotifyGpuInfoUpdate(); -} - -void GpuDataManagerImplPrivate::UpdateVideoMemoryUsageStats( - const GPUVideoMemoryUsageStats& video_memory_usage_stats) { - GpuDataManagerImpl::UnlockedSession session(owner_); - observer_list_->Notify(&GpuDataManagerObserver::OnVideoMemoryUsageStatsUpdate, - video_memory_usage_stats); -} - -void GpuDataManagerImplPrivate::AppendRendererCommandLine( - CommandLine* command_line) const { - DCHECK(command_line); - - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_WEBGL)) { -#if !defined(OS_ANDROID) - if (!command_line->HasSwitch(switches::kDisableExperimentalWebGL)) - command_line->AppendSwitch(switches::kDisableExperimentalWebGL); -#endif - if (!command_line->HasSwitch(switches::kDisablePepper3d)) - command_line->AppendSwitch(switches::kDisablePepper3d); - } - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_MULTISAMPLING) && - !command_line->HasSwitch(switches::kDisableGLMultisampling)) - command_line->AppendSwitch(switches::kDisableGLMultisampling); - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) && - !command_line->HasSwitch(switches::kDisableAcceleratedCompositing)) - command_line->AppendSwitch(switches::kDisableAcceleratedCompositing); - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS) && - !command_line->HasSwitch(switches::kDisableAccelerated2dCanvas)) - command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas); - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) && - !command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) - command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode); - if (ShouldUseSwiftShader()) - command_line->AppendSwitch(switches::kDisableFlashFullscreen3d); -} - -void GpuDataManagerImplPrivate::AppendGpuCommandLine( - CommandLine* command_line) const { - DCHECK(command_line); - - std::string use_gl = - CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL); - base::FilePath swiftshader_path = - CommandLine::ForCurrentProcess()->GetSwitchValuePath( - switches::kSwiftShaderPath); - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_MULTISAMPLING) && - !command_line->HasSwitch(switches::kDisableGLMultisampling)) - command_line->AppendSwitch(switches::kDisableGLMultisampling); - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_TEXTURE_SHARING)) - command_line->AppendSwitch(switches::kDisableImageTransportSurface); - - if (use_swiftshader_) { - command_line->AppendSwitchASCII(switches::kUseGL, "swiftshader"); - if (swiftshader_path.empty()) - swiftshader_path = swiftshader_path_; - } else if ((IsFeatureBlacklisted(GPU_FEATURE_TYPE_WEBGL) || - IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) || - IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)) && - (use_gl == "any")) { - command_line->AppendSwitchASCII( - switches::kUseGL, gfx::kGLImplementationOSMesaName); - } else if (!use_gl.empty()) { - command_line->AppendSwitchASCII(switches::kUseGL, use_gl); - } - if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) { - command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "true"); - switch (gpu_switching_) { - case GPU_SWITCHING_OPTION_FORCE_DISCRETE: - command_line->AppendSwitchASCII(switches::kGpuSwitching, - switches::kGpuSwitchingOptionNameForceDiscrete); - break; - case GPU_SWITCHING_OPTION_FORCE_INTEGRATED: - command_line->AppendSwitchASCII(switches::kGpuSwitching, - switches::kGpuSwitchingOptionNameForceIntegrated); - break; - case GPU_SWITCHING_OPTION_AUTOMATIC: - case GPU_SWITCHING_OPTION_UNKNOWN: - break; - } - } else { - command_line->AppendSwitchASCII(switches::kSupportsDualGpus, "false"); - } - - if (!swiftshader_path.empty()) - command_line->AppendSwitchPath(switches::kSwiftShaderPath, - swiftshader_path); - - if (!gpu_driver_bugs_.empty()) { - command_line->AppendSwitchASCII(switches::kGpuDriverBugWorkarounds, - IntSetToString(gpu_driver_bugs_)); - } - -#if defined(OS_WIN) - // DisplayLink 7.1 and earlier can cause the GPU process to crash on startup. - // http://crbug.com/177611 - // Thinkpad USB Port Replicator driver causes GPU process to crash when the - // sandbox is enabled. http://crbug.com/181665. - if ((gpu_info_.display_link_version.IsValid() - && gpu_info_.display_link_version.IsOlderThan("7.2")) || - gpu_info_.lenovo_dcute) { - command_line->AppendSwitch(switches::kReduceGpuSandbox); - } -#endif - - if (gpu_info_.optimus) - command_line->AppendSwitch(switches::kReduceGpuSandbox); - if (gpu_info_.amd_switchable) { - // The image transport surface currently doesn't work with AMD Dynamic - // Switchable graphics. - command_line->AppendSwitch(switches::kReduceGpuSandbox); - command_line->AppendSwitch(switches::kDisableImageTransportSurface); - } - // Pass GPU and driver information to GPU process. We try to avoid full GPU - // info collection at GPU process startup, but we need gpu vendor_id, - // device_id, driver_vendor, driver_version for deciding whether we need to - // collect full info (on Linux) and for crash reporting purpose. - command_line->AppendSwitchASCII(switches::kGpuVendorID, - base::StringPrintf("0x%04x", gpu_info_.gpu.vendor_id)); - command_line->AppendSwitchASCII(switches::kGpuDeviceID, - base::StringPrintf("0x%04x", gpu_info_.gpu.device_id)); - command_line->AppendSwitchASCII(switches::kGpuDriverVendor, - gpu_info_.driver_vendor); - command_line->AppendSwitchASCII(switches::kGpuDriverVersion, - gpu_info_.driver_version); -} - -void GpuDataManagerImplPrivate::AppendPluginCommandLine( - CommandLine* command_line) const { - DCHECK(command_line); - -#if defined(OS_MACOSX) - // TODO(jbauman): Add proper blacklist support for core animation plugins so - // special-casing this video card won't be necessary. See - // http://crbug.com/134015 - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) || - CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableAcceleratedCompositing)) { - if (!command_line->HasSwitch( - switches::kDisableCoreAnimationPlugins)) - command_line->AppendSwitch( - switches::kDisableCoreAnimationPlugins); - } -#endif -} - -void GpuDataManagerImplPrivate::UpdateRendererWebPrefs( - WebPreferences* prefs) const { - DCHECK(prefs); - - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING)) - prefs->accelerated_compositing_enabled = false; - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_WEBGL)) - prefs->experimental_webgl_enabled = false; - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_FLASH3D)) - prefs->flash_3d_enabled = false; - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_FLASH_STAGE3D)) { - prefs->flash_stage3d_enabled = false; - prefs->flash_stage3d_baseline_enabled = false; - } - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE)) - prefs->flash_stage3d_baseline_enabled = false; - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)) - prefs->accelerated_2d_canvas_enabled = false; - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_MULTISAMPLING)) - prefs->gl_multisampling_enabled = false; - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_3D_CSS)) { - prefs->accelerated_compositing_for_3d_transforms_enabled = false; - prefs->accelerated_compositing_for_animation_enabled = false; - } - if (IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_VIDEO)) - prefs->accelerated_compositing_for_video_enabled = false; - - // Accelerated video and animation are slower than regular when using - // SwiftShader. 3D CSS may also be too slow to be worthwhile. - if (ShouldUseSwiftShader()) { - prefs->accelerated_compositing_for_video_enabled = false; - prefs->accelerated_compositing_for_animation_enabled = false; - prefs->accelerated_compositing_for_3d_transforms_enabled = false; - prefs->accelerated_compositing_for_plugins_enabled = false; - } -} - -GpuSwitchingOption GpuDataManagerImplPrivate::GetGpuSwitchingOption() const { - if (!ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) - return GPU_SWITCHING_OPTION_UNKNOWN; - return gpu_switching_; -} - -void GpuDataManagerImplPrivate::DisableHardwareAcceleration() { - card_blacklisted_ = true; - - for (int i = 0; i < NUMBER_OF_GPU_FEATURE_TYPES; ++i) - blacklisted_features_.insert(i); - - EnableSwiftShaderIfNecessary(); - NotifyGpuInfoUpdate(); -} - -std::string GpuDataManagerImplPrivate::GetBlacklistVersion() const { - if (gpu_blacklist_) - return gpu_blacklist_->version(); - return "0"; -} - -base::ListValue* GpuDataManagerImplPrivate::GetBlacklistReasons() const { - ListValue* reasons = new ListValue(); - if (gpu_blacklist_) - gpu_blacklist_->GetReasons(reasons); - return reasons; -} - -void GpuDataManagerImplPrivate::AddLogMessage( - int level, const std::string& header, const std::string& message) { - DictionaryValue* dict = new DictionaryValue(); - dict->SetInteger("level", level); - dict->SetString("header", header); - dict->SetString("message", message); - log_messages_.Append(dict); -} - -void GpuDataManagerImplPrivate::ProcessCrashed( - base::TerminationStatus exit_code) { - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { - // Unretained is ok, because it's posted to UI thread, the thread - // where the singleton GpuDataManagerImpl lives until the end. - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&GpuDataManagerImpl::ProcessCrashed, - base::Unretained(owner_), - exit_code)); - return; - } - { - GpuDataManagerImpl::UnlockedSession session(owner_); - observer_list_->Notify( - &GpuDataManagerObserver::OnGpuProcessCrashed, exit_code); - } -} - -base::ListValue* GpuDataManagerImplPrivate::GetLogMessages() const { - base::ListValue* value; - value = log_messages_.DeepCopy(); - return value; -} - -void GpuDataManagerImplPrivate::HandleGpuSwitch() { - GpuDataManagerImpl::UnlockedSession session(owner_); - observer_list_->Notify(&GpuDataManagerObserver::OnGpuSwitching); -} - -#if defined(OS_WIN) -bool GpuDataManagerImplPrivate::IsUsingAcceleratedSurface() const { - if (base::win::GetVersion() < base::win::VERSION_VISTA) - return false; - - if (gpu_info_.amd_switchable) - return false; - if (use_swiftshader_) - return false; - CommandLine* command_line = CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kDisableImageTransportSurface)) - return false; - return !IsFeatureBlacklisted(GPU_FEATURE_TYPE_TEXTURE_SHARING); -} -#endif - -void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIs( - const GURL& url, GpuDataManagerImpl::DomainGuilt guilt) { - BlockDomainFrom3DAPIsAtTime(url, guilt, base::Time::Now()); -} - -bool GpuDataManagerImplPrivate::Are3DAPIsBlocked(const GURL& url, - int render_process_id, - int render_view_id, - ThreeDAPIType requester) { - bool blocked = Are3DAPIsBlockedAtTime(url, base::Time::Now()) != - GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED; - if (blocked) { - // Unretained is ok, because it's posted to UI thread, the thread - // where the singleton GpuDataManagerImpl lives until the end. - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&GpuDataManagerImpl::Notify3DAPIBlocked, - base::Unretained(owner_), url, render_process_id, - render_view_id, requester)); - } - - return blocked; -} - -void GpuDataManagerImplPrivate::DisableDomainBlockingFor3DAPIsForTesting() { - domain_blocking_enabled_ = false; -} - -// static -GpuDataManagerImplPrivate* GpuDataManagerImplPrivate::Create( - GpuDataManagerImpl* owner) { - return new GpuDataManagerImplPrivate(owner); -} - -GpuDataManagerImplPrivate::GpuDataManagerImplPrivate( - GpuDataManagerImpl* owner) - : complete_gpu_info_already_requested_(false), - gpu_switching_(GPU_SWITCHING_OPTION_AUTOMATIC), - observer_list_(new GpuDataManagerObserverList), - use_swiftshader_(false), - card_blacklisted_(false), - update_histograms_(true), - window_count_(0), - domain_blocking_enabled_(true), - owner_(owner) { - DCHECK(owner_); - CommandLine* command_line = CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kDisableAcceleratedCompositing)) { - command_line->AppendSwitch(switches::kDisableAccelerated2dCanvas); - command_line->AppendSwitch(switches::kDisableAcceleratedLayers); - } - if (command_line->HasSwitch(switches::kDisableGpu)) - DisableHardwareAcceleration(); - if (command_line->HasSwitch(switches::kGpuSwitching)) { - std::string option_string = command_line->GetSwitchValueASCII( - switches::kGpuSwitching); - GpuSwitchingOption option = StringToGpuSwitchingOption(option_string); - if (option != GPU_SWITCHING_OPTION_UNKNOWN) - gpu_switching_ = option; - } - -#if defined(OS_MACOSX) - CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback, owner_); -#endif // OS_MACOSX -} - -GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() { -#if defined(OS_MACOSX) - CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback, owner_); -#endif -} - -void GpuDataManagerImplPrivate::InitializeImpl( - const std::string& gpu_blacklist_json, - const std::string& gpu_switching_list_json, - const std::string& gpu_driver_bug_list_json, - const GPUInfo& gpu_info) { - std::string browser_version_string = ProcessVersionString( - GetContentClient()->GetProduct()); - CHECK(!browser_version_string.empty()); - - if (!gpu_blacklist_json.empty()) { - gpu_blacklist_.reset(GpuBlacklist::Create()); - gpu_blacklist_->LoadList( - browser_version_string, gpu_blacklist_json, - GpuControlList::kCurrentOsOnly); - } - if (!gpu_switching_list_json.empty()) { - gpu_switching_list_.reset(GpuSwitchingList::Create()); - gpu_switching_list_->LoadList( - browser_version_string, gpu_switching_list_json, - GpuControlList::kCurrentOsOnly); - } - if (!gpu_driver_bug_list_json.empty()) { - gpu_driver_bug_list_.reset(GpuDriverBugList::Create()); - gpu_driver_bug_list_->LoadList( - browser_version_string, gpu_driver_bug_list_json, - GpuControlList::kCurrentOsOnly); - } - - gpu_info_ = gpu_info; - UpdateGpuInfo(gpu_info); - UpdateGpuSwitchingManager(gpu_info); - UpdatePreliminaryBlacklistedFeatures(); -} - -void GpuDataManagerImplPrivate::UpdateBlacklistedFeatures( - const std::set<int>& features) { - CommandLine* command_line = CommandLine::ForCurrentProcess(); - blacklisted_features_ = features; - - // Force disable using the GPU for these features, even if they would - // otherwise be allowed. - if (card_blacklisted_ || - command_line->HasSwitch(switches::kBlacklistAcceleratedCompositing)) { - blacklisted_features_.insert(GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING); - } - if (card_blacklisted_ || - command_line->HasSwitch(switches::kBlacklistWebGL)) { - blacklisted_features_.insert(GPU_FEATURE_TYPE_WEBGL); - } - - EnableSwiftShaderIfNecessary(); -} - -void GpuDataManagerImplPrivate::UpdatePreliminaryBlacklistedFeatures() { - preliminary_blacklisted_features_ = blacklisted_features_; -} - -void GpuDataManagerImplPrivate::UpdateGpuSwitchingManager( - const GPUInfo& gpu_info) { - ui::GpuSwitchingManager::GetInstance()->SetGpuCount( - gpu_info.secondary_gpus.size() + 1); - - if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) { - switch (gpu_switching_) { - case GPU_SWITCHING_OPTION_FORCE_DISCRETE: - ui::GpuSwitchingManager::GetInstance()->ForceUseOfDiscreteGpu(); - break; - case GPU_SWITCHING_OPTION_FORCE_INTEGRATED: - ui::GpuSwitchingManager::GetInstance()->ForceUseOfIntegratedGpu(); - break; - case GPU_SWITCHING_OPTION_AUTOMATIC: - case GPU_SWITCHING_OPTION_UNKNOWN: - break; - } - } -} - -void GpuDataManagerImplPrivate::NotifyGpuInfoUpdate() { - observer_list_->Notify(&GpuDataManagerObserver::OnGpuInfoUpdate); -} - -void GpuDataManagerImplPrivate::EnableSwiftShaderIfNecessary() { - if (!GpuAccessAllowed(NULL) || - blacklisted_features_.count(GPU_FEATURE_TYPE_WEBGL)) { - if (!swiftshader_path_.empty() && - !CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableSoftwareRasterizer)) - use_swiftshader_ = true; - } -} - -std::string GpuDataManagerImplPrivate::GetDomainFromURL( - const GURL& url) const { - // For the moment, we just use the host, or its IP address, as the - // entry in the set, rather than trying to figure out the top-level - // domain. This does mean that a.foo.com and b.foo.com will be - // treated independently in the blocking of a given domain, but it - // would require a third-party library to reliably figure out the - // top-level domain from a URL. - if (!url.has_host()) { - return std::string(); - } - - return url.host(); -} - -void GpuDataManagerImplPrivate::BlockDomainFrom3DAPIsAtTime( - const GURL& url, - GpuDataManagerImpl::DomainGuilt guilt, - base::Time at_time) { - if (!domain_blocking_enabled_) - return; - - std::string domain = GetDomainFromURL(url); - - DomainBlockEntry& entry = blocked_domains_[domain]; - entry.last_guilt = guilt; - timestamps_of_gpu_resets_.push_back(at_time); -} - -GpuDataManagerImpl::DomainBlockStatus -GpuDataManagerImplPrivate::Are3DAPIsBlockedAtTime( - const GURL& url, base::Time at_time) const { - if (!domain_blocking_enabled_) - return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED; - - // Note: adjusting the policies in this code will almost certainly - // require adjusting the associated unit tests. - std::string domain = GetDomainFromURL(url); - - DomainBlockMap::const_iterator iter = blocked_domains_.find(domain); - if (iter != blocked_domains_.end()) { - // Err on the side of caution, and assume that if a particular - // domain shows up in the block map, it's there for a good - // reason and don't let its presence there automatically expire. - - UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs", - BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED, - BLOCK_STATUS_MAX); - - return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED; - } - - // Look at the timestamps of the recent GPU resets to see if there are - // enough within the threshold which would cause us to blacklist all - // domains. This doesn't need to be overly precise -- if time goes - // backward due to a system clock adjustment, that's fine. - // - // TODO(kbr): make this pay attention to the TDR thresholds in the - // Windows registry, but make sure it continues to be testable. - { - std::list<base::Time>::iterator iter = timestamps_of_gpu_resets_.begin(); - int num_resets_within_timeframe = 0; - while (iter != timestamps_of_gpu_resets_.end()) { - base::Time time = *iter; - base::TimeDelta delta_t = at_time - time; - - // If this entry has "expired", just remove it. - if (delta_t.InMilliseconds() > kBlockAllDomainsMs) { - iter = timestamps_of_gpu_resets_.erase(iter); - continue; - } - - ++num_resets_within_timeframe; - ++iter; - } - - if (num_resets_within_timeframe >= kNumResetsWithinDuration) { - UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs", - BLOCK_STATUS_ALL_DOMAINS_BLOCKED, - BLOCK_STATUS_MAX); - - return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED; - } - } - - UMA_HISTOGRAM_ENUMERATION("GPU.BlockStatusForClient3DAPIs", - BLOCK_STATUS_NOT_BLOCKED, - BLOCK_STATUS_MAX); - - return GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED; -} - -int64 GpuDataManagerImplPrivate::GetBlockAllDomainsDurationInMs() const { - return kBlockAllDomainsMs; -} - -void GpuDataManagerImplPrivate::Notify3DAPIBlocked(const GURL& url, - int render_process_id, - int render_view_id, - ThreeDAPIType requester) { - GpuDataManagerImpl::UnlockedSession session(owner_); - observer_list_->Notify(&GpuDataManagerObserver::DidBlock3DAPIs, - url, render_process_id, render_view_id, requester); -} - -} // namespace content - diff --git a/content/browser/gpu/gpu_data_manager_impl_private.h b/content/browser/gpu/gpu_data_manager_impl_private.h deleted file mode 100644 index fb91a46..0000000 --- a/content/browser/gpu/gpu_data_manager_impl_private.h +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_GPU_GPU_DATA_MANAGER_IMPL_PRIVATE_H_ -#define CONTENT_BROWSER_GPU_GPU_DATA_MANAGER_IMPL_PRIVATE_H_ - -#include <list> -#include <map> -#include <set> -#include <string> - -#include "base/memory/ref_counted.h" -#include "base/memory/singleton.h" -#include "base/observer_list_threadsafe.h" -#include "content/browser/gpu/gpu_blacklist.h" -#include "content/browser/gpu/gpu_data_manager_impl.h" -#include "content/browser/gpu/gpu_driver_bug_list.h" -#include "content/browser/gpu/gpu_switching_list.h" - -namespace content { - -class CONTENT_EXPORT GpuDataManagerImplPrivate { - public: - static GpuDataManagerImplPrivate* Create(GpuDataManagerImpl* owner); - - void InitializeForTesting( - const std::string& gpu_blacklist_json, - const GPUInfo& gpu_info); - bool IsFeatureBlacklisted(int feature) const; - GPUInfo GetGPUInfo() const; - void GetGpuProcessHandles( - const GpuDataManager::GetGpuProcessHandlesCallback& callback) const; - bool GpuAccessAllowed(std::string* reason) const; - void RequestCompleteGpuInfoIfNeeded(); - bool IsCompleteGpuInfoAvailable() const; - void RequestVideoMemoryUsageStatsUpdate() const; - bool ShouldUseSwiftShader() const; - void RegisterSwiftShaderPath(const base::FilePath& path); - void AddObserver(GpuDataManagerObserver* observer); - void RemoveObserver(GpuDataManagerObserver* observer); - void UnblockDomainFrom3DAPIs(const GURL& url); - void DisableGpuWatchdog(); - void SetGLStrings(const std::string& gl_vendor, - const std::string& gl_renderer, - const std::string& gl_version); - void GetGLStrings(std::string* gl_vendor, - std::string* gl_renderer, - std::string* gl_version); - void DisableHardwareAcceleration(); - - void Initialize(); - - void UpdateGpuInfo(const GPUInfo& gpu_info); - - void UpdateVideoMemoryUsageStats( - const GPUVideoMemoryUsageStats& video_memory_usage_stats); - - void AppendRendererCommandLine(CommandLine* command_line) const; - - void AppendGpuCommandLine(CommandLine* command_line) const; - - void AppendPluginCommandLine(CommandLine* command_line) const; - - void UpdateRendererWebPrefs(WebPreferences* prefs) const; - - GpuSwitchingOption GetGpuSwitchingOption() const; - - std::string GetBlacklistVersion() const; - - base::ListValue* GetBlacklistReasons() const; - - void AddLogMessage(int level, - const std::string& header, - const std::string& message); - - void ProcessCrashed(base::TerminationStatus exit_code); - - base::ListValue* GetLogMessages() const; - - void HandleGpuSwitch(); - -#if defined(OS_WIN) - // Is the GPU process using the accelerated surface to present, instead of - // presenting by itself. - bool IsUsingAcceleratedSurface() const; -#endif - - void BlockDomainFrom3DAPIs( - const GURL& url, GpuDataManagerImpl::DomainGuilt guilt); - bool Are3DAPIsBlocked(const GURL& url, - int render_process_id, - int render_view_id, - ThreeDAPIType requester); - - void DisableDomainBlockingFor3DAPIsForTesting(); - - void Notify3DAPIBlocked(const GURL& url, - int render_process_id, - int render_view_id, - ThreeDAPIType requester); - - size_t GetBlacklistedFeatureCount() const; - - virtual ~GpuDataManagerImplPrivate(); - - private: - friend class GpuDataManagerImplPrivateTest; - - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - GpuSideBlacklisting); - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - GpuSideExceptions); - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - DisableHardwareAcceleration); - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - SwiftShaderRendering); - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - SwiftShaderRendering2); - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - GpuInfoUpdate); - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - NoGpuInfoUpdateWithSwiftShader); - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - GPUVideoMemoryUsageStatsUpdate); - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - BlockAllDomainsFrom3DAPIs); - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - UnblockGuiltyDomainFrom3DAPIs); - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - UnblockDomainOfUnknownGuiltFrom3DAPIs); - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - UnblockOtherDomainFrom3DAPIs); - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - UnblockThisDomainFrom3DAPIs); -#if defined(OS_LINUX) - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - SetGLStrings); - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - SetGLStringsNoEffects); -#endif - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - GpuDriverBugListSingle); - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - GpuDriverBugListMultiple); - FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest, - BlacklistAllFeatures); - - struct DomainBlockEntry { - GpuDataManagerImpl::DomainGuilt last_guilt; - }; - - typedef std::map<std::string, DomainBlockEntry> DomainBlockMap; - - typedef ObserverListThreadSafe<GpuDataManagerObserver> - GpuDataManagerObserverList; - - explicit GpuDataManagerImplPrivate(GpuDataManagerImpl* owner); - - void InitializeImpl(const std::string& gpu_blacklist_json, - const std::string& gpu_switching_list_json, - const std::string& gpu_driver_bug_list_json, - const GPUInfo& gpu_info); - - void UpdateBlacklistedFeatures(const std::set<int>& features); - - // This should only be called once at initialization time, when preliminary - // gpu info is collected. - void UpdatePreliminaryBlacklistedFeatures(); - - // Update the GPU switching status. - // This should only be called once at initialization time. - void UpdateGpuSwitchingManager(const GPUInfo& gpu_info); - - // Notify all observers whenever there is a GPU info update. - void NotifyGpuInfoUpdate(); - - // Try to switch to SwiftShader rendering, if possible and necessary. - void EnableSwiftShaderIfNecessary(); - - // Helper to extract the domain from a given URL. - std::string GetDomainFromURL(const GURL& url) const; - - // Implementation functions for blocking of 3D graphics APIs, used - // for unit testing. - void BlockDomainFrom3DAPIsAtTime(const GURL& url, - GpuDataManagerImpl::DomainGuilt guilt, - base::Time at_time); - GpuDataManagerImpl::DomainBlockStatus Are3DAPIsBlockedAtTime( - const GURL& url, base::Time at_time) const; - int64 GetBlockAllDomainsDurationInMs() const; - - bool complete_gpu_info_already_requested_; - - std::set<int> blacklisted_features_; - std::set<int> preliminary_blacklisted_features_; - - GpuSwitchingOption gpu_switching_; - - std::set<int> gpu_driver_bugs_; - - GPUInfo gpu_info_; - - scoped_ptr<GpuBlacklist> gpu_blacklist_; - scoped_ptr<GpuSwitchingList> gpu_switching_list_; - scoped_ptr<GpuDriverBugList> gpu_driver_bug_list_; - - const scoped_refptr<GpuDataManagerObserverList> observer_list_; - - ListValue log_messages_; - - bool use_swiftshader_; - - base::FilePath swiftshader_path_; - - // Current card force-blacklisted due to GPU crashes, or disabled through - // the --disable-gpu commandline switch. - bool card_blacklisted_; - - // We disable histogram stuff in testing, especially in unit tests because - // they cause random failures. - bool update_histograms_; - - // Number of currently open windows, to be used in gpu memory allocation. - int window_count_; - - DomainBlockMap blocked_domains_; - mutable std::list<base::Time> timestamps_of_gpu_resets_; - bool domain_blocking_enabled_; - - GpuDataManagerImpl* owner_; - - DISALLOW_COPY_AND_ASSIGN(GpuDataManagerImplPrivate); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_GPU_GPU_DATA_MANAGER_IMPL_PRIVATE_H_ - diff --git a/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc b/content/browser/gpu/gpu_data_manager_impl_unittest.cc index 21d2c06..7d15bba 100644 --- a/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc +++ b/content/browser/gpu/gpu_data_manager_impl_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,7 +6,7 @@ #include "base/message_loop.h" #include "base/run_loop.h" #include "base/time.h" -#include "content/browser/gpu/gpu_data_manager_impl_private.h" +#include "content/browser/gpu/gpu_data_manager_impl.h" #include "content/public/browser/gpu_data_manager_observer.h" #include "content/public/common/gpu_feature_type.h" #include "content/public/common/gpu_info.h" @@ -60,64 +60,40 @@ static GURL GetDomain2ForTesting() { } // namespace anonymous -class GpuDataManagerImplPrivateTest : public testing::Test { +class GpuDataManagerImplTest : public testing::Test { public: - GpuDataManagerImplPrivateTest() { } + GpuDataManagerImplTest() { } - virtual ~GpuDataManagerImplPrivateTest() { } + virtual ~GpuDataManagerImplTest() { } protected: // scoped_ptr doesn't work with GpuDataManagerImpl because its - // destructor is private. GpuDataManagerImplPrivateTest is however a friend + // destructor is private. GpuDataManagerImplTest is however a friend // so we can make a little helper class here. class ScopedGpuDataManagerImpl { public: - ScopedGpuDataManagerImpl() : impl_(new GpuDataManagerImpl()) { - ASSERT_TRUE(impl_); - ASSERT_TRUE(impl_->private_.get()); - } + ScopedGpuDataManagerImpl() : impl_(new GpuDataManagerImpl()) {} ~ScopedGpuDataManagerImpl() { delete impl_; } GpuDataManagerImpl* get() const { return impl_; } - GpuDataManagerImpl* operator->() const { return impl_; } + // Small violation of C++ style guide to avoid polluting several + // tests with get() calls. + operator GpuDataManagerImpl*() { return impl_; } private: GpuDataManagerImpl* impl_; DISALLOW_COPY_AND_ASSIGN(ScopedGpuDataManagerImpl); }; - // We want to test the code path where GpuDataManagerImplPrivate is created - // in the GpuDataManagerImpl constructor. - class ScopedGpuDataManagerImplPrivate { - public: - ScopedGpuDataManagerImplPrivate() : impl_(new GpuDataManagerImpl()) { - ASSERT_TRUE(impl_); - ASSERT_TRUE(impl_->private_.get()); - } - ~ScopedGpuDataManagerImplPrivate() { delete impl_; } - - GpuDataManagerImplPrivate* get() const { - return impl_->private_.get(); - } - - GpuDataManagerImplPrivate* operator->() const { - return impl_->private_.get(); - } - - private: - GpuDataManagerImpl* impl_; - DISALLOW_COPY_AND_ASSIGN(ScopedGpuDataManagerImplPrivate); - }; - virtual void SetUp() { } virtual void TearDown() { } - base::Time JustBeforeExpiration(const GpuDataManagerImplPrivate* manager); - base::Time JustAfterExpiration(const GpuDataManagerImplPrivate* manager); + base::Time JustBeforeExpiration(GpuDataManagerImpl* manager); + base::Time JustAfterExpiration(GpuDataManagerImpl* manager); void TestBlockingDomainFrom3DAPIs( GpuDataManagerImpl::DomainGuilt guilt_level); void TestUnblockingDomainFrom3DAPIs( @@ -129,12 +105,13 @@ class GpuDataManagerImplPrivateTest : public testing::Test { // We use new method instead of GetInstance() method because we want // each test to be independent of each other. -TEST_F(GpuDataManagerImplPrivateTest, GpuSideBlacklisting) { +TEST_F(GpuDataManagerImplTest, GpuSideBlacklisting) { // If a feature is allowed in preliminary step (browser side), but // disabled when GPU process launches and collects full GPU info, // it's too late to let renderer know, so we basically block all GPU // access, to be on the safe side. - ScopedGpuDataManagerImplPrivate manager; + ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); std::string reason; EXPECT_TRUE(manager->GpuAccessAllowed(&reason)); @@ -186,8 +163,9 @@ TEST_F(GpuDataManagerImplPrivateTest, GpuSideBlacklisting) { GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)); } -TEST_F(GpuDataManagerImplPrivateTest, GpuSideExceptions) { - ScopedGpuDataManagerImplPrivate manager; +TEST_F(GpuDataManagerImplTest, GpuSideExceptions) { + ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); @@ -228,8 +206,9 @@ TEST_F(GpuDataManagerImplPrivateTest, GpuSideExceptions) { EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); } -TEST_F(GpuDataManagerImplPrivateTest, DisableHardwareAcceleration) { - ScopedGpuDataManagerImplPrivate manager; +TEST_F(GpuDataManagerImplTest, DisableHardwareAcceleration) { + ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); std::string reason; EXPECT_TRUE(manager->GpuAccessAllowed(&reason)); @@ -242,9 +221,10 @@ TEST_F(GpuDataManagerImplPrivateTest, DisableHardwareAcceleration) { manager->GetBlacklistedFeatureCount()); } -TEST_F(GpuDataManagerImplPrivateTest, SwiftShaderRendering) { +TEST_F(GpuDataManagerImplTest, SwiftShaderRendering) { // Blacklist, then register SwiftShader. - ScopedGpuDataManagerImplPrivate manager; + ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); EXPECT_FALSE(manager->ShouldUseSwiftShader()); @@ -264,9 +244,10 @@ TEST_F(GpuDataManagerImplPrivateTest, SwiftShaderRendering) { manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)); } -TEST_F(GpuDataManagerImplPrivateTest, SwiftShaderRendering2) { +TEST_F(GpuDataManagerImplTest, SwiftShaderRendering2) { // Register SwiftShader, then blacklist. - ScopedGpuDataManagerImplPrivate manager; + ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); EXPECT_FALSE(manager->ShouldUseSwiftShader()); @@ -285,8 +266,9 @@ TEST_F(GpuDataManagerImplPrivateTest, SwiftShaderRendering2) { manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)); } -TEST_F(GpuDataManagerImplPrivateTest, GpuInfoUpdate) { +TEST_F(GpuDataManagerImplTest, GpuInfoUpdate) { ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); TestObserver observer; manager->AddObserver(&observer); @@ -306,8 +288,9 @@ TEST_F(GpuDataManagerImplPrivateTest, GpuInfoUpdate) { EXPECT_TRUE(observer.gpu_info_updated()); } -TEST_F(GpuDataManagerImplPrivateTest, NoGpuInfoUpdateWithSwiftShader) { +TEST_F(GpuDataManagerImplTest, NoGpuInfoUpdateWithSwiftShader) { ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); manager->DisableHardwareAcceleration(); const base::FilePath test_path(FILE_PATH_LITERAL("AnyPath")); @@ -337,8 +320,9 @@ TEST_F(GpuDataManagerImplPrivateTest, NoGpuInfoUpdateWithSwiftShader) { EXPECT_FALSE(observer.gpu_info_updated()); } -TEST_F(GpuDataManagerImplPrivateTest, GPUVideoMemoryUsageStatsUpdate) { +TEST_F(GpuDataManagerImplTest, GPUVideoMemoryUsageStatsUpdate) { ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); TestObserver observer; manager->AddObserver(&observer); @@ -358,43 +342,45 @@ TEST_F(GpuDataManagerImplPrivateTest, GPUVideoMemoryUsageStatsUpdate) { EXPECT_TRUE(observer.video_memory_usage_stats_updated()); } -base::Time GpuDataManagerImplPrivateTest::JustBeforeExpiration( - const GpuDataManagerImplPrivate* manager) { +base::Time GpuDataManagerImplTest::JustBeforeExpiration( + GpuDataManagerImpl* manager) { return GetTimeForTesting() + base::TimeDelta::FromMilliseconds( manager->GetBlockAllDomainsDurationInMs()) - base::TimeDelta::FromMilliseconds(3); } -base::Time GpuDataManagerImplPrivateTest::JustAfterExpiration( - const GpuDataManagerImplPrivate* manager) { +base::Time GpuDataManagerImplTest::JustAfterExpiration( + GpuDataManagerImpl* manager) { return GetTimeForTesting() + base::TimeDelta::FromMilliseconds( manager->GetBlockAllDomainsDurationInMs()) + base::TimeDelta::FromMilliseconds(3); } -void GpuDataManagerImplPrivateTest::TestBlockingDomainFrom3DAPIs( +void GpuDataManagerImplTest::TestBlockingDomainFrom3DAPIs( GpuDataManagerImpl::DomainGuilt guilt_level) { - ScopedGpuDataManagerImplPrivate manager; + ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(), - guilt_level, - GetTimeForTesting()); + guilt_level, + GetTimeForTesting()); // This domain should be blocked no matter what. EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED, manager->Are3DAPIsBlockedAtTime(GetDomain1ForTesting(), - GetTimeForTesting())); + GetTimeForTesting())); EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED, - manager->Are3DAPIsBlockedAtTime( - GetDomain1ForTesting(), JustBeforeExpiration(manager.get()))); + manager->Are3DAPIsBlockedAtTime(GetDomain1ForTesting(), + JustBeforeExpiration(manager))); EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED, - manager->Are3DAPIsBlockedAtTime( - GetDomain1ForTesting(), JustAfterExpiration(manager.get()))); + manager->Are3DAPIsBlockedAtTime(GetDomain1ForTesting(), + JustAfterExpiration(manager))); } -void GpuDataManagerImplPrivateTest::TestUnblockingDomainFrom3DAPIs( +void GpuDataManagerImplTest::TestUnblockingDomainFrom3DAPIs( GpuDataManagerImpl::DomainGuilt guilt_level) { - ScopedGpuDataManagerImplPrivate manager; + ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(), guilt_level, @@ -406,23 +392,24 @@ void GpuDataManagerImplPrivateTest::TestUnblockingDomainFrom3DAPIs( manager->Are3DAPIsBlockedAtTime(GetDomain1ForTesting(), GetTimeForTesting())); EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED, - manager->Are3DAPIsBlockedAtTime( - GetDomain1ForTesting(), JustBeforeExpiration(manager.get()))); + manager->Are3DAPIsBlockedAtTime(GetDomain1ForTesting(), + JustBeforeExpiration(manager))); EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED, - manager->Are3DAPIsBlockedAtTime( - GetDomain1ForTesting(), JustAfterExpiration(manager.get()))); + manager->Are3DAPIsBlockedAtTime(GetDomain1ForTesting(), + JustAfterExpiration(manager))); } -TEST_F(GpuDataManagerImplPrivateTest, BlockGuiltyDomainFrom3DAPIs) { +TEST_F(GpuDataManagerImplTest, BlockGuiltyDomainFrom3DAPIs) { TestBlockingDomainFrom3DAPIs(GpuDataManagerImpl::DOMAIN_GUILT_KNOWN); } -TEST_F(GpuDataManagerImplPrivateTest, BlockDomainOfUnknownGuiltFrom3DAPIs) { +TEST_F(GpuDataManagerImplTest, BlockDomainOfUnknownGuiltFrom3DAPIs) { TestBlockingDomainFrom3DAPIs(GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN); } -TEST_F(GpuDataManagerImplPrivateTest, BlockAllDomainsFrom3DAPIs) { - ScopedGpuDataManagerImplPrivate manager; +TEST_F(GpuDataManagerImplTest, BlockAllDomainsFrom3DAPIs) { + ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(), GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN, @@ -430,23 +417,24 @@ TEST_F(GpuDataManagerImplPrivateTest, BlockAllDomainsFrom3DAPIs) { // Blocking of other domains should expire. EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_ALL_DOMAINS_BLOCKED, - manager->Are3DAPIsBlockedAtTime( - GetDomain2ForTesting(), JustBeforeExpiration(manager.get()))); + manager->Are3DAPIsBlockedAtTime(GetDomain2ForTesting(), + JustBeforeExpiration(manager))); EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED, - manager->Are3DAPIsBlockedAtTime( - GetDomain2ForTesting(), JustAfterExpiration(manager.get()))); + manager->Are3DAPIsBlockedAtTime(GetDomain2ForTesting(), + JustAfterExpiration(manager))); } -TEST_F(GpuDataManagerImplPrivateTest, UnblockGuiltyDomainFrom3DAPIs) { +TEST_F(GpuDataManagerImplTest, UnblockGuiltyDomainFrom3DAPIs) { TestUnblockingDomainFrom3DAPIs(GpuDataManagerImpl::DOMAIN_GUILT_KNOWN); } -TEST_F(GpuDataManagerImplPrivateTest, UnblockDomainOfUnknownGuiltFrom3DAPIs) { +TEST_F(GpuDataManagerImplTest, UnblockDomainOfUnknownGuiltFrom3DAPIs) { TestUnblockingDomainFrom3DAPIs(GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN); } -TEST_F(GpuDataManagerImplPrivateTest, UnblockOtherDomainFrom3DAPIs) { - ScopedGpuDataManagerImplPrivate manager; +TEST_F(GpuDataManagerImplTest, UnblockOtherDomainFrom3DAPIs) { + ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(), GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN, @@ -455,17 +443,18 @@ TEST_F(GpuDataManagerImplPrivateTest, UnblockOtherDomainFrom3DAPIs) { manager->UnblockDomainFrom3DAPIs(GetDomain2ForTesting()); EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED, - manager->Are3DAPIsBlockedAtTime( - GetDomain2ForTesting(), JustBeforeExpiration(manager.get()))); + manager->Are3DAPIsBlockedAtTime(GetDomain2ForTesting(), + JustBeforeExpiration(manager))); // The original domain should still be blocked. EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_BLOCKED, - manager->Are3DAPIsBlockedAtTime( - GetDomain1ForTesting(), JustBeforeExpiration(manager.get()))); + manager->Are3DAPIsBlockedAtTime(GetDomain1ForTesting(), + JustBeforeExpiration(manager))); } -TEST_F(GpuDataManagerImplPrivateTest, UnblockThisDomainFrom3DAPIs) { - ScopedGpuDataManagerImplPrivate manager; +TEST_F(GpuDataManagerImplTest, UnblockThisDomainFrom3DAPIs) { + ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); manager->BlockDomainFrom3DAPIsAtTime(GetDomain1ForTesting(), GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN, @@ -476,17 +465,18 @@ TEST_F(GpuDataManagerImplPrivateTest, UnblockThisDomainFrom3DAPIs) { // This behavior is debatable. Perhaps the GPU reset caused by // domain 1 should still cause other domains to be blocked. EXPECT_EQ(GpuDataManagerImpl::DOMAIN_BLOCK_STATUS_NOT_BLOCKED, - manager->Are3DAPIsBlockedAtTime( - GetDomain2ForTesting(), JustBeforeExpiration(manager.get()))); + manager->Are3DAPIsBlockedAtTime(GetDomain2ForTesting(), + JustBeforeExpiration(manager))); } #if defined(OS_LINUX) -TEST_F(GpuDataManagerImplPrivateTest, SetGLStrings) { +TEST_F(GpuDataManagerImplTest, SetGLStrings) { const char* kGLVendorMesa = "Tungsten Graphics, Inc"; const char* kGLRendererMesa = "Mesa DRI Intel(R) G41"; const char* kGLVersionMesa801 = "2.1 Mesa 8.0.1-DEVEL"; - ScopedGpuDataManagerImplPrivate manager; + ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); @@ -533,13 +523,14 @@ TEST_F(GpuDataManagerImplPrivateTest, SetGLStrings) { EXPECT_TRUE(manager->IsFeatureBlacklisted(GPU_FEATURE_TYPE_WEBGL)); } -TEST_F(GpuDataManagerImplPrivateTest, SetGLStringsNoEffects) { +TEST_F(GpuDataManagerImplTest, SetGLStringsNoEffects) { const char* kGLVendorMesa = "Tungsten Graphics, Inc"; const char* kGLRendererMesa = "Mesa DRI Intel(R) G41"; const char* kGLVersionMesa801 = "2.1 Mesa 8.0.1-DEVEL"; const char* kGLVersionMesa802 = "2.1 Mesa 8.0.2-DEVEL"; - ScopedGpuDataManagerImplPrivate manager; + ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); EXPECT_TRUE(manager->GpuAccessAllowed(NULL)); @@ -592,8 +583,9 @@ TEST_F(GpuDataManagerImplPrivateTest, SetGLStringsNoEffects) { } #endif // OS_LINUX -TEST_F(GpuDataManagerImplPrivateTest, GpuDriverBugListSingle) { - ScopedGpuDataManagerImplPrivate manager; +TEST_F(GpuDataManagerImplTest, GpuDriverBugListSingle) { + ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); manager->gpu_driver_bugs_.insert(5); CommandLine command_line(0, NULL); @@ -605,8 +597,9 @@ TEST_F(GpuDataManagerImplPrivateTest, GpuDriverBugListSingle) { EXPECT_STREQ("5", args.c_str()); } -TEST_F(GpuDataManagerImplPrivateTest, GpuDriverBugListMultiple) { - ScopedGpuDataManagerImplPrivate manager; +TEST_F(GpuDataManagerImplTest, GpuDriverBugListMultiple) { + ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); manager->gpu_driver_bugs_.insert(5); manager->gpu_driver_bugs_.insert(7); @@ -619,8 +612,9 @@ TEST_F(GpuDataManagerImplPrivateTest, GpuDriverBugListMultiple) { EXPECT_STREQ("5,7", args.c_str()); } -TEST_F(GpuDataManagerImplPrivateTest, BlacklistAllFeatures) { - ScopedGpuDataManagerImplPrivate manager; +TEST_F(GpuDataManagerImplTest, BlacklistAllFeatures) { + ScopedGpuDataManagerImpl manager; + ASSERT_TRUE(manager.get()); EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); std::string reason; EXPECT_TRUE(manager->GpuAccessAllowed(&reason)); diff --git a/content/browser/gpu/gpu_internals_ui.cc b/content/browser/gpu/gpu_internals_ui.cc index 6419ba8..eb7646c 100644 --- a/content/browser/gpu/gpu_internals_ui.cc +++ b/content/browser/gpu/gpu_internals_ui.cc @@ -479,7 +479,9 @@ class GpuMessageHandler // GpuDataManagerObserver implementation. virtual void OnGpuInfoUpdate() OVERRIDE; - virtual void OnGpuSwitching() OVERRIDE; + + // Gpu switch handler. + void OnGpuSwitch(); // Messages void OnBrowserBridgeInitialized(const base::ListValue* list); @@ -494,6 +496,8 @@ class GpuMessageHandler // DCHECK). bool observing_; + GpuDataManagerImpl::GpuSwitchCallback gpu_switch_callback_; + DISALLOW_COPY_AND_ASSIGN(GpuMessageHandler); }; @@ -504,11 +508,15 @@ class GpuMessageHandler //////////////////////////////////////////////////////////////////////////////// GpuMessageHandler::GpuMessageHandler() - : observing_(false) { + : observing_(false), + gpu_switch_callback_(base::Bind(&GpuMessageHandler::OnGpuSwitch, + base::Unretained(this))) { } GpuMessageHandler::~GpuMessageHandler() { GpuDataManagerImpl::GetInstance()->RemoveObserver(this); + GpuDataManagerImpl::GetInstance()->RemoveGpuSwitchCallback( + gpu_switch_callback_); } /* BrowserBridge.callAsync prepends a requestID to these messages. */ @@ -575,8 +583,11 @@ void GpuMessageHandler::OnBrowserBridgeInitialized( DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); // Watch for changes in GPUInfo - if (!observing_) + if (!observing_) { GpuDataManagerImpl::GetInstance()->AddObserver(this); + GpuDataManagerImpl::GetInstance()->AddGpuSwitchCallback( + gpu_switch_callback_); + } observing_ = true; // Tell GpuDataManager it should have full GpuInfo. If the @@ -628,7 +639,7 @@ void GpuMessageHandler::OnGpuInfoUpdate() { *(gpu_info_val.get())); } -void GpuMessageHandler::OnGpuSwitching() { +void GpuMessageHandler::OnGpuSwitch() { GpuDataManagerImpl::GetInstance()->RequestCompleteGpuInfoIfNeeded(); } diff --git a/content/content_browser.gypi b/content/content_browser.gypi index c29c3e7..0442297 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -502,8 +502,6 @@ 'browser/gpu/gpu_control_list.h', 'browser/gpu/gpu_data_manager_impl.cc', 'browser/gpu/gpu_data_manager_impl.h', - 'browser/gpu/gpu_data_manager_impl_private.cc', - 'browser/gpu/gpu_data_manager_impl_private.h', 'browser/gpu/gpu_driver_bug_list.cc', 'browser/gpu/gpu_driver_bug_list.h', 'browser/gpu/gpu_internals_ui.cc', diff --git a/content/content_tests.gypi b/content/content_tests.gypi index bb7028e..49747a0 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -296,7 +296,7 @@ 'browser/gpu/gpu_control_list_string_info_unittest.cc', 'browser/gpu/gpu_control_list_unittest.cc', 'browser/gpu/gpu_control_list_version_info_unittest.cc', - 'browser/gpu/gpu_data_manager_impl_private_unittest.cc', + 'browser/gpu/gpu_data_manager_impl_unittest.cc', 'browser/gpu/gpu_driver_bug_list_unittest.cc', 'browser/gpu/gpu_switching_list_unittest.cc', 'browser/gpu/gpu_util_unittest.cc', diff --git a/content/public/browser/gpu_data_manager_observer.h b/content/public/browser/gpu_data_manager_observer.h index 53989fe..4ed348e 100644 --- a/content/public/browser/gpu_data_manager_observer.h +++ b/content/public/browser/gpu_data_manager_observer.h @@ -35,9 +35,6 @@ class GpuDataManagerObserver { // Called for any observer when the GPU process crashed. virtual void OnGpuProcessCrashed(base::TerminationStatus exit_code) {} - // Called for any observer when the system switches to a different GPU. - virtual void OnGpuSwitching() {} - protected: virtual ~GpuDataManagerObserver() {} }; |