summaryrefslogtreecommitdiffstats
path: root/content/common/gpu/gpu_channel.cc
diff options
context:
space:
mode:
Diffstat (limited to 'content/common/gpu/gpu_channel.cc')
-rw-r--r--content/common/gpu/gpu_channel.cc303
1 files changed, 303 insertions, 0 deletions
diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc
new file mode 100644
index 0000000..8df65cd
--- /dev/null
+++ b/content/common/gpu/gpu_channel.cc
@@ -0,0 +1,303 @@
+// 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.
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+#include "content/common/gpu/gpu_channel.h"
+
+#include "base/command_line.h"
+#include "base/process_util.h"
+#include "base/string_util.h"
+#include "content/common/child_process.h"
+#include "content/common/content_client.h"
+#include "content/common/content_switches.h"
+#include "content/common/gpu_messages.h"
+#include "content/common/gpu/gpu_channel_manager.h"
+#include "content/common/gpu/gpu_video_service.h"
+#include "content/gpu/transport_texture.h"
+
+#if defined(OS_POSIX)
+#include "ipc/ipc_channel_posix.h"
+#endif
+
+GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager,
+ GpuWatchdogThread* gpu_watchdog_thread,
+ int renderer_id)
+ : gpu_channel_manager_(gpu_channel_manager),
+ renderer_id_(renderer_id),
+ renderer_process_(base::kNullProcessHandle),
+ renderer_pid_(base::kNullProcessId),
+ watchdog_thread_(gpu_watchdog_thread) {
+ DCHECK(gpu_channel_manager);
+ DCHECK(renderer_id);
+ const CommandLine* command_line = CommandLine::ForCurrentProcess();
+ log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages);
+ disallowed_extensions_.multisampling =
+ command_line->HasSwitch(switches::kDisableGLMultisampling);
+}
+
+GpuChannel::~GpuChannel() {
+#if defined(OS_WIN)
+ if (renderer_process_)
+ CloseHandle(renderer_process_);
+#endif
+}
+
+TransportTexture* GpuChannel::GetTransportTexture(int32 route_id) {
+ return transport_textures_.Lookup(route_id);
+}
+
+void GpuChannel::DestroyTransportTexture(int32 route_id) {
+ transport_textures_.Remove(route_id);
+ router_.RemoveRoute(route_id);
+}
+
+bool GpuChannel::OnMessageReceived(const IPC::Message& message) {
+ if (log_messages_) {
+ VLOG(1) << "received message @" << &message << " on channel @" << this
+ << " with type " << message.type();
+ }
+
+ if (message.routing_id() == MSG_ROUTING_CONTROL)
+ return OnControlMessageReceived(message);
+
+ if (!router_.RouteMessage(message)) {
+ // Respond to sync messages even if router failed to route.
+ if (message.is_sync()) {
+ IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message);
+ reply->set_reply_error();
+ Send(reply);
+ }
+ return false;
+ }
+
+ return true;
+}
+
+void GpuChannel::OnChannelError() {
+ gpu_channel_manager_->RemoveChannel(renderer_id_);
+}
+
+void GpuChannel::OnChannelConnected(int32 peer_pid) {
+ renderer_pid_ = peer_pid;
+}
+
+bool GpuChannel::Send(IPC::Message* message) {
+ if (log_messages_) {
+ VLOG(1) << "sending message @" << message << " on channel @" << this
+ << " with type " << message->type();
+ }
+
+ if (!channel_.get()) {
+ delete message;
+ return false;
+ }
+
+ return channel_->Send(message);
+}
+
+void GpuChannel::CreateViewCommandBuffer(
+ gfx::PluginWindowHandle window,
+ int32 render_view_id,
+ const GPUCreateCommandBufferConfig& init_params,
+ int32* route_id) {
+ *route_id = MSG_ROUTING_NONE;
+ content::GetContentClient()->SetActiveURL(init_params.active_url);
+
+#if defined(ENABLE_GPU)
+ *route_id = GenerateRouteID();
+ scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub(
+ this, window, NULL, gfx::Size(), disallowed_extensions_,
+ init_params.allowed_extensions,
+ init_params.attribs, 0, *route_id, renderer_id_, render_view_id,
+ watchdog_thread_));
+ router_.AddRoute(*route_id, stub.get());
+ stubs_.AddWithID(stub.release(), *route_id);
+#endif // ENABLE_GPU
+}
+
+#if defined(OS_MACOSX)
+void GpuChannel::AcceleratedSurfaceBuffersSwapped(
+ int32 route_id, uint64 swap_buffers_count) {
+ GpuCommandBufferStub* stub = stubs_.Lookup(route_id);
+ if (stub == NULL)
+ return;
+ stub->AcceleratedSurfaceBuffersSwapped(swap_buffers_count);
+}
+
+void GpuChannel::DestroyCommandBufferByViewId(int32 render_view_id) {
+ // This responds to a message from the browser process to destroy the command
+ // buffer when the window with a GPUProcessor is closed (see
+ // RenderWidgetHostViewMac::DeallocFakePluginWindowHandle). Find the route id
+ // that matches the given render_view_id and delete the route.
+ for (StubMap::const_iterator iter(&stubs_); !iter.IsAtEnd(); iter.Advance()) {
+ if (iter.GetCurrentValue()->render_view_id() == render_view_id) {
+ OnDestroyCommandBuffer(iter.GetCurrentKey());
+ return;
+ }
+ }
+}
+#endif
+
+bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(GpuChannel, msg)
+ IPC_MESSAGE_HANDLER(GpuChannelMsg_Initialize, OnInitialize)
+ IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateOffscreenCommandBuffer,
+ OnCreateOffscreenCommandBuffer)
+ IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyCommandBuffer,
+ OnDestroyCommandBuffer)
+ IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateVideoDecoder,
+ OnCreateVideoDecoder)
+ IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyVideoDecoder,
+ OnDestroyVideoDecoder)
+ IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateTransportTexture,
+ OnCreateTransportTexture)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ DCHECK(handled);
+ return handled;
+}
+
+int GpuChannel::GenerateRouteID() {
+ static int last_id = 0;
+ return ++last_id;
+}
+
+void GpuChannel::OnInitialize(base::ProcessHandle renderer_process) {
+ // Initialize should only happen once.
+ DCHECK(!renderer_process_);
+
+ // Verify that the renderer has passed its own process handle.
+ if (base::GetProcId(renderer_process) == renderer_pid_)
+ renderer_process_ = renderer_process;
+}
+
+void GpuChannel::OnCreateOffscreenCommandBuffer(
+ int32 parent_route_id,
+ const gfx::Size& size,
+ const GPUCreateCommandBufferConfig& init_params,
+ uint32 parent_texture_id,
+ int32* route_id) {
+ content::GetContentClient()->SetActiveURL(init_params.active_url);
+#if defined(ENABLE_GPU)
+ *route_id = GenerateRouteID();
+ GpuCommandBufferStub* parent_stub = NULL;
+ if (parent_route_id != 0)
+ parent_stub = stubs_.Lookup(parent_route_id);
+
+ scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub(
+ this,
+ gfx::kNullPluginWindow,
+ parent_stub,
+ size,
+ disallowed_extensions_,
+ init_params.allowed_extensions,
+ init_params.attribs,
+ parent_texture_id,
+ *route_id,
+ 0, 0, watchdog_thread_));
+ router_.AddRoute(*route_id, stub.get());
+ stubs_.AddWithID(stub.release(), *route_id);
+#else
+ *route_id = MSG_ROUTING_NONE;
+#endif
+}
+
+void GpuChannel::OnDestroyCommandBuffer(int32 route_id) {
+#if defined(ENABLE_GPU)
+ if (router_.ResolveRoute(route_id)) {
+ router_.RemoveRoute(route_id);
+ stubs_.Remove(route_id);
+ }
+#endif
+}
+
+void GpuChannel::OnCreateVideoDecoder(int32 context_route_id,
+ int32 decoder_host_id) {
+// TODO(cevans): do NOT re-enable this until GpuVideoService has been checked
+// for integer overflows, including the classic "width * height" overflow.
+#if 0
+ VLOG(1) << "GpuChannel::OnCreateVideoDecoder";
+ GpuVideoService* service = GpuVideoService::GetInstance();
+ if (service == NULL) {
+ // TODO(hclam): Need to send a failure message.
+ return;
+ }
+
+ // The context ID corresponds to the command buffer used.
+ GpuCommandBufferStub* stub = stubs_.Lookup(context_route_id);
+ int32 decoder_id = GenerateRouteID();
+
+ // TODO(hclam): Need to be careful about the lifetime of the command buffer
+ // decoder.
+ bool ret = service->CreateVideoDecoder(
+ this, &router_, decoder_host_id, decoder_id,
+ stub->processor()->decoder());
+ DCHECK(ret) << "Failed to create a GpuVideoDecoder";
+#endif
+}
+
+void GpuChannel::OnDestroyVideoDecoder(int32 decoder_id) {
+#if defined(ENABLE_GPU)
+ LOG(ERROR) << "GpuChannel::OnDestroyVideoDecoder";
+ GpuVideoService* service = GpuVideoService::GetInstance();
+ if (service == NULL)
+ return;
+ service->DestroyVideoDecoder(&router_, decoder_id);
+#endif
+}
+
+void GpuChannel::OnCreateTransportTexture(int32 context_route_id,
+ int32 host_id) {
+ #if defined(ENABLE_GPU)
+ GpuCommandBufferStub* stub = stubs_.Lookup(context_route_id);
+ int32 route_id = GenerateRouteID();
+
+ scoped_ptr<TransportTexture> transport(
+ new TransportTexture(this, channel_.get(), stub->processor()->decoder(),
+ host_id, route_id));
+ router_.AddRoute(route_id, transport.get());
+ transport_textures_.AddWithID(transport.release(), route_id);
+
+ IPC::Message* msg = new GpuTransportTextureHostMsg_TransportTextureCreated(
+ host_id, route_id);
+ Send(msg);
+ #endif
+ }
+
+bool GpuChannel::Init(MessageLoop* io_message_loop,
+ base::WaitableEvent* shutdown_event) {
+ // Check whether we're already initialized.
+ if (channel_.get())
+ return true;
+
+ // 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,
+ io_message_loop,
+ false,
+ shutdown_event));
+
+ return true;
+}
+
+std::string GpuChannel::GetChannelName() {
+ return StringPrintf("%d.r%d.gpu", base::GetCurrentProcId(), renderer_id_);
+}
+
+#if defined(OS_POSIX)
+int GpuChannel::GetRendererFileDescriptor() {
+ int fd = -1;
+ if (channel_.get()) {
+ fd = channel_->GetClientFileDescriptor();
+ }
+ return fd;
+}
+#endif // defined(OS_POSIX)