summaryrefslogtreecommitdiffstats
path: root/content/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'content/gpu')
-rw-r--r--content/gpu/gpu_channel.cc22
-rw-r--r--content/gpu/gpu_channel.h19
-rw-r--r--content/gpu/gpu_child_thread.cc (renamed from content/gpu/gpu_thread.cc)194
-rw-r--r--content/gpu/gpu_child_thread.h (renamed from content/gpu/gpu_thread.h)58
-rw-r--r--content/gpu/gpu_command_buffer_stub.cc26
-rw-r--r--content/gpu/gpu_main.cc14
-rw-r--r--content/gpu/gpu_render_thread.cc146
-rw-r--r--content/gpu/gpu_render_thread.h91
8 files changed, 365 insertions, 205 deletions
diff --git a/content/gpu/gpu_channel.cc b/content/gpu/gpu_channel.cc
index 622c213..cd41c92 100644
--- a/content/gpu/gpu_channel.cc
+++ b/content/gpu/gpu_channel.cc
@@ -14,20 +14,20 @@
#include "content/common/child_process.h"
#include "content/common/content_switches.h"
#include "content/common/gpu_messages.h"
-#include "content/gpu/gpu_thread.h"
+#include "content/gpu/gpu_render_thread.h"
#include "content/gpu/gpu_video_service.h"
#if defined(OS_POSIX)
#include "ipc/ipc_channel_posix.h"
#endif
-GpuChannel::GpuChannel(GpuThread* gpu_thread,
+GpuChannel::GpuChannel(GpuRenderThread* gpu_render_thread,
int renderer_id)
- : gpu_thread_(gpu_thread),
+ : gpu_render_thread_(gpu_render_thread),
renderer_id_(renderer_id),
renderer_process_(NULL),
renderer_pid_(NULL) {
- DCHECK(gpu_thread);
+ DCHECK(gpu_render_thread);
DCHECK(renderer_id);
const CommandLine* command_line = CommandLine::ForCurrentProcess();
log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages);
@@ -65,7 +65,7 @@ bool GpuChannel::OnMessageReceived(const IPC::Message& message) {
}
void GpuChannel::OnChannelError() {
- gpu_thread_->RemoveChannel(renderer_id_);
+ gpu_render_thread_->RemoveChannel(renderer_id_);
}
void GpuChannel::OnChannelConnected(int32 peer_pid) {
@@ -233,7 +233,8 @@ void GpuChannel::OnDestroyVideoDecoder(int32 decoder_id) {
#endif
}
-bool GpuChannel::Init() {
+bool GpuChannel::Init(MessageLoop* io_message_loop,
+ base::WaitableEvent* shutdown_event) {
// Check whether we're already initialized.
if (channel_.get())
return true;
@@ -241,9 +242,12 @@ bool GpuChannel::Init() {
// Map renderer ID to a (single) channel to that process.
std::string channel_name = GetChannelName();
channel_.reset(new IPC::SyncChannel(
- channel_name, IPC::Channel::MODE_SERVER, this,
- ChildProcess::current()->io_message_loop(), false,
- ChildProcess::current()->GetShutDownEvent()));
+ channel_name,
+ IPC::Channel::MODE_SERVER,
+ this,
+ io_message_loop,
+ false,
+ shutdown_event));
return true;
}
diff --git a/content/gpu/gpu_channel.h b/content/gpu/gpu_channel.h
index 5e24a4c..b8cd921 100644
--- a/content/gpu/gpu_channel.h
+++ b/content/gpu/gpu_channel.h
@@ -20,8 +20,13 @@
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
-class GpuThread;
+class GpuRenderThread;
struct GPUCreateCommandBufferConfig;
+class MessageLoop;
+
+namespace base {
+class WaitableEvent;
+}
// Encapsulates an IPC channel between the GPU process and one renderer
// process. On the renderer side there's a corresponding GpuChannelHost.
@@ -30,14 +35,14 @@ class GpuChannel : public IPC::Channel::Listener,
public base::RefCountedThreadSafe<GpuChannel> {
public:
// Takes ownership of the renderer process handle.
- GpuChannel(GpuThread* gpu_thread,
+ GpuChannel(GpuRenderThread* gpu_render_thread,
int renderer_id);
virtual ~GpuChannel();
- bool Init();
+ bool Init(MessageLoop* io_message_loop, base::WaitableEvent* shutdown_event);
// Get the GpuThread that owns this channel.
- GpuThread* gpu_thread() const { return gpu_thread_; }
+ GpuRenderThread* gpu_render_thread() const { return gpu_render_thread_; }
// Returns the name of the associated IPC channel.
std::string GetChannelName();
@@ -89,10 +94,10 @@ class GpuChannel : public IPC::Channel::Listener,
int32 decoder_host_id);
void OnDestroyVideoDecoder(int32 decoder_id);
- // The lifetime of objects of this class is managed by a GpuThread. The
- // GpuThreadss destroy all the GpuChannels that they own when they
+ // The lifetime of objects of this class is managed by a GpuRenderThread. The
+ // GpuRenderThreads destroy all the GpuChannels that they own when they
// are destroyed. So a raw pointer is safe.
- GpuThread* gpu_thread_;
+ GpuRenderThread* gpu_render_thread_;
scoped_ptr<IPC::SyncChannel> channel_;
diff --git a/content/gpu/gpu_thread.cc b/content/gpu/gpu_child_thread.cc
index e8fd331..a9db8c7 100644
--- a/content/gpu/gpu_thread.cc
+++ b/content/gpu/gpu_child_thread.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/gpu/gpu_thread.h"
+#include "content/gpu/gpu_child_thread.h"
#include <string>
#include <vector>
@@ -13,8 +13,8 @@
#include "base/command_line.h"
#include "base/threading/worker_pool.h"
#include "build/build_config.h"
+#include "chrome/common/chrome_switches.h"
#include "content/common/child_process.h"
-#include "content/common/content_switches.h"
#include "content/common/gpu_messages.h"
#include "content/gpu/content_gpu_client.h"
#include "content/gpu/gpu_info_collector.h"
@@ -44,19 +44,30 @@ bool InitializeGpuSandbox() {
#endif
}
+bool GpuProcessLogMessageHandler(int severity,
+ const char* file, int line,
+ size_t message_start,
+ const std::string& str) {
+ std::string header = str.substr(0, message_start);
+ std::string message = str.substr(message_start);
+ ChildThread::current()->Send(
+ new GpuHostMsg_OnLogMessage(severity, header, message));
+ return false;
+}
+
} // namespace
#if defined(OS_WIN)
-GpuThread::GpuThread(sandbox::TargetServices* target_services)
+GpuChildThread::GpuChildThread(sandbox::TargetServices* target_services)
: target_services_(target_services),
collecting_dx_diagnostics_(false) {
}
#else
-GpuThread::GpuThread() {
+GpuChildThread::GpuChildThread() {
}
#endif
-GpuThread::GpuThread(const std::string& channel_id)
+GpuChildThread::GpuChildThread(const std::string& channel_id)
: ChildThread(channel_id) {
#if defined(OS_WIN)
target_services_ = NULL;
@@ -64,64 +75,44 @@ GpuThread::GpuThread(const std::string& channel_id)
}
-GpuThread::~GpuThread() {
+GpuChildThread::~GpuChildThread() {
logging::SetLogMessageHandler(NULL);
}
-void GpuThread::Init(const base::Time& process_start_time) {
+void GpuChildThread::Init(const base::Time& process_start_time) {
process_start_time_ = process_start_time;
}
-void GpuThread::RemoveChannel(int renderer_id) {
- gpu_channels_.erase(renderer_id);
+bool GpuChildThread::Send(IPC::Message* msg) {
+ // The GPU process must never send a synchronous IPC message to the browser
+ // process. This could result in deadlock. Unfortunately linux does this for
+ // GpuHostMsg_ResizeXID. TODO(apatrick): fix this before issuing any GL calls
+ // on the browser process' GPU thread.
+#if !defined(OS_LINUX)
+ DCHECK(!msg->is_sync());
+#endif
+
+ return ChildThread::Send(msg);
}
-bool GpuThread::OnControlMessageReceived(const IPC::Message& msg) {
+bool GpuChildThread::OnControlMessageReceived(const IPC::Message& msg) {
bool msg_is_ok = true;
bool handled = true;
- IPC_BEGIN_MESSAGE_MAP_EX(GpuThread, msg, msg_is_ok)
+ IPC_BEGIN_MESSAGE_MAP_EX(GpuChildThread, msg, msg_is_ok)
IPC_MESSAGE_HANDLER(GpuMsg_Initialize, OnInitialize)
- IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel)
- IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel)
- IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer,
- OnCreateViewCommandBuffer);
- IPC_MESSAGE_HANDLER(GpuMsg_Synchronize, OnSynchronize)
IPC_MESSAGE_HANDLER(GpuMsg_CollectGraphicsInfo, OnCollectGraphicsInfo)
-#if defined(OS_MACOSX)
- IPC_MESSAGE_HANDLER(GpuMsg_AcceleratedSurfaceBuffersSwappedACK,
- OnAcceleratedSurfaceBuffersSwappedACK)
- IPC_MESSAGE_HANDLER(GpuMsg_DestroyCommandBuffer,
- OnDestroyCommandBuffer)
-#endif
IPC_MESSAGE_HANDLER(GpuMsg_Crash, OnCrash)
IPC_MESSAGE_HANDLER(GpuMsg_Hang, OnHang)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP_EX()
- return handled;
-}
-namespace {
+ if (handled)
+ return true;
-bool GpuProcessLogMessageHandler(int severity,
- const char* file, int line,
- size_t message_start,
- const std::string& str) {
- std::string header = str.substr(0, message_start);
- std::string message = str.substr(message_start);
- ChildThread::current()->Send(
- new GpuHostMsg_OnLogMessage(severity, header, message));
- return false;
+ return render_thread_.get() && render_thread_->OnMessageReceived(msg);
}
-} // namespace
-
-void GpuThread::OnInitialize() {
- // Redirect LOG messages to the GpuProcessHost
- bool single_process = CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kSingleProcess);
- if (!single_process)
- logging::SetLogMessageHandler(GpuProcessLogMessageHandler);
-
+void GpuChildThread::OnInitialize() {
// 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.
@@ -191,60 +182,27 @@ void GpuThread::OnInitialize() {
watchdog_thread_ = new GpuWatchdogThread(kGpuTimeout);
watchdog_thread_->Start();
}
-}
-void GpuThread::StopWatchdog() {
- if (watchdog_thread_.get()) {
- watchdog_thread_->Stop();
- }
-}
-
-void GpuThread::OnEstablishChannel(int renderer_id) {
- scoped_refptr<GpuChannel> channel;
- IPC::ChannelHandle channel_handle;
- GPUInfo gpu_info;
-
- GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id);
- if (iter == gpu_channels_.end())
- channel = new GpuChannel(this, renderer_id);
- else
- channel = iter->second;
-
- DCHECK(channel != NULL);
-
- if (channel->Init())
- gpu_channels_[renderer_id] = channel;
- else
- channel = NULL;
-
- if (channel.get()) {
- channel_handle.name = channel->GetChannelName();
-#if defined(OS_POSIX)
- // On POSIX, pass the renderer-side FD. Also mark it as auto-close so
- // that it gets closed after it has been sent.
- int renderer_fd = channel->GetRendererFileDescriptor();
- channel_handle.socket = base::FileDescriptor(renderer_fd, false);
-#endif
- }
+ // Defer creation of the render thread. This is to prevent it from handling
+ // IPC messages before the sandbox has been enabled and all other necessary
+ // initialization has succeeded.
+ render_thread_.reset(new GpuRenderThread(
+ this,
+ ChildProcess::current()->io_message_loop(),
+ ChildProcess::current()->GetShutDownEvent()));
- Send(new GpuHostMsg_ChannelEstablished(channel_handle, gpu_info_));
+ // Ensure the browser process receives the GPU info before a reply to any
+ // subsequent IPC it might send.
+ Send(new GpuHostMsg_GraphicsInfoCollected(gpu_info_));
}
-void GpuThread::OnCloseChannel(const IPC::ChannelHandle& channel_handle) {
- for (GpuChannelMap::iterator iter = gpu_channels_.begin();
- iter != gpu_channels_.end(); ++iter) {
- if (iter->second->GetChannelName() == channel_handle.name) {
- gpu_channels_.erase(iter);
- return;
- }
+void GpuChildThread::StopWatchdog() {
+ if (watchdog_thread_.get()) {
+ watchdog_thread_->Stop();
}
}
-void GpuThread::OnSynchronize() {
- Send(new GpuHostMsg_SynchronizeReply());
-}
-
-void GpuThread::OnCollectGraphicsInfo() {
+void GpuChildThread::OnCollectGraphicsInfo() {
#if defined(OS_WIN)
if (!gpu_info_.finalized && !collecting_dx_diagnostics_) {
// Prevent concurrent collection of DirectX diagnostics.
@@ -254,9 +212,8 @@ void GpuThread::OnCollectGraphicsInfo() {
// couple of seconds.
if (!base::WorkerPool::PostTask(
FROM_HERE,
- NewRunnableFunction(&GpuThread::CollectDxDiagnostics, this),
+ NewRunnableFunction(&GpuChildThread::CollectDxDiagnostics, this),
true)) {
-
// Flag GPU info as complete if the DirectX diagnostics cannot be
// collected.
collecting_dx_diagnostics_ = false;
@@ -270,50 +227,14 @@ void GpuThread::OnCollectGraphicsInfo() {
Send(new GpuHostMsg_GraphicsInfoCollected(gpu_info_));
}
-void GpuThread::OnCreateViewCommandBuffer(
- gfx::PluginWindowHandle window,
- int32 render_view_id,
- int32 renderer_id,
- const GPUCreateCommandBufferConfig& init_params) {
- int32 route_id = MSG_ROUTING_NONE;
-
- GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id);
- if (iter != gpu_channels_.end()) {
- iter->second->CreateViewCommandBuffer(
- window, render_view_id, init_params, &route_id);
- }
-
- Send(new GpuHostMsg_CommandBufferCreated(route_id));
-}
-
-#if defined(OS_MACOSX)
-void GpuThread::OnAcceleratedSurfaceBuffersSwappedACK(
- int renderer_id, int32 route_id, uint64 swap_buffers_count) {
- GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id);
- if (iter == gpu_channels_.end())
- return;
- scoped_refptr<GpuChannel> channel = iter->second;
- channel->AcceleratedSurfaceBuffersSwapped(route_id, swap_buffers_count);
-}
-
-void GpuThread::OnDestroyCommandBuffer(
- int renderer_id, int32 render_view_id) {
- GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id);
- if (iter == gpu_channels_.end())
- return;
- scoped_refptr<GpuChannel> channel = iter->second;
- channel->DestroyCommandBufferByViewId(render_view_id);
-}
-#endif
-
-void GpuThread::OnCrash() {
+void GpuChildThread::OnCrash() {
LOG(INFO) << "GPU: Simulating GPU crash";
// Good bye, cruel world.
volatile int* it_s_the_end_of_the_world_as_we_know_it = NULL;
*it_s_the_end_of_the_world_as_we_know_it = 0xdead;
}
-void GpuThread::OnHang() {
+void GpuChildThread::OnHang() {
LOG(INFO) << "GPU: Simulating GPU hang";
for (;;) {
// Do not sleep here. The GPU watchdog timer tracks the amount of user
@@ -323,9 +244,9 @@ void GpuThread::OnHang() {
#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) {
+// Runs on a worker thread. The GPU process never terminates voluntarily so
+// it is safe to assume that its message loop is valid.
+void GpuChildThread::CollectDxDiagnostics(GpuChildThread* thread) {
app::win::ScopedCOMInitializer com_initializer;
DxDiagNode node;
@@ -333,11 +254,12 @@ void GpuThread::CollectDxDiagnostics(GpuThread* thread) {
thread->message_loop()->PostTask(
FROM_HERE,
- NewRunnableFunction(&GpuThread::SetDxDiagnostics, thread, node));
+ NewRunnableFunction(&GpuChildThread::SetDxDiagnostics, thread, node));
}
-// Runs on the GPU thread.
-void GpuThread::SetDxDiagnostics(GpuThread* thread, const DxDiagNode& node) {
+// Runs on the main thread.
+void GpuChildThread::SetDxDiagnostics(GpuChildThread* thread,
+ const DxDiagNode& node) {
thread->gpu_info_.dx_diagnostics = node;
thread->gpu_info_.finalized = true;
thread->collecting_dx_diagnostics_ = false;
diff --git a/content/gpu/gpu_thread.h b/content/gpu/gpu_child_thread.h
index 0baf864..7f1350f 100644
--- a/content/gpu/gpu_thread.h
+++ b/content/gpu/gpu_child_thread.h
@@ -2,14 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_GPU_GPU_THREAD_H_
-#define CONTENT_GPU_GPU_THREAD_H_
+#ifndef CONTENT_GPU_GPU_CHILD_THREAD_H_
+#define CONTENT_GPU_GPU_CHILD_THREAD_H_
#pragma once
#include <string>
#include "base/basictypes.h"
#include "base/command_line.h"
+#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "base/time.h"
#include "build/build_config.h"
@@ -17,6 +18,7 @@
#include "content/common/gpu_info.h"
#include "content/gpu/gpu_channel.h"
#include "content/gpu/gpu_config.h"
+#include "content/gpu/gpu_render_thread.h"
#include "content/gpu/x_util.h"
#include "ui/gfx/native_widget_types.h"
@@ -30,62 +32,45 @@ class TargetServices;
class GpuWatchdogThread;
-class GpuThread : public ChildThread {
+// The main thread of the GPU child process. There will only ever be one of
+// these per process. It does process initialization and shutdown. It forwards
+// IPC messages to GpuRenderThread, which is responsible for issuing rendering
+// commands to the GPU.
+class GpuChildThread : public ChildThread {
public:
#if defined(OS_WIN)
- explicit GpuThread(sandbox::TargetServices* target_services);
+ explicit GpuChildThread(sandbox::TargetServices* target_services);
#else
- GpuThread();
+ GpuChildThread();
#endif
// For single-process mode.
- explicit GpuThread(const std::string& channel_id);
+ explicit GpuChildThread(const std::string& channel_id);
- ~GpuThread();
+ ~GpuChildThread();
void Init(const base::Time& process_start_time);
void StopWatchdog();
- // Remove the channel for a particular renderer.
- void RemoveChannel(int renderer_id);
-
- private:
// ChildThread overrides.
+ virtual bool Send(IPC::Message* msg);
virtual bool OnControlMessageReceived(const IPC::Message& msg);
+ private:
// Message handlers.
void OnInitialize();
- void OnEstablishChannel(int renderer_id);
- void OnCloseChannel(const IPC::ChannelHandle& channel_handle);
- void OnSynchronize();
void OnCollectGraphicsInfo();
- void OnCreateViewCommandBuffer(
- gfx::PluginWindowHandle window,
- int32 render_view_id,
- int32 renderer_id,
- const GPUCreateCommandBufferConfig& init_params);
-#if defined(OS_MACOSX)
- void OnAcceleratedSurfaceBuffersSwappedACK(
- int renderer_id, int32 route_id, uint64 swap_buffers_count);
- void OnDestroyCommandBuffer(int renderer_id, int32 render_view_id);
-#endif
void OnCrash();
void OnHang();
#if defined(OS_WIN)
- static void CollectDxDiagnostics(GpuThread* thread);
- static void SetDxDiagnostics(GpuThread* thread, const DxDiagNode& node);
+ static void CollectDxDiagnostics(GpuChildThread* thread);
+ static void SetDxDiagnostics(GpuChildThread* thread, const DxDiagNode& node);
#endif
base::Time process_start_time_;
scoped_refptr<GpuWatchdogThread> watchdog_thread_;
- typedef base::hash_map<int, scoped_refptr<GpuChannel> > GpuChannelMap;
- GpuChannelMap gpu_channels_;
-
- // Information about the GPU, such as device and vendor ID.
- GPUInfo gpu_info_;
-
#if defined(OS_WIN)
// Windows specific client sandbox interface.
sandbox::TargetServices* target_services_;
@@ -94,7 +79,12 @@ class GpuThread : public ChildThread {
bool collecting_dx_diagnostics_;
#endif
- DISALLOW_COPY_AND_ASSIGN(GpuThread);
+ scoped_ptr<GpuRenderThread> render_thread_;
+
+ // Information about the GPU, such as device and vendor ID.
+ GPUInfo gpu_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuChildThread);
};
-#endif // CONTENT_GPU_GPU_THREAD_H_
+#endif // CONTENT_GPU_GPU_CHILD_THREAD_H_
diff --git a/content/gpu/gpu_command_buffer_stub.cc b/content/gpu/gpu_command_buffer_stub.cc
index 0347a60..d5c0bef 100644
--- a/content/gpu/gpu_command_buffer_stub.cc
+++ b/content/gpu/gpu_command_buffer_stub.cc
@@ -7,11 +7,11 @@
#include "base/process_util.h"
#include "base/shared_memory.h"
#include "build/build_config.h"
-#include "content/common/child_thread.h"
#include "content/common/gpu_messages.h"
+#include "content/common/child_thread.h"
#include "content/gpu/gpu_channel.h"
#include "content/gpu/gpu_command_buffer_stub.h"
-#include "content/gpu/gpu_thread.h"
+#include "content/gpu/gpu_render_thread.h"
#include "gpu/common/gpu_trace_event.h"
using gpu::Buffer;
@@ -140,8 +140,8 @@ bool GpuCommandBufferStub::CreateCompositorWindow() {
}
void GpuCommandBufferStub::OnCompositorWindowPainted() {
- GpuThread* gpu_thread = channel_->gpu_thread();
- gpu_thread->Send(new GpuHostMsg_ScheduleComposite(
+ GpuRenderThread* render_thread = channel_->gpu_render_thread();
+ render_thread->Send(new GpuHostMsg_ScheduleComposite(
renderer_id_, render_view_id_));
}
#endif // defined(OS_WIN)
@@ -158,8 +158,8 @@ GpuCommandBufferStub::~GpuCommandBufferStub() {
}
#endif // defined(OS_WIN)
- GpuThread* gpu_thread = channel_->gpu_thread();
- gpu_thread->Send(new GpuHostMsg_DestroyCommandBuffer(
+ GpuRenderThread* render_thread = channel_->gpu_render_thread();
+ render_thread->Send(new GpuHostMsg_DestroyCommandBuffer(
handle_, renderer_id_, render_view_id_));
}
@@ -353,7 +353,7 @@ void GpuCommandBufferStub::OnSwapBuffers() {
#if defined(OS_MACOSX)
void GpuCommandBufferStub::OnSetWindowSize(const gfx::Size& size) {
- GpuThread* gpu_thread = channel_->gpu_thread();
+ GpuRenderThread* gpu_render_thread = channel_->gpu_render_thread();
// Try using the IOSurface version first.
uint64 new_backing_store = processor_->SetWindowSizeForIOSurface(size);
if (new_backing_store) {
@@ -364,7 +364,8 @@ void GpuCommandBufferStub::OnSetWindowSize(const gfx::Size& size) {
params.width = size.width();
params.height = size.height();
params.identifier = new_backing_store;
- gpu_thread->Send(new GpuHostMsg_AcceleratedSurfaceSetIOSurface(params));
+ gpu_render_thread->Send(
+ new GpuHostMsg_AcceleratedSurfaceSetIOSurface(params));
} else {
// TODO(kbr): figure out what to do here. It wouldn't be difficult
// to support the compositor on 10.5, but the performance would be
@@ -375,7 +376,7 @@ void GpuCommandBufferStub::OnSetWindowSize(const gfx::Size& size) {
void GpuCommandBufferStub::SwapBuffersCallback() {
OnSwapBuffers();
- GpuThread* gpu_thread = channel_->gpu_thread();
+ GpuRenderThread* gpu_render_thread = channel_->gpu_render_thread();
GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
params.renderer_id = renderer_id_;
params.render_view_id = render_view_id_;
@@ -383,7 +384,8 @@ void GpuCommandBufferStub::SwapBuffersCallback() {
params.surface_id = processor_->GetSurfaceId();
params.route_id = route_id();
params.swap_buffers_count = processor_->swap_buffers_count();
- gpu_thread->Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
+ gpu_render_thread->Send(
+ new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
}
void GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped(
@@ -400,9 +402,9 @@ void GpuCommandBufferStub::ResizeCallback(gfx::Size size) {
processor_->decoder()->UpdateOffscreenFrameBufferSize();
} else {
#if defined(OS_LINUX) && !defined(TOUCH_UI)
- GpuThread* gpu_thread = channel_->gpu_thread();
+ GpuRenderThread* gpu_render_thread = channel_->gpu_render_thread();
bool result = false;
- gpu_thread->Send(
+ gpu_render_thread->Send(
new GpuHostMsg_ResizeXID(handle_, size, &result));
#elif defined(OS_WIN)
HWND hwnd = static_cast<HWND>(compositor_window_);
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
index ec79ba9..4076ad8 100644
--- a/content/gpu/gpu_main.cc
+++ b/content/gpu/gpu_main.cc
@@ -16,9 +16,9 @@
#include "build/build_config.h"
#include "content/common/content_switches.h"
#include "content/common/main_function_params.h"
+#include "content/gpu/gpu_child_thread.h"
#include "content/gpu/gpu_config.h"
#include "content/gpu/gpu_process.h"
-#include "content/gpu/gpu_thread.h"
#if defined(OS_MACOSX)
#include "content/common/chrome_application_mac.h"
@@ -68,20 +68,20 @@ int GpuMain(const MainFunctionParams& parameters) {
// the GpuMsg_Initialize message from the browser.
GpuProcess gpu_process;
- GpuThread* gpu_thread =
+ GpuChildThread* child_thread =
#if defined(OS_WIN)
- new GpuThread(parameters.sandbox_info_.TargetServices());
+ new GpuChildThread(parameters.sandbox_info_.TargetServices());
#else
- new GpuThread;
+ new GpuChildThread;
#endif
- gpu_thread->Init(start_time);
+ child_thread->Init(start_time);
- gpu_process.set_main_thread(gpu_thread);
+ gpu_process.set_main_thread(child_thread);
main_message_loop.Run();
- gpu_thread->StopWatchdog();
+ child_thread->StopWatchdog();
return 0;
}
diff --git a/content/gpu/gpu_render_thread.cc b/content/gpu/gpu_render_thread.cc
new file mode 100644
index 0000000..99d9e58
--- /dev/null
+++ b/content/gpu/gpu_render_thread.cc
@@ -0,0 +1,146 @@
+// 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 "content/gpu/gpu_render_thread.h"
+
+#include <string>
+#include <vector>
+
+#include "app/gfx/gl/gl_context.h"
+#include "app/gfx/gl/gl_implementation.h"
+#include "app/win/scoped_com_initializer.h"
+#include "base/command_line.h"
+#include "base/threading/worker_pool.h"
+#include "build/build_config.h"
+#include "chrome/common/child_process_logging.h"
+#include "chrome/common/chrome_switches.h"
+#include "content/common/child_process.h"
+#include "content/common/gpu_messages.h"
+#include "content/gpu/gpu_child_thread.h"
+#include "content/gpu/gpu_info_collector.h"
+#include "content/gpu/gpu_watchdog_thread.h"
+#include "ipc/ipc_channel_handle.h"
+
+GpuRenderThread::GpuRenderThread(IPC::Message::Sender* browser_channel,
+ MessageLoop* io_message_loop,
+ base::WaitableEvent* shutdown_event)
+ : io_message_loop_(io_message_loop),
+ shutdown_event_(shutdown_event),
+ browser_channel_(browser_channel) {
+ DCHECK(browser_channel);
+ DCHECK(io_message_loop);
+ DCHECK(shutdown_event);
+}
+
+GpuRenderThread::~GpuRenderThread() {
+ gpu_channels_.clear();
+}
+
+void GpuRenderThread::RemoveChannel(int renderer_id) {
+ gpu_channels_.erase(renderer_id);
+}
+
+bool GpuRenderThread::OnMessageReceived(const IPC::Message& msg) {
+ bool msg_is_ok = true;
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(GpuRenderThread, msg, msg_is_ok)
+ IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel)
+ IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel)
+ IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer,
+ OnCreateViewCommandBuffer);
+ IPC_MESSAGE_HANDLER(GpuMsg_Synchronize, OnSynchronize)
+#if defined(OS_MACOSX)
+ IPC_MESSAGE_HANDLER(GpuMsg_AcceleratedSurfaceBuffersSwappedACK,
+ OnAcceleratedSurfaceBuffersSwappedACK)
+ IPC_MESSAGE_HANDLER(GpuMsg_DestroyCommandBuffer,
+ OnDestroyCommandBuffer)
+#endif
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP_EX()
+ return handled;
+}
+
+bool GpuRenderThread::Send(IPC::Message* msg) {
+ return browser_channel_->Send(msg);
+}
+
+void GpuRenderThread::OnEstablishChannel(int renderer_id) {
+ scoped_refptr<GpuChannel> channel;
+ IPC::ChannelHandle channel_handle;
+ GPUInfo gpu_info;
+
+ GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id);
+ if (iter == gpu_channels_.end())
+ channel = new GpuChannel(this, renderer_id);
+ else
+ channel = iter->second;
+
+ DCHECK(channel != NULL);
+
+ if (channel->Init(io_message_loop_, shutdown_event_))
+ gpu_channels_[renderer_id] = channel;
+ else
+ channel = NULL;
+
+ if (channel.get()) {
+ channel_handle.name = channel->GetChannelName();
+#if defined(OS_POSIX)
+ // On POSIX, pass the renderer-side FD. Also mark it as auto-close so
+ // that it gets closed after it has been sent.
+ int renderer_fd = channel->GetRendererFileDescriptor();
+ channel_handle.socket = base::FileDescriptor(dup(renderer_fd), true);
+#endif
+ }
+
+ Send(new GpuHostMsg_ChannelEstablished(channel_handle));
+}
+
+void GpuRenderThread::OnCloseChannel(const IPC::ChannelHandle& channel_handle) {
+ for (GpuChannelMap::iterator iter = gpu_channels_.begin();
+ iter != gpu_channels_.end(); ++iter) {
+ if (iter->second->GetChannelName() == channel_handle.name) {
+ gpu_channels_.erase(iter);
+ return;
+ }
+ }
+}
+
+void GpuRenderThread::OnSynchronize() {
+ Send(new GpuHostMsg_SynchronizeReply());
+}
+
+void GpuRenderThread::OnCreateViewCommandBuffer(
+ gfx::PluginWindowHandle window,
+ int32 render_view_id,
+ int32 renderer_id,
+ const GPUCreateCommandBufferConfig& init_params) {
+ int32 route_id = MSG_ROUTING_NONE;
+
+ GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id);
+ if (iter != gpu_channels_.end()) {
+ iter->second->CreateViewCommandBuffer(
+ window, render_view_id, init_params, &route_id);
+ }
+
+ Send(new GpuHostMsg_CommandBufferCreated(route_id));
+}
+
+#if defined(OS_MACOSX)
+void GpuRenderThread::OnAcceleratedSurfaceBuffersSwappedACK(
+ int renderer_id, int32 route_id, uint64 swap_buffers_count) {
+ GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id);
+ if (iter == gpu_channels_.end())
+ return;
+ scoped_refptr<GpuChannel> channel = iter->second;
+ channel->AcceleratedSurfaceBuffersSwapped(route_id, swap_buffers_count);
+}
+void GpuRenderThread::OnDestroyCommandBuffer(
+ int renderer_id, int32 renderer_view_id) {
+ GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id);
+ if (iter == gpu_channels_.end())
+ return;
+ scoped_refptr<GpuChannel> channel = iter->second;
+ channel->DestroyCommandBufferByViewId(renderer_view_id);
+}
+#endif
diff --git a/content/gpu/gpu_render_thread.h b/content/gpu/gpu_render_thread.h
new file mode 100644
index 0000000..9f6287e
--- /dev/null
+++ b/content/gpu/gpu_render_thread.h
@@ -0,0 +1,91 @@
+// 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 CONTENT_GPU_GPU_RENDER_THREAD_H_
+#define CONTENT_GPU_GPU_RENDER_THREAD_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/hash_tables.h"
+#include "base/command_line.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/time.h"
+#include "build/build_config.h"
+#include "content/common/child_thread.h"
+#include "content/common/gpu_info.h"
+#include "content/gpu/gpu_channel.h"
+#include "content/gpu/gpu_config.h"
+#include "content/gpu/x_util.h"
+#include "ipc/ipc_channel.h"
+#include "ipc/ipc_message.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace IPC {
+struct ChannelHandle;
+}
+
+// A GpuRenderThread is a thread responsible for issuing rendering commands to
+// a GPU. There is currently only one per GPU process. This might change. Assume
+// there are many, all running on different threads.
+//
+// A GpuRenderThread can also be hosted in the browser process in single process
+// or in-process GPU modes. In this case there is no corresponding
+// GpuChildThread and this is the reason the GpuChildThread is referenced via
+// a pointer to IPC::Message::Sender, which can be implemented by other hosts
+// to send IPC messages to the browser process IO thread on the
+// GpuRenderThread's behalf.
+class GpuRenderThread : public IPC::Channel::Listener,
+ public IPC::Message::Sender {
+ public:
+ GpuRenderThread(IPC::Message::Sender* browser_channel,
+ MessageLoop* io_message_loop,
+ base::WaitableEvent* shutdown_event);
+ ~GpuRenderThread();
+
+ // Remove the channel for a particular renderer.
+ void RemoveChannel(int renderer_id);
+
+ // Listener overrides.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+
+ // Sender overrides.
+ virtual bool Send(IPC::Message* msg);
+
+ private:
+ // Message handlers.
+ void OnEstablishChannel(int renderer_id);
+ void OnCloseChannel(const IPC::ChannelHandle& channel_handle);
+ void OnSynchronize();
+ void OnCreateViewCommandBuffer(
+ gfx::PluginWindowHandle window,
+ int32 render_view_id,
+ int32 renderer_id,
+ const GPUCreateCommandBufferConfig& init_params);
+#if defined(OS_MACOSX)
+ void OnAcceleratedSurfaceBuffersSwappedACK(
+ int renderer_id, int32 route_id, uint64 swap_buffers_count);
+ void OnDestroyCommandBuffer(int renderer_id, int32 renderer_view_id);
+#endif
+
+ MessageLoop* io_message_loop_;
+ base::WaitableEvent* shutdown_event_;
+
+ // Either an IPC channel to the browser or, if the GpuRenderThread is
+ // running in the browser process, a Sender implementation that will post
+ // IPC messages to the UI thread.
+ IPC::Message::Sender* browser_channel_;
+
+ // These objects manage channels to individual renderer processes there is
+ // one channel for each renderer process that has connected to this GPU
+ // process.
+ typedef base::hash_map<int, scoped_refptr<GpuChannel> > GpuChannelMap;
+ GpuChannelMap gpu_channels_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuRenderThread);
+};
+
+#endif // CONTENT_GPU_GPU_RENDER_THREAD_H_