diff options
author | zmo@google.com <zmo@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-19 00:05:57 +0000 |
---|---|---|
committer | zmo@google.com <zmo@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-19 00:05:57 +0000 |
commit | 079c4ad1af9ba5bbac595bd126540c5f4744e3a3 (patch) | |
tree | 8ddc008ca3b8c9d8b95defd9eef3ef2f3ea1e818 | |
parent | 8b70f1e6b4909378f23fe1ebd6a75db6919a7155 (diff) | |
download | chromium_src-079c4ad1af9ba5bbac595bd126540c5f4744e3a3.zip chromium_src-079c4ad1af9ba5bbac595bd126540c5f4744e3a3.tar.gz chromium_src-079c4ad1af9ba5bbac595bd126540c5f4744e3a3.tar.bz2 |
Collect as much GPU information as possible without creating a GL/D3D context. If based on such partial information, a graphics card/driver is already blacklisted, we shouldn't even try to establish GPU channel. This gives us the ability to blacklist REALLY BAD graphics card/driver that will crash during GPU info collection.
BUG=72979
TEST=none
Review URL: http://codereview.chromium.org/6531023
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75473 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/gpu_blacklist.cc | 34 | ||||
-rw-r--r-- | chrome/browser/gpu_blacklist.h | 8 | ||||
-rw-r--r-- | chrome/browser/gpu_process_host_ui_shim.cc | 49 | ||||
-rw-r--r-- | chrome/browser/gpu_process_host_ui_shim.h | 2 | ||||
-rw-r--r-- | chrome/common/gpu_messages_internal.h | 6 | ||||
-rw-r--r-- | chrome/gpu/gpu_info_collector.h | 5 | ||||
-rw-r--r-- | chrome/gpu/gpu_info_collector_linux.cc | 15 | ||||
-rw-r--r-- | chrome/gpu/gpu_info_collector_mac.mm | 15 | ||||
-rw-r--r-- | chrome/gpu/gpu_info_collector_win.cc | 12 | ||||
-rw-r--r-- | chrome/gpu/gpu_thread.cc | 15 |
10 files changed, 131 insertions, 30 deletions
diff --git a/chrome/browser/gpu_blacklist.cc b/chrome/browser/gpu_blacklist.cc index 33511bd..a09b807 100644 --- a/chrome/browser/gpu_blacklist.cc +++ b/chrome/browser/gpu_blacklist.cc @@ -378,26 +378,26 @@ bool GpuBlacklist::GpuBlacklistEntry::SetBlacklistedFeatures( } bool GpuBlacklist::GpuBlacklistEntry::Contains( - OsType os_type, const Version& os_version, - uint32 vendor_id, uint32 device_id, - const std::string& driver_vendor, - const Version& driver_version, - const std::string& gl_renderer) const { + OsType os_type, const Version& os_version, const GPUInfo& gpu_info) const { DCHECK(os_type != kOsAny); if (os_info_.get() != NULL && !os_info_->Contains(os_type, os_version)) return false; - if (vendor_id_ != 0 && vendor_id_ != vendor_id) + if (vendor_id_ != 0 && vendor_id_ != gpu_info.vendor_id()) return false; - if (device_id_ != 0 && device_id_ != device_id) + if (device_id_ != 0 && device_id_ != gpu_info.device_id()) return false; if (driver_vendor_info_.get() != NULL && - !driver_vendor_info_->Contains(driver_vendor)) - return false; - if (driver_version_info_.get() != NULL && - !driver_version_info_->Contains(driver_version)) + !driver_vendor_info_->Contains(gpu_info.driver_vendor())) return false; + if (driver_version_info_.get() != NULL) { + scoped_ptr<Version> driver_version( + Version::GetVersionFromString(gpu_info.driver_version())); + if (driver_version.get() == NULL || + !driver_version_info_->Contains(*driver_version)) + return false; + } if (gl_renderer_info_.get() != NULL && - !gl_renderer_info_->Contains(gl_renderer)) + !gl_renderer_info_->Contains(gpu_info.gl_renderer())) return false; return true; } @@ -492,10 +492,6 @@ GpuFeatureFlags GpuBlacklist::DetermineGpuFeatureFlags( // No need to go through blacklist entries if GPUInfo isn't available. if (gpu_info.level() == GPUInfo::kUninitialized) return flags; - scoped_ptr<Version> driver_version( - Version::GetVersionFromString(gpu_info.driver_version())); - if (driver_version.get() == NULL) - return flags; if (os == kOsAny) os = GetOsType(); @@ -524,11 +520,7 @@ GpuFeatureFlags GpuBlacklist::DetermineGpuFeatureFlags( DCHECK(os_version != NULL); for (size_t i = 0; i < blacklist_.size(); ++i) { - if (blacklist_[i]->Contains(os, *os_version, - gpu_info.vendor_id(), gpu_info.device_id(), - gpu_info.driver_vendor(), - *driver_version, - gpu_info.gl_renderer())) { + if (blacklist_[i]->Contains(os, *os_version, gpu_info)) { flags.Combine(blacklist_[i]->GetGpuFeatureFlags()); active_entries_.push_back(blacklist_[i]); } diff --git a/chrome/browser/gpu_blacklist.h b/chrome/browser/gpu_blacklist.h index e5e04b1..4fdf13a 100644 --- a/chrome/browser/gpu_blacklist.h +++ b/chrome/browser/gpu_blacklist.h @@ -154,11 +154,9 @@ class GpuBlacklist { DictionaryValue* value); // Determines if a given os/gc/driver is included in the Entry set. - bool Contains(OsType os_type, const Version& os_version, - uint32 vendor_id, uint32 device_id, - const std::string& driver_vendor, - const Version& driver_version, - const std::string& gl_renderer) const; + bool Contains(OsType os_type, + const Version& os_version, + const GPUInfo& gpu_info) const; // Returns the OsType. OsType GetOsType() const; diff --git a/chrome/browser/gpu_process_host_ui_shim.cc b/chrome/browser/gpu_process_host_ui_shim.cc index 70bb25f..671f9e3 100644 --- a/chrome/browser/gpu_process_host_ui_shim.cc +++ b/chrome/browser/gpu_process_host_ui_shim.cc @@ -17,6 +17,7 @@ #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 "grit/browser_resources.h" #include "ui/base/resource/resource_bundle.h" @@ -234,6 +235,13 @@ void GpuProcessHostUIShim::EstablishGpuChannel( DCHECK(CalledOnValidThread()); linked_ptr<EstablishChannelCallback> wrapped_callback(callback); + // If GPU features are already blacklisted, no need to establish the channel. + if (EnsureInitialized() && gpu_feature_flags_.flags() != 0) { + EstablishChannelError( + wrapped_callback.release(), IPC::ChannelHandle(), GPUInfo()); + return; + } + if (Send(new GpuMsg_EstablishChannel(renderer_id))) { channel_requests_.push(wrapped_callback); } else { @@ -284,6 +292,9 @@ void GpuProcessHostUIShim::CreateViewCommandBuffer( void GpuProcessHostUIShim::CollectGraphicsInfoAsynchronously( GPUInfo::Level level) { DCHECK(CalledOnValidThread()); + // If GPU is already blacklisted, no more info will be collected. + if (gpu_feature_flags_.flags() != 0) + return; Send(new GpuMsg_CollectGraphicsInfo(level)); } @@ -321,6 +332,8 @@ bool GpuProcessHostUIShim::OnControlMessageReceived( OnDestroyCommandBuffer) IPC_MESSAGE_HANDLER(GpuHostMsg_GraphicsInfoCollected, OnGraphicsInfoCollected) + IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuHostMsg_PreliminaryGraphicsInfoCollected, + OnPreliminaryGraphicsInfoCollected) IPC_MESSAGE_HANDLER(GpuHostMsg_OnLogMessage, OnLogMessage) IPC_MESSAGE_HANDLER(GpuHostMsg_SynchronizeReply, @@ -420,13 +433,47 @@ void GpuProcessHostUIShim::OnDestroyCommandBuffer( void GpuProcessHostUIShim::OnGraphicsInfoCollected(const GPUInfo& gpu_info) { gpu_info_ = gpu_info; - child_process_logging::SetGpuInfo(gpu_info); + if (gpu_feature_flags_.flags() != 0) + gpu_info_.SetLevel(GPUInfo::kComplete); + child_process_logging::SetGpuInfo(gpu_info_); // Used only in testing. if (gpu_info_collected_callback_.get()) gpu_info_collected_callback_->Run(); } +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); + } + } + } + + GpuHostMsg_PreliminaryGraphicsInfoCollected::WriteReplyParams( + reply_msg, blacklisted); + Send(reply_msg); +} + void GpuProcessHostUIShim::OnLogMessage(int level, const std::string& header, const std::string& message) { diff --git a/chrome/browser/gpu_process_host_ui_shim.h b/chrome/browser/gpu_process_host_ui_shim.h index 14c2585..fbe364a 100644 --- a/chrome/browser/gpu_process_host_ui_shim.h +++ b/chrome/browser/gpu_process_host_ui_shim.h @@ -142,6 +142,8 @@ class GpuProcessHostUIShim : public IPC::Channel::Sender, void OnDestroyCommandBuffer(gfx::PluginWindowHandle window, int32 renderer_id, int32 render_view_id); void OnGraphicsInfoCollected(const GPUInfo& gpu_info); + void OnPreliminaryGraphicsInfoCollected( + const GPUInfo& gpu_info, IPC::Message* reply_msg); void OnLogMessage(int level, const std::string& header, const std::string& message); void OnSynchronizeReply(); diff --git a/chrome/common/gpu_messages_internal.h b/chrome/common/gpu_messages_internal.h index 635362a..ca3e31c 100644 --- a/chrome/common/gpu_messages_internal.h +++ b/chrome/common/gpu_messages_internal.h @@ -133,6 +133,12 @@ IPC_MESSAGE_CONTROL3(GpuHostMsg_DestroyCommandBuffer, IPC_MESSAGE_CONTROL1(GpuHostMsg_GraphicsInfoCollected, GPUInfo /* GPU logging stats */) +// Request from GPU to check if GPU is blacklisted based on preliminary GPU +// info. +IPC_SYNC_MESSAGE_CONTROL1_1(GpuHostMsg_PreliminaryGraphicsInfoCollected, + GPUInfo, /* preliminary GPU logging stats */ + bool /* blacklisted or not */) + // Message from GPU to add a GPU log message to the about:gpu page. IPC_MESSAGE_CONTROL3(GpuHostMsg_OnLogMessage, int /*severity*/, diff --git a/chrome/gpu/gpu_info_collector.h b/chrome/gpu/gpu_info_collector.h index 577d197..9dab03e 100644 --- a/chrome/gpu/gpu_info_collector.h +++ b/chrome/gpu/gpu_info_collector.h @@ -19,6 +19,11 @@ namespace gpu_info_collector { // Returns true on success. bool CollectGraphicsInfo(GPUInfo* gpu_info); +// Similar to CollectGraphicsInfo, only this collects a subset of variables +// without creating a GL/DirectX context (and without the danger of crashing). +// The subset each platform collects may be different. +bool CollectPreliminaryGraphicsInfo(GPUInfo* gpu_info); + #if defined(OS_WIN) // Windows provides two ways of doing graphics so we need two ways of // collecting info based on what's on a user's machine. diff --git a/chrome/gpu/gpu_info_collector_linux.cc b/chrome/gpu/gpu_info_collector_linux.cc index 638081d..63f4d34 100644 --- a/chrome/gpu/gpu_info_collector_linux.cc +++ b/chrome/gpu/gpu_info_collector_linux.cc @@ -137,6 +137,21 @@ bool CollectGraphicsInfo(GPUInfo* gpu_info) { return CollectGraphicsInfoGL(gpu_info); } +bool CollectPreliminaryGraphicsInfo(GPUInfo* gpu_info) { + DCHECK(gpu_info); + + gpu_info->SetLevel(GPUInfo::kPartial); + + bool rt = true; + if (!CollectVideoCardInfo(gpu_info)) + rt = false; + + // TODO(zmo): if vendor is ATI, consider passing /etc/ati/amdpcsdb.default + // for driver information. + + return rt; +} + bool CollectVideoCardInfo(GPUInfo* gpu_info) { DCHECK(gpu_info); diff --git a/chrome/gpu/gpu_info_collector_mac.mm b/chrome/gpu/gpu_info_collector_mac.mm index e401e8f..38e10bb 100644 --- a/chrome/gpu/gpu_info_collector_mac.mm +++ b/chrome/gpu/gpu_info_collector_mac.mm @@ -52,11 +52,20 @@ bool CollectGraphicsInfo(GPUInfo* gpu_info) { return CollectGraphicsInfoGL(gpu_info); } -bool CollectVideoCardInfo(GPUInfo* gpu_info) { +bool CollectPreliminaryGraphicsInfo(GPUInfo* gpu_info) { DCHECK(gpu_info); - if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) - return false; + gpu_info->SetLevel(GPUInfo::kPartial); + + bool rt = true; + if (!CollectVideoCardInfo(gpu_info)) + rt = false; + + return rt; +} + +bool CollectVideoCardInfo(GPUInfo* gpu_info) { + DCHECK(gpu_info); UInt32 vendor_id = 0, device_id = 0; io_registry_entry_t dsp_port = CGDisplayIOServicePort(kCGDirectMainDisplay); diff --git a/chrome/gpu/gpu_info_collector_win.cc b/chrome/gpu/gpu_info_collector_win.cc index 84b62d7..b3bca8e 100644 --- a/chrome/gpu/gpu_info_collector_win.cc +++ b/chrome/gpu/gpu_info_collector_win.cc @@ -53,6 +53,18 @@ bool CollectGraphicsInfo(GPUInfo* gpu_info) { return true; } +bool CollectPreliminaryGraphicsInfo(GPUInfo* gpu_info) { + DCHECK(gpu_info); + + gpu_info->SetLevel(GPUInfo::kPartial); + + bool rt = true; + if (!CollectVideoCardInfo(gpu_info)) + rt = false; + + return rt; +} + bool CollectGraphicsInfoD3D(IDirect3D9* d3d, GPUInfo* gpu_info) { DCHECK(d3d); DCHECK(gpu_info); diff --git a/chrome/gpu/gpu_thread.cc b/chrome/gpu/gpu_thread.cc index f9f3341..fce4adb 100644 --- a/chrome/gpu/gpu_thread.cc +++ b/chrome/gpu/gpu_thread.cc @@ -109,6 +109,21 @@ void GpuThread::OnInitialize() { if (!single_process) logging::SetLogMessageHandler(GpuProcessLogMessageHandler); + // Collect as much GPU info as possible without creating GL/D3D context. + gpu_info_collector::CollectPreliminaryGraphicsInfo(&gpu_info_); + LOG(INFO) << "gpu_info_collector::CollectPreliminaryGraphicsInfo complete"; + + // Go through GPU blacklist with partial GPU info; if GPU is already + // blacklisted, don't create GL/D3D context. + bool blacklisted; + Send(new GpuHostMsg_PreliminaryGraphicsInfoCollected(gpu_info_, + &blacklisted)); + if (blacklisted) { + LOG(INFO) << "GPU is blacklisted based on preliminary GPU info collection"; + MessageLoop::current()->Quit(); + return; + } + // Load the GL implementation and locate the bindings before starting the GPU // watchdog because this can take a lot of time and the GPU watchdog might // terminate the GPU process. |