summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzmo@google.com <zmo@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-19 00:05:57 +0000
committerzmo@google.com <zmo@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-19 00:05:57 +0000
commit079c4ad1af9ba5bbac595bd126540c5f4744e3a3 (patch)
tree8ddc008ca3b8c9d8b95defd9eef3ef2f3ea1e818
parent8b70f1e6b4909378f23fe1ebd6a75db6919a7155 (diff)
downloadchromium_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.cc34
-rw-r--r--chrome/browser/gpu_blacklist.h8
-rw-r--r--chrome/browser/gpu_process_host_ui_shim.cc49
-rw-r--r--chrome/browser/gpu_process_host_ui_shim.h2
-rw-r--r--chrome/common/gpu_messages_internal.h6
-rw-r--r--chrome/gpu/gpu_info_collector.h5
-rw-r--r--chrome/gpu/gpu_info_collector_linux.cc15
-rw-r--r--chrome/gpu/gpu_info_collector_mac.mm15
-rw-r--r--chrome/gpu/gpu_info_collector_win.cc12
-rw-r--r--chrome/gpu/gpu_thread.cc15
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.