diff options
author | zmo@google.com <zmo@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-26 02:37:38 +0000 |
---|---|---|
committer | zmo@google.com <zmo@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-26 02:37:38 +0000 |
commit | bb4bf9d76e99ba7e1c7f4246dde03e2f9cf92227 (patch) | |
tree | 3acdd3c5c16508bed92f2749916aec15f35b6281 | |
parent | b2d08988ad842790cabeb728a34473db064a660a (diff) | |
download | chromium_src-bb4bf9d76e99ba7e1c7f4246dde03e2f9cf92227.zip chromium_src-bb4bf9d76e99ba7e1c7f4246dde03e2f9cf92227.tar.gz chromium_src-bb4bf9d76e99ba7e1c7f4246dde03e2f9cf92227.tar.bz2 |
With this CL, GPU blacklist auto update from the web is implemented. This allows us to blacklist bad GPU/drivers as soon as we discover them.
Note that this patch does not turn the auto update on. We will turn it on in a separate CL.
Reland this patch after fixing a bug causing a XP test failure.
BUG=68802
TEST=bots green
TBR=kbr
Review URL: http://codereview.chromium.org/6588035
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76143 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/browser_main.cc | 6 | ||||
-rw-r--r-- | chrome/browser/gpu_data_manager.cc | 187 | ||||
-rw-r--r-- | chrome/browser/gpu_data_manager.h | 85 | ||||
-rw-r--r-- | chrome/browser/gpu_process_host_ui_shim.cc | 172 | ||||
-rw-r--r-- | chrome/browser/gpu_process_host_ui_shim.h | 62 | ||||
-rw-r--r-- | chrome/browser/web_resource/gpu_blacklist_updater.cc | 51 | ||||
-rw-r--r-- | chrome/browser/web_resource/gpu_blacklist_updater.h | 28 | ||||
-rw-r--r-- | chrome/browser/web_resource/promo_resource_service.cc | 2 | ||||
-rw-r--r-- | chrome/browser/web_resource/web_resource_service.cc | 9 | ||||
-rw-r--r-- | chrome/browser/web_resource/web_resource_service.h | 3 | ||||
-rw-r--r-- | chrome/browser/webui/gpu_internals_ui.cc | 23 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 4 | ||||
-rw-r--r-- | chrome/common/pref_names.cc | 7 | ||||
-rw-r--r-- | chrome/common/pref_names.h | 3 | ||||
-rw-r--r-- | chrome/test/gpu/gpu_pixel_browsertest.cc | 13 | ||||
-rw-r--r-- | content/browser/gpu_blacklist.cc | 31 | ||||
-rw-r--r-- | content/browser/gpu_blacklist.h | 7 |
17 files changed, 461 insertions, 232 deletions
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc index a3beb41..3a701e0 100644 --- a/chrome/browser/browser_main.cc +++ b/chrome/browser/browser_main.cc @@ -40,6 +40,7 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extensions_startup.h" #include "chrome/browser/first_run/first_run.h" +#include "chrome/browser/gpu_data_manager.h" #include "chrome/browser/jankometer.h" #include "chrome/browser/metrics/histogram_synchronizer.h" #include "chrome/browser/metrics/metrics_log.h" @@ -1811,6 +1812,11 @@ int BrowserMain(const MainFunctionParams& parameters) { // might have shutdown because an update was available. profile->GetCloudPrintProxyService(); + // Need to initialize GpuDataManager to load the current GPU blacklist + // and schedule a GPU blacklist auto update. + GpuDataManager* gpu_data_manager = GpuDataManager::GetInstance(); + DCHECK(gpu_data_manager); + int result_code = ResultCodes::NORMAL_EXIT; if (parameters.ui_task) { // We are in test mode. Run one task and enter the main message loop. diff --git a/chrome/browser/gpu_data_manager.cc b/chrome/browser/gpu_data_manager.cc new file mode 100644 index 0000000..1c8d120 --- /dev/null +++ b/chrome/browser/gpu_data_manager.cc @@ -0,0 +1,187 @@ +// Copyright (c) 2011 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 "chrome/browser/gpu_data_manager.h" + +#include "app/app_switches.h" +#include "app/gfx/gl/gl_implementation.h" +#include "base/command_line.h" +#include "base/metrics/histogram.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/common/child_process_logging.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/pref_names.h" +#include "content/browser/gpu_blacklist.h" +#include "grit/browser_resources.h" +#include "ui/base/resource/resource_bundle.h" + +GpuDataManager::GpuDataManager() + : gpu_feature_flags_set_(false), + gpu_blacklist_cache_(NULL) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(g_browser_process); + PrefService* prefs = g_browser_process->local_state(); + // If we bring up chrome normally, prefs should never be NULL; however, we + // we handle the case where prefs == NULL for certain tests. + if (prefs) { + prefs->RegisterDictionaryPref(prefs::kGpuBlacklist); + gpu_blacklist_cache_ = prefs->GetMutableDictionary(prefs::kGpuBlacklist); + DCHECK(gpu_blacklist_cache_); + + gpu_blacklist_updater_ = new GpuBlacklistUpdater(); + // TODO(zmo): uncomment the following line to turn on auto-updating. + // gpu_blacklist_updater_->StartAfterDelay(); + } + + LoadGpuBlacklist(); + UpdateGpuBlacklist(); +} + +GpuDataManager::~GpuDataManager() { } + +GpuDataManager* GpuDataManager::GetInstance() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return Singleton<GpuDataManager>::get(); +} + +void GpuDataManager::UpdateGpuInfo(const GPUInfo& gpu_info) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (gpu_info_.level() >= gpu_info.level()) + return; + gpu_info_ = gpu_info; + child_process_logging::SetGpuInfo(gpu_info); + RunGpuInfoUpdateCallbacks(); +} + +const GPUInfo& GpuDataManager::gpu_info() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return gpu_info_; +} + +GpuFeatureFlags GpuDataManager::GetGpuFeatureFlags() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + UpdateGpuFeatureFlags(); + return gpu_feature_flags_; +} + +void GpuDataManager::AddGpuInfoUpdateCallback(Callback0::Type* callback) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + gpu_info_update_callbacks_.insert(callback); +} + +bool GpuDataManager::RemoveGpuInfoUpdateCallback(Callback0::Type* callback) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + std::set<Callback0::Type*>::iterator i = + gpu_info_update_callbacks_.find(callback); + if (i != gpu_info_update_callbacks_.end()) { + gpu_info_update_callbacks_.erase(i); + return true; + } + return false; +} + +void GpuDataManager::RunGpuInfoUpdateCallbacks() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + std::set<Callback0::Type*>::iterator i = gpu_info_update_callbacks_.begin(); + for (; i != gpu_info_update_callbacks_.end(); ++i) { + (*i)->Run(); + } +} + +bool GpuDataManager::LoadGpuBlacklist() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (gpu_blacklist_.get() != NULL) + return true; + static const base::StringPiece gpu_blacklist_json( + ResourceBundle::GetSharedInstance().GetRawDataResource( + IDR_GPU_BLACKLIST)); + gpu_blacklist_.reset(new GpuBlacklist()); + if (gpu_blacklist_->LoadGpuBlacklist(gpu_blacklist_json.as_string(), true)) + return true; + gpu_blacklist_.reset(NULL); + return false; +} + +bool GpuDataManager::UpdateGpuBlacklist() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (gpu_blacklist_cache_ == NULL) + return false; + uint16 cached_version_major, cached_version_minor; + if (!GpuBlacklist::GetVersion(*gpu_blacklist_cache_, + &cached_version_major, + &cached_version_minor)) + return false; + if (gpu_blacklist_.get() != NULL) { + uint16 current_version_major, current_version_minor; + if (gpu_blacklist_->GetVersion(¤t_version_major, + ¤t_version_minor) && + (cached_version_major < current_version_major || + (cached_version_major == current_version_major && + cached_version_minor <= current_version_minor))) + return false; + } + GpuBlacklist* updated_list = new GpuBlacklist(); + if (!updated_list->LoadGpuBlacklist(*gpu_blacklist_cache_, true)) { + delete updated_list; + return false; + } + gpu_blacklist_.reset(updated_list); + // Clear the flag to triger a re-computation of GpuFeatureFlags using the + // updated GPU blacklist. + gpu_feature_flags_set_ = false; + return true; +} + +void GpuDataManager::UpdateGpuFeatureFlags() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (gpu_info_.level() == GPUInfo::kUninitialized) + return; + + // Need to call this before checking gpu_feature_flags_set_ because it might + // be reset if a newer version of GPU blacklist is downloaed. + GpuBlacklist* gpu_blacklist = GetGpuBlacklist(); + if (gpu_blacklist == NULL) + return; + + if (gpu_feature_flags_set_) + return; + + gpu_feature_flags_set_ = true; + gpu_feature_flags_.set_flags(0); + + if (gpu_blacklist != NULL) { + gpu_feature_flags_ = gpu_blacklist->DetermineGpuFeatureFlags( + GpuBlacklist::kOsAny, NULL, gpu_info_); + if (gpu_feature_flags_.flags() != 0) { + // If gpu is blacklisted, no further GPUInfo will be collected. + gpu_info_.SetLevel(GPUInfo::kComplete); + // TODO(zmo): move histograming to GpuBlacklist::DetermineGpuFeatureFlags. + uint32 max_entry_id = gpu_blacklist->max_entry_id(); + std::vector<uint32> flag_entries; + gpu_blacklist->GetGpuFeatureFlagEntries( + GpuFeatureFlags::kGpuFeatureAll, flag_entries); + DCHECK_GT(flag_entries.size(), 0u); + for (size_t i = 0; i < flag_entries.size(); ++i) { + UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry", + flag_entries[i], max_entry_id + 1); + } + } + } +} + +GpuBlacklist* GpuDataManager::GetGpuBlacklist() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); + if (browser_command_line.HasSwitch(switches::kIgnoreGpuBlacklist) || + browser_command_line.GetSwitchValueASCII( + switches::kUseGL) == gfx::kGLImplementationOSMesaName) + return NULL; + UpdateGpuBlacklist(); + // No need to return an empty blacklist. + if (gpu_blacklist_.get() != NULL && gpu_blacklist_->max_entry_id() == 0) + return NULL; + return gpu_blacklist_.get(); +} + diff --git a/chrome/browser/gpu_data_manager.h b/chrome/browser/gpu_data_manager.h new file mode 100644 index 0000000..8275c4f --- /dev/null +++ b/chrome/browser/gpu_data_manager.h @@ -0,0 +1,85 @@ +// Copyright (c) 2011 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 CHROME_BROWSER_GPU_DATA_MANAGER_H_ +#define CHROME_BROWSER_GPU_DATA_MANAGER_H_ +#pragma once + +#include <set> + +#include "base/callback.h" +#include "base/scoped_ptr.h" +#include "base/singleton.h" +#include "chrome/browser/web_resource/gpu_blacklist_updater.h" +#include "chrome/common/gpu_feature_flags.h" +#include "chrome/common/gpu_info.h" + +class DictionaryValue; +class GpuBlacklist; +class GPUInfo; + +class GpuDataManager { + public: + // Getter for the singleton. This will return NULL on failure. + static GpuDataManager* GetInstance(); + + // Only update if the level is higher than the cached GPUInfo level. + void UpdateGpuInfo(const GPUInfo& gpu_info); + + const GPUInfo& gpu_info() const; + + // If necessary, compute the flags before returning them. + GpuFeatureFlags GetGpuFeatureFlags(); + + // Add a callback. + void AddGpuInfoUpdateCallback(Callback0::Type* callback); + + // Remove a callback. + // Returns true if removed, or false if it was not found. + bool RemoveGpuInfoUpdateCallback(Callback0::Type* callback); + + private: + friend struct DefaultSingletonTraits<GpuDataManager>; + + GpuDataManager(); + virtual ~GpuDataManager(); + + bool LoadGpuBlacklist(); + + // Check if a newer version of GPU blacklist has been downloaded from the + // web (and saved in the local state); if yes, use the newer version instead. + // Return true if a newer version is installed. + bool UpdateGpuBlacklist(); + + // Check if we should go ahead and use gpu blacklist. + // If not, return NULL; otherwise, update and return the current list. + GpuBlacklist* GetGpuBlacklist(); + + // If flags hasn't been set and GPUInfo is available, run through blacklist + // and compute the flags. + void UpdateGpuFeatureFlags(); + + // Call all callbacks. + void RunGpuInfoUpdateCallbacks(); + + bool gpu_feature_flags_set_; + GpuFeatureFlags gpu_feature_flags_; + + GPUInfo gpu_info_; + + scoped_ptr<GpuBlacklist> gpu_blacklist_; + + scoped_refptr<GpuBlacklistUpdater> gpu_blacklist_updater_; + // This is the version cached in local state that's automatically updated + // from the web. + DictionaryValue* gpu_blacklist_cache_; + + // Map of callbacks. + std::set<Callback0::Type*> gpu_info_update_callbacks_; + + DISALLOW_COPY_AND_ASSIGN(GpuDataManager); +}; + +#endif // CHROME_BROWSER_GPU_DATA_MANAGER_H_ + diff --git a/chrome/browser/gpu_process_host_ui_shim.cc b/chrome/browser/gpu_process_host_ui_shim.cc index 431846c..ff7a237 100644 --- a/chrome/browser/gpu_process_host_ui_shim.cc +++ b/chrome/browser/gpu_process_host_ui_shim.cc @@ -7,23 +7,14 @@ #include "chrome/browser/gpu_process_host_ui_shim.h" -#include "app/app_switches.h" -#include "app/gfx/gl/gl_implementation.h" -#include "base/command_line.h" #include "base/id_map.h" -#include "base/metrics/histogram.h" #include "chrome/browser/browser_thread.h" +#include "chrome/browser/gpu_data_manager.h" #include "chrome/browser/gpu_process_host.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/render_widget_host_view.h" -#include "chrome/common/child_process_logging.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/gpu_messages.h" -#include "chrome/gpu/gpu_info_collector.h" -#include "content/browser/gpu_blacklist.h" -#include "grit/browser_resources.h" -#include "ui/base/resource/resource_bundle.h" #if defined(OS_LINUX) // These two #includes need to come after gpu_messages.h. @@ -62,62 +53,6 @@ class SendOnIOThreadTask : public Task { } // namespace -//////////////////////////////////////////////////////////////////////////////// -// -// Callback0Group -// -//////////////////////////////////////////////////////////////////////////////// - -Callback0Group::Callback0Group() { -} - -Callback0Group::~Callback0Group() { -} - -void Callback0Group::Add(Callback0::Type* callback) { - callbacks_.insert(callback); -} - -bool Callback0Group::Remove(Callback0::Type* callback) { - std::set<Callback0::Type*>::iterator i = callbacks_.find(callback); - if (i != callbacks_.end()) { - callbacks_.erase(i); - return true; - } - return false; -} - -void Callback0Group::Run() { - std::set<Callback0::Type*>::iterator i = callbacks_.begin(); - for (; i != callbacks_.end(); ++i) { - (*i)->Run(); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// -// GpuProcessHostUIShimManager -// -//////////////////////////////////////////////////////////////////////////////// - -GpuProcessHostUIShimManager::GpuProcessHostUIShimManager() { -} - -GpuProcessHostUIShimManager* GpuProcessHostUIShimManager::GetInstance() { - return Singleton<GpuProcessHostUIShimManager>::get(); -} - -void GpuProcessHostUIShimManager::SetGpuInfo(const GPUInfo& gpu_info) { - gpu_info_ = gpu_info; - gpu_info_update_callbacks().Run(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -// GpuProcessHostUIShim -// -//////////////////////////////////////////////////////////////////////////////// - class GpuProcessHostUIShim::ViewSurface { public: explicit ViewSurface(ViewID view_id); @@ -167,9 +102,10 @@ RenderWidgetHostView* GpuProcessHostUIShim::ViewSurface:: GpuProcessHostUIShim::GpuProcessHostUIShim() : host_id_(++g_last_host_id), - gpu_process_(NULL), - gpu_feature_flags_set_(false) { + gpu_process_(NULL) { g_hosts_by_id.AddWithID(this, host_id_); + gpu_data_manager_ = GpuDataManager::GetInstance(); + DCHECK(gpu_data_manager_); } // static @@ -185,10 +121,6 @@ GpuProcessHostUIShim* GpuProcessHostUIShim::GetForRenderer(int renderer_id) { } GpuProcessHostUIShim* ui_shim(new GpuProcessHostUIShim); - if (!ui_shim->Init()) { - delete ui_shim; - return NULL; - } // If Init succeeds, post a task to create the corresponding GpuProcessHost. // The GpuProcessHost will take ownership of the GpuProcessHostUIShim. @@ -332,7 +264,7 @@ void GpuProcessHostUIShim::EstablishGpuChannel( linked_ptr<EstablishChannelCallback> wrapped_callback(callback); // If GPU features are already blacklisted, no need to establish the channel. - if (gpu_feature_flags_.flags() != 0) { + if (gpu_data_manager_->GetGpuFeatureFlags().flags() != 0) { EstablishChannelError( wrapped_callback.release(), IPC::ChannelHandle(), NULL, GPUInfo()); return; @@ -397,8 +329,9 @@ void GpuProcessHostUIShim::DidDestroyAcceleratedSurface(int renderer_id, void GpuProcessHostUIShim::CollectGpuInfoAsynchronously( GPUInfo::Level level) { DCHECK(CalledOnValidThread()); + // If GPU is already blacklisted, no more info will be collected. - if (gpu_feature_flags_.flags() != 0) + if (gpu_data_manager_->GetGpuFeatureFlags().flags() != 0) return; Send(new GpuMsg_CollectGraphicsInfo(level)); } @@ -415,7 +348,7 @@ void GpuProcessHostUIShim::SendAboutGpuHang() { const GPUInfo& GpuProcessHostUIShim::gpu_info() const { DCHECK(CalledOnValidThread()); - return gpu_info_; + return gpu_data_manager_->gpu_info(); } GpuProcessHostUIShim::~GpuProcessHostUIShim() { @@ -428,10 +361,6 @@ GpuProcessHostUIShim::~GpuProcessHostUIShim() { #endif } -bool GpuProcessHostUIShim::Init() { - return LoadGpuBlacklist(); -} - void GpuProcessHostUIShim::AddCustomLogMessage(int level, const std::string& header, const std::string& message) { @@ -476,48 +405,19 @@ bool GpuProcessHostUIShim::OnControlMessageReceived( void GpuProcessHostUIShim::OnChannelEstablished( const IPC::ChannelHandle& channel_handle, const GPUInfo& gpu_info) { + gpu_data_manager_->UpdateGpuInfo(gpu_info); + // The GPU process should have launched at this point and this object should // have been notified of its process handle. DCHECK(gpu_process_); - uint32 max_entry_id = gpu_blacklist_->max_entry_id(); - // max_entry_id can be zero if we failed to load the GPU blacklist, don't - // bother with histograms then. - if (channel_handle.name.size() != 0 && !gpu_feature_flags_set_ && - max_entry_id != 0) - { - gpu_feature_flags_set_ = true; - - const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); - if (!browser_command_line.HasSwitch(switches::kIgnoreGpuBlacklist) && - browser_command_line.GetSwitchValueASCII( - switches::kUseGL) != gfx::kGLImplementationOSMesaName) { - gpu_feature_flags_ = gpu_blacklist_->DetermineGpuFeatureFlags( - GpuBlacklist::kOsAny, NULL, gpu_info); - - if (gpu_feature_flags_.flags() != 0) { - std::vector<uint32> flag_entries; - gpu_blacklist_->GetGpuFeatureFlagEntries( - GpuFeatureFlags::kGpuFeatureAll, flag_entries); - DCHECK_GT(flag_entries.size(), 0u); - for (size_t i = 0; i < flag_entries.size(); ++i) { - UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry", - flag_entries[i], max_entry_id + 1); - } - } else { - // id 0 is never used by any entry, so we use it here to indicate that - // gpu is allowed. - UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry", - 0, max_entry_id + 1); - } - } - } linked_ptr<EstablishChannelCallback> callback = channel_requests_.front(); channel_requests_.pop(); // Currently if any of the GPU features are blacklisted, we don't establish a // GPU channel. - if (gpu_feature_flags_.flags() != 0) { + if (channel_handle.name.size() != 0 && + gpu_data_manager_->GetGpuFeatureFlags().flags() != 0) { Send(new GpuMsg_CloseChannel(channel_handle)); EstablishChannelError(callback.release(), IPC::ChannelHandle(), @@ -559,43 +459,16 @@ void GpuProcessHostUIShim::OnDestroyCommandBuffer( } void GpuProcessHostUIShim::OnGraphicsInfoCollected(const GPUInfo& gpu_info) { - gpu_info_ = gpu_info; - if (gpu_feature_flags_.flags() != 0) - gpu_info_.SetLevel(GPUInfo::kComplete); - child_process_logging::SetGpuInfo(gpu_info_); - - GpuProcessHostUIShimManager::GetInstance()->SetGpuInfo(gpu_info); + gpu_data_manager_->UpdateGpuInfo(gpu_info); } void GpuProcessHostUIShim::OnPreliminaryGraphicsInfoCollected( const GPUInfo& gpu_info, IPC::Message* reply_msg) { - bool blacklisted = false; - const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); - if (!browser_command_line.HasSwitch(switches::kIgnoreGpuBlacklist) && - browser_command_line.GetSwitchValueASCII( - switches::kUseGL) != gfx::kGLImplementationOSMesaName) { - gpu_feature_flags_ = gpu_blacklist_->DetermineGpuFeatureFlags( - GpuBlacklist::kOsAny, NULL, gpu_info); - if (gpu_feature_flags_.flags() != 0) { - blacklisted = true; - gpu_feature_flags_set_ = true; - gpu_info_ = gpu_info; - gpu_info_.SetLevel(GPUInfo::kComplete); - child_process_logging::SetGpuInfo(gpu_info_); - uint32 max_entry_id = gpu_blacklist_->max_entry_id(); - std::vector<uint32> flag_entries; - gpu_blacklist_->GetGpuFeatureFlagEntries( - GpuFeatureFlags::kGpuFeatureAll, flag_entries); - DCHECK_GT(flag_entries.size(), 0u); - for (size_t i = 0; i < flag_entries.size(); ++i) { - UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerEntry", - flag_entries[i], max_entry_id + 1); - } - } - } + gpu_data_manager_->UpdateGpuInfo(gpu_info); + GpuFeatureFlags flags = gpu_data_manager_->GetGpuFeatureFlags(); GpuHostMsg_PreliminaryGraphicsInfoCollected::WriteReplyParams( - reply_msg, blacklisted); + reply_msg, flags.flags() != 0); Send(reply_msg); } @@ -675,16 +548,3 @@ void GpuProcessHostUIShim::OnScheduleComposite(int renderer_id, #endif -bool GpuProcessHostUIShim::LoadGpuBlacklist() { - if (gpu_blacklist_.get() != NULL) - return true; - static const base::StringPiece gpu_blacklist_json( - ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_GPU_BLACKLIST)); - gpu_blacklist_.reset(new GpuBlacklist()); - if (gpu_blacklist_->LoadGpuBlacklist(gpu_blacklist_json.as_string(), true)) - return true; - gpu_blacklist_.reset(NULL); - return false; -} - diff --git a/chrome/browser/gpu_process_host_ui_shim.h b/chrome/browser/gpu_process_host_ui_shim.h index f973860..1e9ae53 100644 --- a/chrome/browser/gpu_process_host_ui_shim.h +++ b/chrome/browser/gpu_process_host_ui_shim.h @@ -13,7 +13,6 @@ #include <map> #include <queue> -#include <set> #include "base/callback.h" #include "base/linked_ptr.h" @@ -32,7 +31,7 @@ namespace gfx { class Size; } -class GpuBlacklist; +class GpuDataManager; struct GPUCreateCommandBufferConfig; class GPUInfo; struct GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params; @@ -43,55 +42,6 @@ struct ChannelHandle; class Message; } -class Callback0Group -{ - public: - Callback0Group(); - ~Callback0Group(); - - // Add a callback. - void Add(Callback0::Type* callback); - - // Remove a callback. - // Returns true if removed, or false if it was not found. - bool Remove(Callback0::Type* callback); - - // Call all callbacks. - void Run(); - - private: - DISALLOW_COPY_AND_ASSIGN(Callback0Group); - - // Map of callbacks. - std::set<Callback0::Type*> callbacks_; -}; - -class GpuProcessHostUIShimManager -{ - public: - static GpuProcessHostUIShimManager* GetInstance(); - - void SetGpuInfo(const GPUInfo& gpu_info); - - // This callback group is invoked when GPU info is updated. - Callback0Group& gpu_info_update_callbacks() { - return gpu_info_update_callbacks_; - } - - // Return all known information about the GPU. - const GPUInfo& gpu_info() const { - return gpu_info_; - } - - private: - GpuProcessHostUIShimManager(); - friend struct DefaultSingletonTraits<GpuProcessHostUIShimManager>; - DISALLOW_COPY_AND_ASSIGN(GpuProcessHostUIShimManager); - - GPUInfo gpu_info_; - Callback0Group gpu_info_update_callbacks_; -}; - class GpuProcessHostUIShim : public IPC::Channel::Listener, public IPC::Channel::Sender, @@ -184,12 +134,9 @@ class GpuProcessHostUIShim void AddCustomLogMessage(int level, const std::string& header, const std::string& message); - bool LoadGpuBlacklist(); - private: GpuProcessHostUIShim(); virtual ~GpuProcessHostUIShim(); - bool Init(); // Message handlers. bool OnControlMessageReceived(const IPC::Message& message); @@ -222,9 +169,11 @@ class GpuProcessHostUIShim // The handle for the GPU process or null if it is not known to be launched. base::ProcessHandle gpu_process_; - GPUInfo gpu_info_; ListValue log_messages_; + // Cached pointer to the singleton for efficiency purpose. + GpuDataManager* gpu_data_manager_; + // These are the channel requests that we have already sent to // the GPU process, but haven't heard back about yet. std::queue<linked_ptr<EstablishChannelCallback> > channel_requests_; @@ -245,9 +194,6 @@ class GpuProcessHostUIShim class ViewSurface; std::map<ViewID, linked_ptr<ViewSurface> > acquired_surfaces_; - bool gpu_feature_flags_set_; - scoped_ptr<GpuBlacklist> gpu_blacklist_; - GpuFeatureFlags gpu_feature_flags_; }; #endif // CHROME_BROWSER_GPU_PROCESS_HOST_UI_SHIM_H_ diff --git a/chrome/browser/web_resource/gpu_blacklist_updater.cc b/chrome/browser/web_resource/gpu_blacklist_updater.cc new file mode 100644 index 0000000..ca297a1 --- /dev/null +++ b/chrome/browser/web_resource/gpu_blacklist_updater.cc @@ -0,0 +1,51 @@ +// Copyright (c) 2011 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 "chrome/browser/web_resource/gpu_blacklist_updater.h" + +#include "base/values.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_thread.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/common/notification_type.h" +#include "chrome/common/pref_names.h" + +namespace { + +// Delay on first fetch so we don't interfere with startup. +static const int kStartGpuBlacklistFetchDelay = 6000; + +// Delay between calls to update the gpu blacklist (48 hours). +static const int kCacheUpdateDelay = 48 * 60 * 60 * 1000; + +} // namespace + +const char* GpuBlacklistUpdater::kDefaultGpuBlacklistURL = + "http://cache.pack.google.com/edgedl/chrome/gpu/" + "software_rendering_list.json"; + +GpuBlacklistUpdater::GpuBlacklistUpdater() + : WebResourceService(ProfileManager::GetDefaultProfile(), + g_browser_process->local_state(), + GpuBlacklistUpdater::kDefaultGpuBlacklistURL, + false, // don't append locale to URL + NotificationType::NOTIFICATION_TYPE_COUNT, + prefs::kGpuBlacklistUpdate, + kStartGpuBlacklistFetchDelay, + kCacheUpdateDelay) { +} + +GpuBlacklistUpdater::~GpuBlacklistUpdater() { } + +void GpuBlacklistUpdater::Unpack(const DictionaryValue& parsed_json) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DictionaryValue* gpu_blacklist_cache = + prefs_->GetMutableDictionary(prefs::kGpuBlacklist); + DCHECK(gpu_blacklist_cache); + gpu_blacklist_cache->Clear(); + gpu_blacklist_cache->MergeDictionary(&parsed_json); +} + diff --git a/chrome/browser/web_resource/gpu_blacklist_updater.h b/chrome/browser/web_resource/gpu_blacklist_updater.h new file mode 100644 index 0000000..136fd72 --- /dev/null +++ b/chrome/browser/web_resource/gpu_blacklist_updater.h @@ -0,0 +1,28 @@ +// Copyright (c) 2011 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 CHROME_BROWSER_WEB_RESOURCE_GPU_BLACKLIST_UPDATER_H_ +#define CHROME_BROWSER_WEB_RESOURCE_GPU_BLACKLIST_UPDATER_H_ +#pragma once + +#include "chrome/browser/web_resource/web_resource_service.h" + +class GpuBlacklistUpdater + : public WebResourceService { + public: + explicit GpuBlacklistUpdater(); + + // URL of the up-to-date gpu_blacklist.json file. + static const char* kDefaultGpuBlacklistURL; + + private: + virtual ~GpuBlacklistUpdater(); + + virtual void Unpack(const DictionaryValue& parsed_json); + + DISALLOW_COPY_AND_ASSIGN(GpuBlacklistUpdater); +}; + +#endif // CHROME_BROWSER_WEB_RESOURCE_GPU_BLACKLIST_UPDATER_H_ + diff --git a/chrome/browser/web_resource/promo_resource_service.cc b/chrome/browser/web_resource/promo_resource_service.cc index f694563..30a2c74 100644 --- a/chrome/browser/web_resource/promo_resource_service.cc +++ b/chrome/browser/web_resource/promo_resource_service.cc @@ -53,6 +53,7 @@ const char* PromoResourceService::kDefaultPromoResourceServer = PromoResourceService::PromoResourceService(Profile* profile) : WebResourceService(profile, + profile->GetPrefs(), PromoResourceService::kDefaultPromoResourceServer, true, // append locale to URL NotificationType::PROMO_RESOURCE_STATE_CHANGED, @@ -66,7 +67,6 @@ PromoResourceService::PromoResourceService(Profile* profile) PromoResourceService::~PromoResourceService() { } void PromoResourceService::Init() { - prefs_->RegisterStringPref(prefs::kNTPPromoResourceCacheUpdate, "0"); prefs_->RegisterDoublePref(prefs::kNTPCustomLogoStart, 0); prefs_->RegisterDoublePref(prefs::kNTPCustomLogoEnd, 0); prefs_->RegisterDoublePref(prefs::kNTPPromoStart, 0); diff --git a/chrome/browser/web_resource/web_resource_service.cc b/chrome/browser/web_resource/web_resource_service.cc index daddae7..1026651 100644 --- a/chrome/browser/web_resource/web_resource_service.cc +++ b/chrome/browser/web_resource/web_resource_service.cc @@ -198,13 +198,15 @@ class WebResourceService::UnpackerClient WebResourceService::WebResourceService( Profile* profile, + PrefService* prefs, const char* web_resource_server, bool apply_locale_to_url, NotificationType::Type notification_type, const char* last_update_time_pref_name, int start_fetch_delay, int cache_update_delay) - : profile_(profile), + : prefs_(prefs), + profile_(profile), ALLOW_THIS_IN_INITIALIZER_LIST(service_factory_(this)), in_fetch_(false), web_resource_server_(web_resource_server), @@ -214,8 +216,9 @@ WebResourceService::WebResourceService( start_fetch_delay_(start_fetch_delay), cache_update_delay_(cache_update_delay), web_resource_update_scheduled_(false) { + DCHECK(prefs); DCHECK(profile); - prefs_ = profile_->GetPrefs(); + prefs_->RegisterStringPref(last_update_time_pref_name, "0"); resource_dispatcher_host_ = g_browser_process->resource_dispatcher_host(); web_resource_fetcher_.reset(new WebResourceFetcher(this)); } @@ -247,6 +250,8 @@ void WebResourceService::OnWebResourceUnpacked( void WebResourceService::WebResourceStateChange() { web_resource_update_scheduled_ = false; + if (notification_type_ == NotificationType::NOTIFICATION_TYPE_COUNT) + return; NotificationService* service = NotificationService::current(); service->Notify(notification_type_, Source<WebResourceService>(this), diff --git a/chrome/browser/web_resource/web_resource_service.h b/chrome/browser/web_resource/web_resource_service.h index 1b4b680..64c37e6 100644 --- a/chrome/browser/web_resource/web_resource_service.h +++ b/chrome/browser/web_resource/web_resource_service.h @@ -19,7 +19,10 @@ class Profile; class WebResourceService : public UtilityProcessHost::Client { public: + // Pass notification_type = NOTIFICATION_TYPE_COUNT if notification is not + // required. WebResourceService(Profile* profile, + PrefService* prefs, const char* web_resource_server, bool apply_locale_to_url_, NotificationType::Type notification_type, diff --git a/chrome/browser/webui/gpu_internals_ui.cc b/chrome/browser/webui/gpu_internals_ui.cc index 2462d05..7a2f2bd 100644 --- a/chrome/browser/webui/gpu_internals_ui.cc +++ b/chrome/browser/webui/gpu_internals_ui.cc @@ -20,6 +20,7 @@ #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" +#include "chrome/browser/gpu_data_manager.h" #include "chrome/browser/gpu_process_host.h" #include "chrome/browser/gpu_process_host_ui_shim.h" #include "chrome/browser/io_thread.h" @@ -93,6 +94,9 @@ class GpuMessageHandler private: DISALLOW_COPY_AND_ASSIGN(GpuMessageHandler); + // Cache the Singleton for efficiency. + GpuDataManager* gpu_data_manager_; + Callback0::Type* gpu_info_update_callback_; }; @@ -140,12 +144,13 @@ std::string GpuHTMLSource::GetMimeType(const std::string&) const { //////////////////////////////////////////////////////////////////////////////// GpuMessageHandler::GpuMessageHandler() : gpu_info_update_callback_(NULL) { + gpu_data_manager_ = GpuDataManager::GetInstance(); + DCHECK(gpu_data_manager_); } GpuMessageHandler::~GpuMessageHandler() { if (gpu_info_update_callback_) { - GpuProcessHostUIShimManager::GetInstance()-> - gpu_info_update_callbacks().Remove(gpu_info_update_callback_); + gpu_data_manager_->RemoveGpuInfoUpdateCallback(gpu_info_update_callback_); delete gpu_info_update_callback_; } } @@ -216,12 +221,16 @@ void GpuMessageHandler::OnCallAsync(const ListValue* args) { } void GpuMessageHandler::OnRequestGpuInfo(const ListValue* args) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (gpu_info_update_callback_ == NULL) { // Add us to be called when GPUInfo changes and ask for updated GPUInfo. gpu_info_update_callback_ = NewCallback(this, &GpuMessageHandler::OnGpuInfoCollected); - GpuProcessHostUIShimManager::GetInstance()->gpu_info_update_callbacks().Add( - gpu_info_update_callback_); + gpu_data_manager_->AddGpuInfoUpdateCallback(gpu_info_update_callback_); + // Run callback immediately in case the info is ready and no update in the + // future. + OnGpuInfoCollected(); } GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::GetForRenderer(0); if (ui_shim) @@ -362,9 +371,11 @@ Value* GpuMessageHandler::OnRequestLogMessages(const ListValue*) { } void GpuMessageHandler::OnGpuInfoCollected() { - // Get GPU Info. - GPUInfo gpu_info = GpuProcessHostUIShimManager::GetInstance()->gpu_info(); + const GPUInfo& gpu_info = gpu_data_manager_->gpu_info(); + + if (gpu_info.level() == GPUInfo::kUninitialized) + return; // Send GPU Info to javascript. Value* gpuInfoVal = GpuInfoToDict(gpu_info); diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index e2dbf29..6204ce8 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1180,6 +1180,8 @@ 'browser/google/google_url_tracker.h', 'browser/google/google_util.cc', 'browser/google/google_util.h', + 'browser/gpu_data_manager.cc', + 'browser/gpu_data_manager.h', 'browser/gpu_process_host_ui_shim.cc', 'browser/gpu_process_host_ui_shim.h', 'browser/hang_monitor/hung_plugin_action.cc', @@ -3275,6 +3277,8 @@ 'browser/visitedlink/visitedlink_master.h', 'browser/web_applications/web_app.cc', 'browser/web_applications/web_app.h', + 'browser/web_resource/gpu_blacklist_updater.cc', + 'browser/web_resource/gpu_blacklist_updater.h', 'browser/web_resource/promo_resource_service.cc', 'browser/web_resource/promo_resource_service.h', 'browser/web_resource/web_resource_service.cc', diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index c6dcce6..651b355 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -1094,6 +1094,13 @@ const char kNTPPromoLine[] = "ntp.promo_line"; const char kNTPPromoStart[] = "ntp.promo_start"; const char kNTPPromoEnd[] = "ntp.promo_end"; +// The most up-to-date GPU blacklist downloaded from the web, which replaces +// the one that's installed with chrome. +const char kGpuBlacklist[] = "gpu_blacklist"; + +// Last time of update of gpu_blacklist. +const char kGpuBlacklistUpdate[] = "gpu_blacklist_update"; + const char kDevToolsDisabled[] = "devtools.disabled"; // A boolean specifying whether dev tools window should be opened docked. diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 6e05d71..938240f 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -381,6 +381,9 @@ extern const char kNTPPromoGroup[]; extern const char kNTPPromoGroupTimeSlice[]; extern const char kNTPPromoBuild[]; +extern const char kGpuBlacklist[]; +extern const char kGpuBlacklistUpdate[]; + extern const char kDevToolsDisabled[]; extern const char kDevToolsOpenDocked[]; extern const char kDevToolsSplitLocation[]; diff --git a/chrome/test/gpu/gpu_pixel_browsertest.cc b/chrome/test/gpu/gpu_pixel_browsertest.cc index ede1c69..26fc191 100644 --- a/chrome/test/gpu/gpu_pixel_browsertest.cc +++ b/chrome/test/gpu/gpu_pixel_browsertest.cc @@ -14,12 +14,13 @@ #include "base/path_service.h" #include "base/string_util.h" #include "base/stringprintf.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/gpu_data_manager.h" #include "chrome/browser/gpu_process_host.h" #include "chrome/browser/gpu_process_host_ui_shim.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/gpu_info.h" @@ -92,14 +93,14 @@ class GPUInfoCollectedObserver { gpu_info_collected_(false) { gpu_info_update_callback_ = NewCallback(this, &GPUInfoCollectedObserver::OnGpuInfoCollected); - GpuProcessHostUIShimManager::GetInstance()->gpu_info_update_callbacks().Add( - gpu_info_update_callback_); + GpuDataManager::GetInstance()-> + AddGpuInfoUpdateCallback(gpu_info_update_callback_); } void OnGpuInfoCollected() { gpu_info_collected_ = true; - GpuProcessHostUIShimManager::GetInstance()-> - gpu_info_update_callbacks().Remove(gpu_info_update_callback_); + GpuDataManager::GetInstance()-> + RemoveGpuInfoUpdateCallback(gpu_info_update_callback_); delete gpu_info_update_callback_; MessageLoopForUI::current()->Quit(); } diff --git a/content/browser/gpu_blacklist.cc b/content/browser/gpu_blacklist.cc index 544a656..771de1d 100644 --- a/content/browser/gpu_blacklist.cc +++ b/content/browser/gpu_blacklist.cc @@ -426,7 +426,6 @@ GpuBlacklist::~GpuBlacklist() { bool GpuBlacklist::LoadGpuBlacklist(const std::string& json_context, bool current_os_only) { - std::vector<GpuBlacklistEntry*> entries; scoped_ptr<Value> root; root.reset(base::JSONReader::Read(json_context, false)); if (root.get() == NULL || !root->IsType(Value::TYPE_DICTIONARY)) @@ -434,14 +433,21 @@ bool GpuBlacklist::LoadGpuBlacklist(const std::string& json_context, DictionaryValue* root_dictionary = static_cast<DictionaryValue*>(root.get()); DCHECK(root_dictionary); + return LoadGpuBlacklist(*root_dictionary, current_os_only); +} + +bool GpuBlacklist::LoadGpuBlacklist(const DictionaryValue& parsed_json, + bool current_os_only) { + std::vector<GpuBlacklistEntry*> entries; + std::string version_string; - root_dictionary->GetString("version", &version_string); + parsed_json.GetString("version", &version_string); version_.reset(Version::GetVersionFromString(version_string)); if (version_.get() == NULL) return false; ListValue* list = NULL; - root_dictionary->GetList("entries", &list); + parsed_json.GetList("entries", &list); if (list == NULL) return false; @@ -556,6 +562,25 @@ bool GpuBlacklist::GetVersion(uint16* major, uint16* minor) const { return true; } +bool GpuBlacklist::GetVersion( + const DictionaryValue& parsed_json, uint16* major, uint16* minor) { + DCHECK(major && minor); + *major = 0; + *minor = 0; + std::string version_string; + if (!parsed_json.GetString("version", &version_string)) + return false; + scoped_ptr<Version> version(Version::GetVersionFromString(version_string)); + if (version.get() == NULL) + return false; + const std::vector<uint16>& components_reference = version->components(); + if (components_reference.size() != 2) + return false; + *major = components_reference[0]; + *minor = components_reference[1]; + return true; +} + GpuBlacklist::OsType GpuBlacklist::GetOsType() { #if defined(OS_WIN) return kOsWin; diff --git a/content/browser/gpu_blacklist.h b/content/browser/gpu_blacklist.h index f732af9..7758b65 100644 --- a/content/browser/gpu_blacklist.h +++ b/content/browser/gpu_blacklist.h @@ -37,6 +37,8 @@ class GpuBlacklist { // If failed, the current GpuBlacklist is un-touched. bool LoadGpuBlacklist(const std::string& json_context, bool current_os_only); + bool LoadGpuBlacklist(const DictionaryValue& parsed_json, + bool current_os_only); // Collects system information and combines them with gpu_info and blacklist // information to determine gpu feature flags. @@ -63,6 +65,11 @@ class GpuBlacklist { // major and minor to 0 on failure. bool GetVersion(uint16* major, uint16* monir) const; + // Collects the version of the current blacklist from a parsed json file. + // Returns false and sets major and minor to 0 on failure. + static bool GetVersion( + const DictionaryValue& parsed_json, uint16* major, uint16* minor); + private: class VersionInfo { public: |