diff options
Diffstat (limited to 'content/gpu')
-rw-r--r-- | content/gpu/gpu_channel.cc | 22 | ||||
-rw-r--r-- | content/gpu/gpu_channel.h | 19 | ||||
-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.cc | 26 | ||||
-rw-r--r-- | content/gpu/gpu_main.cc | 14 | ||||
-rw-r--r-- | content/gpu/gpu_render_thread.cc | 146 | ||||
-rw-r--r-- | content/gpu/gpu_render_thread.h | 91 |
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_ |