summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-15 22:31:26 +0000
committerapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-15 22:31:26 +0000
commit41579aea1ddb436acb6491e4b79ea564d86b55a0 (patch)
tree42829d8ed9773096be51647be7f73e32b7ba0247 /chrome
parentb7ba5b5e11aaa87de7601daf1ab5443fe41a6f3c (diff)
downloadchromium_src-41579aea1ddb436acb6491e4b79ea564d86b55a0.zip
chromium_src-41579aea1ddb436acb6491e4b79ea564d86b55a0.tar.gz
chromium_src-41579aea1ddb436acb6491e4b79ea564d86b55a0.tar.bz2
Collect DirectX diagnostic information asynchronously.
Collecting this can take a couple of seconds. I put the code onto a worker thread. The about:gpuinfo handler polls for it until it is available, initially displaying only the subset of informtation that can be retreived quickly. This makes the startup time for accelerated compositing, WebGL, etc significantly lower on Windows. None of the other platforms have this issue. TEST=go to about:gpuinfo, try BUG=59711 Review URL: http://codereview.chromium.org/4860001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@66184 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/browser_about_handler.cc33
-rw-r--r--chrome/common/gpu_info.cc14
-rw-r--r--chrome/common/gpu_info.h15
-rw-r--r--chrome/common/gpu_messages.cc87
-rw-r--r--chrome/common/gpu_messages_unittest.cc4
-rw-r--r--chrome/gpu/gpu_info_collector_linux.cc3
-rw-r--r--chrome/gpu/gpu_info_collector_mac.mm2
-rw-r--r--chrome/gpu/gpu_info_collector_win.cc13
-rw-r--r--chrome/gpu/gpu_thread.cc40
-rw-r--r--chrome/gpu/gpu_thread.h5
10 files changed, 148 insertions, 68 deletions
diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc
index 79775e6..b63c88b9b 100644
--- a/chrome/browser/browser_about_handler.cc
+++ b/chrome/browser/browser_about_handler.cc
@@ -761,18 +761,24 @@ std::string AboutGpu() {
GPUInfo gpu_info = GpuProcessHost::Get()->gpu_info();
std::string html;
- if (!gpu_info.initialized()) {
+
+ html.append("<html><head><title>About GPU</title></head>\n");
+
+ if (gpu_info.progress() != GPUInfo::kComplete) {
GpuProcessHostUIShim::Get()->CollectGraphicsInfoAsynchronously();
- // If it's not initialized yet, let the user know and reload the page
- html.append("<html><head><title>About GPU</title></head>\n");
+
+ // If it's not fully initialized yet, set a timeout to reload the page.
html.append("<body onload=\"setTimeout('window.location.reload(true)',");
html.append("2000)\">\n");
- html.append("<h2>GPU Information</h2>\n");
+ } else {
+ html.append("<body>\n");
+ }
+
+ html.append("<h2>GPU Information</h2>\n");
+
+ if (gpu_info.progress() == GPUInfo::kUninitialized) {
html.append("<p>Retrieving GPU information . . .</p>\n");
- html.append("</body></html> ");
} else {
- html.append("<html><head><title>About GPU</title></head><body>\n");
- html.append("<h2>GPU Information</h2>\n");
html.append("<table><tr>");
html.append("<td><strong>Initialization time</strong></td><td>");
html.append(base::Int64ToString(
@@ -799,12 +805,17 @@ std::string AboutGpu() {
html.append("</td></tr></table>");
#if defined(OS_WIN)
- html.append("<h2>DirectX Diagnostics</h2>");
- DxDiagNodeToHTML(&html, gpu_info.dx_diagnostics());
+ if (gpu_info.progress() != GPUInfo::kComplete) {
+ html.append("<p>Retrieving DirectX Diagnostics . . .</p>\n");
+ } else {
+ html.append("<h2>DirectX Diagnostics</h2>");
+ DxDiagNodeToHTML(&html, gpu_info.dx_diagnostics());
+ }
#endif
-
- html.append("</body></html>");
}
+
+ html.append("</body></html>");
+
return html;
}
diff --git a/chrome/common/gpu_info.cc b/chrome/common/gpu_info.cc
index 64f0498..744fdfc 100644
--- a/chrome/common/gpu_info.cc
+++ b/chrome/common/gpu_info.cc
@@ -5,15 +5,18 @@
#include "chrome/common/gpu_info.h"
GPUInfo::GPUInfo()
- : initialized_(false), vendor_id_(0), device_id_(0), driver_version_(L""),
+ : progress_(kUninitialized),
+ vendor_id_(0),
+ device_id_(0),
+ driver_version_(L""),
pixel_shader_version_(0),
vertex_shader_version_(0),
gl_version_(0),
can_lose_context_(false) {
}
-bool GPUInfo::initialized() const {
- return initialized_;
+GPUInfo::Progress GPUInfo::progress() const {
+ return progress_;
}
base::TimeDelta GPUInfo::initialization_time() const {
@@ -68,7 +71,10 @@ void GPUInfo::SetGraphicsInfo(uint32 vendor_id, uint32 device_id,
vertex_shader_version_ = vertex_shader_version;
gl_version_ = gl_version;
can_lose_context_ = can_lose_context;
- initialized_ = true;
+}
+
+void GPUInfo::SetProgress(Progress progress) {
+ progress_ = progress;
}
#if defined(OS_WIN)
diff --git a/chrome/common/gpu_info.h b/chrome/common/gpu_info.h
index bdf8709..b8f7cc6 100644
--- a/chrome/common/gpu_info.h
+++ b/chrome/common/gpu_info.h
@@ -21,8 +21,15 @@ class GPUInfo {
GPUInfo();
~GPUInfo() {}
- // Returns whether this GPUInfo has been initialized with information
- bool initialized() const;
+ enum Progress {
+ kUninitialized,
+ kPartial,
+ kComplete,
+ };
+
+ // Returns whether this GPUInfo has been partially or fully initialized with
+ // information.
+ Progress progress() const;
// The amount of time taken to get from the process starting to the message
// loop being pumped.
@@ -60,6 +67,8 @@ class GPUInfo {
// semantics are available.
bool can_lose_context() const;
+ void SetProgress(Progress progress);
+
void SetInitializationTime(const base::TimeDelta& initialization_time);
// Populate variables with passed in values
@@ -78,7 +87,7 @@ class GPUInfo {
#endif
private:
- bool initialized_;
+ Progress progress_;
base::TimeDelta initialization_time_;
uint32 vendor_id_;
uint32 device_id_;
diff --git a/chrome/common/gpu_messages.cc b/chrome/common/gpu_messages.cc
index d6adda0..1ba2efa 100644
--- a/chrome/common/gpu_messages.cc
+++ b/chrome/common/gpu_messages.cc
@@ -81,14 +81,15 @@ void ParamTraits<GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params> ::Log(
#endif // if defined(OS_MACOSX)
void ParamTraits<GPUInfo> ::Write(Message* m, const param_type& p) {
- ParamTraits<base::TimeDelta> ::Write(m, p.initialization_time());
- m->WriteUInt32(p.vendor_id());
- m->WriteUInt32(p.device_id());
- m->WriteWString(p.driver_version());
- m->WriteUInt32(p.pixel_shader_version());
- m->WriteUInt32(p.vertex_shader_version());
- m->WriteUInt32(p.gl_version());
- m->WriteBool(p.can_lose_context());
+ WriteParam(m, static_cast<int32>(p.progress()));
+ WriteParam(m, p.initialization_time());
+ WriteParam(m, p.vendor_id());
+ WriteParam(m, p.device_id());
+ WriteParam(m, p.driver_version());
+ WriteParam(m, p.pixel_shader_version());
+ WriteParam(m, p.vertex_shader_version());
+ WriteParam(m, p.gl_version());
+ WriteParam(m, p.can_lose_context());
#if defined(OS_WIN)
ParamTraits<DxDiagNode> ::Write(m, p.dx_diagnostics());
@@ -96,6 +97,7 @@ void ParamTraits<GPUInfo> ::Write(Message* m, const param_type& p) {
}
bool ParamTraits<GPUInfo> ::Read(const Message* m, void** iter, param_type* p) {
+ int32 progress;
base::TimeDelta initialization_time;
uint32 vendor_id;
uint32 device_id;
@@ -104,14 +106,16 @@ bool ParamTraits<GPUInfo> ::Read(const Message* m, void** iter, param_type* p) {
uint32 vertex_shader_version;
uint32 gl_version;
bool can_lose_context;
- bool ret = ParamTraits<base::TimeDelta> ::Read(m, iter, &initialization_time);
- ret = ret && m->ReadUInt32(iter, &vendor_id);
- ret = ret && m->ReadUInt32(iter, &device_id);
- ret = ret && m->ReadWString(iter, &driver_version);
- ret = ret && m->ReadUInt32(iter, &pixel_shader_version);
- ret = ret && m->ReadUInt32(iter, &vertex_shader_version);
- ret = ret && m->ReadUInt32(iter, &gl_version);
- ret = ret && m->ReadBool(iter, &can_lose_context);
+ bool ret = ReadParam(m, iter, &progress);
+ ret = ret && ReadParam(m, iter, &initialization_time);
+ ret = ret && ReadParam(m, iter, &vendor_id);
+ ret = ret && ReadParam(m, iter, &device_id);
+ ret = ret && ReadParam(m, iter, &driver_version);
+ ret = ret && ReadParam(m, iter, &pixel_shader_version);
+ ret = ret && ReadParam(m, iter, &vertex_shader_version);
+ ret = ret && ReadParam(m, iter, &gl_version);
+ ret = ret && ReadParam(m, iter, &can_lose_context);
+ p->SetProgress(static_cast<GPUInfo::Progress>(progress));
if (!ret)
return false;
@@ -126,15 +130,18 @@ bool ParamTraits<GPUInfo> ::Read(const Message* m, void** iter, param_type* p) {
#if defined(OS_WIN)
DxDiagNode dx_diagnostics;
- ret = ret && ParamTraits<DxDiagNode> ::Read(m, iter, &dx_diagnostics);
+ if (!ReadParam(m, iter, &dx_diagnostics))
+ return false;
+
p->SetDxDiagnostics(dx_diagnostics);
#endif
- return ret;
+ return true;
}
void ParamTraits<GPUInfo> ::Log(const param_type& p, std::string* l) {
- l->append(base::StringPrintf("<GPUInfo> %d %x %x %ls %d",
+ l->append(base::StringPrintf("<GPUInfo> %d %d %x %x %ls %d",
+ p.progress(),
static_cast<int32>(
p.initialization_time().InMilliseconds()),
p.vendor_id(),
@@ -144,21 +151,15 @@ void ParamTraits<GPUInfo> ::Log(const param_type& p, std::string* l) {
}
void ParamTraits<DxDiagNode> ::Write(Message* m, const param_type& p) {
- ParamTraits<std::map<std::string, std::string> >::Write(m, p.values);
- ParamTraits<std::map<std::string, DxDiagNode> >::Write(m, p.children);
+ WriteParam(m, p.values);
+ WriteParam(m, p.children);
}
bool ParamTraits<DxDiagNode> ::Read(const Message* m,
void** iter,
param_type* p) {
- bool ret = ParamTraits<std::map<std::string, std::string> >::Read(
- m,
- iter,
- &p->values);
- ret = ret && ParamTraits<std::map<std::string, DxDiagNode> >::Read(
- m,
- iter,
- &p->children);
+ bool ret = ReadParam(m, iter, &p->values);
+ ret = ret && ReadParam(m, iter, &p->children);
return ret;
}
@@ -168,22 +169,22 @@ void ParamTraits<DxDiagNode> ::Log(const param_type& p, std::string* l) {
void ParamTraits<gpu::CommandBuffer::State> ::Write(Message* m,
const param_type& p) {
- m->WriteInt(p.num_entries);
- m->WriteInt(p.get_offset);
- m->WriteInt(p.put_offset);
- m->WriteInt(p.token);
- m->WriteInt(p.error);
+ WriteParam(m, p.num_entries);
+ WriteParam(m, p.get_offset);
+ WriteParam(m, p.put_offset);
+ WriteParam(m, p.token);
+ WriteParam(m, static_cast<int32>(p.error));
}
bool ParamTraits<gpu::CommandBuffer::State> ::Read(const Message* m,
void** iter,
param_type* p) {
int32 temp;
- if (m->ReadInt(iter, &p->num_entries) &&
- m->ReadInt(iter, &p->get_offset) &&
- m->ReadInt(iter, &p->put_offset) &&
- m->ReadInt(iter, &p->token) &&
- m->ReadInt(iter, &temp)) {
+ if (ReadParam(m, iter, &p->num_entries) &&
+ ReadParam(m, iter, &p->get_offset) &&
+ ReadParam(m, iter, &p->put_offset) &&
+ ReadParam(m, iter, &p->token) &&
+ ReadParam(m, iter, &temp)) {
p->error = static_cast<gpu::error::Error>(temp);
return true;
} else {
@@ -198,14 +199,14 @@ void ParamTraits<gpu::CommandBuffer::State> ::Log(const param_type& p,
void ParamTraits<GPUCreateCommandBufferConfig> ::Write(
Message* m, const param_type& p) {
- m->WriteString(p.allowed_extensions);
- ParamTraits<std::vector<int> > ::Write(m, p.attribs);
+ WriteParam(m, p.allowed_extensions);
+ WriteParam(m, p.attribs);
}
bool ParamTraits<GPUCreateCommandBufferConfig> ::Read(
const Message* m, void** iter, param_type* p) {
- if (!m->ReadString(iter, &p->allowed_extensions) ||
- !ParamTraits<std::vector<int> > ::Read(m, iter, &p->attribs)) {
+ if (!ReadParam(m, iter, &p->allowed_extensions) ||
+ !ReadParam(m, iter, &p->attribs)) {
return false;
}
return true;
diff --git a/chrome/common/gpu_messages_unittest.cc b/chrome/common/gpu_messages_unittest.cc
index 59d42ed..904d9da 100644
--- a/chrome/common/gpu_messages_unittest.cc
+++ b/chrome/common/gpu_messages_unittest.cc
@@ -13,6 +13,7 @@
TEST(GPUIPCMessageTest, GPUInfo) {
GPUInfo input;
// Test variables taken from Lenovo T61
+ input.SetProgress(GPUInfo::kPartial);
input.SetInitializationTime(base::TimeDelta::FromMilliseconds(100));
input.SetGraphicsInfo(0x10de, 0x429, L"6.14.11.7715",
0xffff0300,
@@ -26,6 +27,7 @@ TEST(GPUIPCMessageTest, GPUInfo) {
GPUInfo output;
void* iter = NULL;
EXPECT_TRUE(IPC::ReadParam(&msg, &iter, &output));
+ EXPECT_EQ(input.progress(), output.progress());
EXPECT_EQ(input.initialization_time().InMilliseconds(),
output.initialization_time().InMilliseconds());
EXPECT_EQ(input.vendor_id(), output.vendor_id());
@@ -38,5 +40,5 @@ TEST(GPUIPCMessageTest, GPUInfo) {
std::string log_message;
IPC::LogParam(output, &log_message);
- EXPECT_STREQ("<GPUInfo> 100 10de 429 6.14.11.7715 1", log_message.c_str());
+ EXPECT_STREQ("<GPUInfo> 1 100 10de 429 6.14.11.7715 1", log_message.c_str());
}
diff --git a/chrome/gpu/gpu_info_collector_linux.cc b/chrome/gpu/gpu_info_collector_linux.cc
index 2a4db9a..fd48c83 100644
--- a/chrome/gpu/gpu_info_collector_linux.cc
+++ b/chrome/gpu/gpu_info_collector_linux.cc
@@ -12,6 +12,9 @@ bool CollectGraphicsInfo(GPUInfo* gpu_info) {
// on this platform in the future.
// bool can_lose_context =
// gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2;
+
+ gpu_info->SetProgress(GPUInfo::kComplete);
+
return true;
}
diff --git a/chrome/gpu/gpu_info_collector_mac.mm b/chrome/gpu/gpu_info_collector_mac.mm
index 02c12b0..9da958c 100644
--- a/chrome/gpu/gpu_info_collector_mac.mm
+++ b/chrome/gpu/gpu_info_collector_mac.mm
@@ -163,6 +163,8 @@ bool CollectGraphicsInfo(GPUInfo* gpu_info) {
gl_version,
false);
+ gpu_info->SetProgress(GPUInfo::kComplete);
+
return true;
}
diff --git a/chrome/gpu/gpu_info_collector_win.cc b/chrome/gpu/gpu_info_collector_win.cc
index b5d30b4..f1ed1f8 100644
--- a/chrome/gpu/gpu_info_collector_win.cc
+++ b/chrome/gpu/gpu_info_collector_win.cc
@@ -37,13 +37,14 @@ bool CollectGraphicsInfo(GPUInfo* gpu_info) {
if (FAILED(device->GetDirect3D(&d3d)))
return false;
- // Don't fail if DirectX diagnostics are not available. Just leave the tree
- // empty. The other GPU info is still valuable.
- DxDiagNode dx_diagnostics;
- if (GetDxDiagnostics(&dx_diagnostics))
- gpu_info->SetDxDiagnostics(dx_diagnostics);
+ if (!CollectGraphicsInfoD3D(d3d, gpu_info))
+ return false;
+
+ // DirectX diagnostics are collected asynchronously because it takes a
+ // couple of seconds. Do not mark as complete until that is done.
+ gpu_info->SetProgress(GPUInfo::kPartial);
- return CollectGraphicsInfoD3D(d3d, gpu_info);
+ return true;
}
bool CollectGraphicsInfoD3D(IDirect3D9* d3d, GPUInfo* gpu_info) {
diff --git a/chrome/gpu/gpu_thread.cc b/chrome/gpu/gpu_thread.cc
index 9dc57d8..e278bec 100644
--- a/chrome/gpu/gpu_thread.cc
+++ b/chrome/gpu/gpu_thread.cc
@@ -9,6 +9,7 @@
#include "app/gfx/gl/gl_context.h"
#include "base/command_line.h"
+#include "base/worker_pool.h"
#include "build/build_config.h"
#include "chrome/common/child_process.h"
#include "chrome/common/child_process_logging.h"
@@ -16,6 +17,10 @@
#include "chrome/gpu/gpu_info_collector.h"
#include "ipc/ipc_channel_handle.h"
+#if defined(OS_WIN)
+#include "app/win_util.h"
+#endif
+
#if defined(TOOLKIT_USES_GTK)
#include <gtk/gtk.h>
#include "app/x11_util.h"
@@ -44,6 +49,18 @@ void GpuThread::Init(const base::Time& process_start_time) {
gpu_info_collector::CollectGraphicsInfo(&gpu_info_);
child_process_logging::SetGpuInfo(gpu_info_);
+#if defined(OS_WIN)
+ // Asynchronously collect the DirectX diagnostics because this can take a
+ // couple of seconds.
+ if (!WorkerPool::PostTask(
+ FROM_HERE,
+ NewRunnableFunction(&GpuThread::CollectDxDiagnostics, this),
+ true)) {
+ // Flag GPU info as complete if the DirectX diagnostics cannot be collected.
+ gpu_info_.SetProgress(GPUInfo::kComplete);
+ }
+#endif
+
// Record initialization only after collecting the GPU info because that can
// take a significant amount of time.
gpu_info_.SetInitializationTime(base::Time::Now() - process_start_time);
@@ -118,3 +135,26 @@ void GpuThread::OnHang() {
for (;;)
PlatformThread::Sleep(1000);
}
+
+#if defined(OS_WIN)
+
+// Runs on a worker thread. The GpuThread never terminates voluntarily so it is
+// safe to assume that its message loop is valid.
+void GpuThread::CollectDxDiagnostics(GpuThread* thread) {
+ win_util::ScopedCOMInitializer com_initializer;
+
+ DxDiagNode node;
+ gpu_info_collector::GetDxDiagnostics(&node);
+
+ thread->message_loop()->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(&GpuThread::SetDxDiagnostics, thread, node));
+}
+
+// Runs on the GPU thread.
+void GpuThread::SetDxDiagnostics(GpuThread* thread, const DxDiagNode& node) {
+ thread->gpu_info_.SetDxDiagnostics(node);
+ thread->gpu_info_.SetProgress(GPUInfo::kComplete);
+}
+
+#endif
diff --git a/chrome/gpu/gpu_thread.h b/chrome/gpu/gpu_thread.h
index 56d4b431..275fa12 100644
--- a/chrome/gpu/gpu_thread.h
+++ b/chrome/gpu/gpu_thread.h
@@ -38,6 +38,11 @@ class GpuThread : public ChildThread {
void OnCrash();
void OnHang();
+#if defined(OS_WIN)
+ static void CollectDxDiagnostics(GpuThread* thread);
+ static void SetDxDiagnostics(GpuThread* thread, const DxDiagNode& node);
+#endif
+
typedef base::hash_map<int, scoped_refptr<GpuChannel> > GpuChannelMap;
GpuChannelMap gpu_channels_;