| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #if defined(OS_WIN) | |
| 6 #include <windows.h> | |
| 7 #endif | |
| 8 | |
| 9 #include "content/gpu/gpu_channel.h" | |
| 10 | |
| 11 #include "base/command_line.h" | |
| 12 #include "base/process_util.h" | |
| 13 #include "base/string_util.h" | |
| 14 #include "content/common/child_process.h" | |
| 15 #include "content/common/content_client.h" | |
| 16 #include "content/common/content_switches.h" | |
| 17 #include "content/common/gpu_messages.h" | |
| 18 #include "content/gpu/gpu_render_thread.h" | |
| 19 #include "content/gpu/gpu_video_service.h" | |
| 20 | |
| 21 #if defined(OS_POSIX) | |
| 22 #include "ipc/ipc_channel_posix.h" | |
| 23 #endif | |
| 24 | |
| 25 GpuChannel::GpuChannel(GpuRenderThread* gpu_render_thread, | |
| 26 GpuWatchdogThread* gpu_watchdog_thread, | |
| 27 int renderer_id) | |
| 28 : gpu_render_thread_(gpu_render_thread), | |
| 29 renderer_id_(renderer_id), | |
| 30 renderer_process_(base::kNullProcessHandle), | |
| 31 renderer_pid_(base::kNullProcessId), | |
| 32 watchdog_thread_(gpu_watchdog_thread) { | |
| 33 DCHECK(gpu_render_thread); | |
| 34 DCHECK(renderer_id); | |
| 35 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | |
| 36 log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages); | |
| 37 disallowed_extensions_.multisampling = | |
| 38 command_line->HasSwitch(switches::kDisableGLMultisampling); | |
| 39 } | |
| 40 | |
| 41 GpuChannel::~GpuChannel() { | |
| 42 #if defined(OS_WIN) | |
| 43 if (renderer_process_) | |
| 44 CloseHandle(renderer_process_); | |
| 45 #endif | |
| 46 } | |
| 47 | |
| 48 bool GpuChannel::OnMessageReceived(const IPC::Message& message) { | |
| 49 if (log_messages_) { | |
| 50 VLOG(1) << "received message @" << &message << " on channel @" << this | |
| 51 << " with type " << message.type(); | |
| 52 } | |
| 53 | |
| 54 if (message.routing_id() == MSG_ROUTING_CONTROL) | |
| 55 return OnControlMessageReceived(message); | |
| 56 | |
| 57 if (!router_.RouteMessage(message)) { | |
| 58 // Respond to sync messages even if router failed to route. | |
| 59 if (message.is_sync()) { | |
| 60 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message); | |
| 61 reply->set_reply_error(); | |
| 62 Send(reply); | |
| 63 } | |
| 64 return false; | |
| 65 } | |
| 66 | |
| 67 return true; | |
| 68 } | |
| 69 | |
| 70 void GpuChannel::OnChannelError() { | |
| 71 gpu_render_thread_->RemoveChannel(renderer_id_); | |
| 72 } | |
| 73 | |
| 74 void GpuChannel::OnChannelConnected(int32 peer_pid) { | |
| 75 renderer_pid_ = peer_pid; | |
| 76 } | |
| 77 | |
| 78 bool GpuChannel::Send(IPC::Message* message) { | |
| 79 if (log_messages_) { | |
| 80 VLOG(1) << "sending message @" << message << " on channel @" << this | |
| 81 << " with type " << message->type(); | |
| 82 } | |
| 83 | |
| 84 if (!channel_.get()) { | |
| 85 delete message; | |
| 86 return false; | |
| 87 } | |
| 88 | |
| 89 return channel_->Send(message); | |
| 90 } | |
| 91 | |
| 92 void GpuChannel::CreateViewCommandBuffer( | |
| 93 gfx::PluginWindowHandle window, | |
| 94 int32 render_view_id, | |
| 95 const GPUCreateCommandBufferConfig& init_params, | |
| 96 int32* route_id) { | |
| 97 *route_id = MSG_ROUTING_NONE; | |
| 98 content::GetContentClient()->SetActiveURL(init_params.active_url); | |
| 99 | |
| 100 #if defined(ENABLE_GPU) | |
| 101 *route_id = GenerateRouteID(); | |
| 102 scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub( | |
| 103 this, window, NULL, gfx::Size(), disallowed_extensions_, | |
| 104 init_params.allowed_extensions, | |
| 105 init_params.attribs, 0, *route_id, renderer_id_, render_view_id, | |
| 106 watchdog_thread_)); | |
| 107 router_.AddRoute(*route_id, stub.get()); | |
| 108 stubs_.AddWithID(stub.release(), *route_id); | |
| 109 #endif // ENABLE_GPU | |
| 110 } | |
| 111 | |
| 112 #if defined(OS_MACOSX) | |
| 113 void GpuChannel::AcceleratedSurfaceBuffersSwapped( | |
| 114 int32 route_id, uint64 swap_buffers_count) { | |
| 115 GpuCommandBufferStub* stub = stubs_.Lookup(route_id); | |
| 116 if (stub == NULL) | |
| 117 return; | |
| 118 stub->AcceleratedSurfaceBuffersSwapped(swap_buffers_count); | |
| 119 } | |
| 120 | |
| 121 void GpuChannel::DestroyCommandBufferByViewId(int32 render_view_id) { | |
| 122 // This responds to a message from the browser process to destroy the command | |
| 123 // buffer when the window with a GPUProcessor is closed (see | |
| 124 // RenderWidgetHostViewMac::DeallocFakePluginWindowHandle). Find the route id | |
| 125 // that matches the given render_view_id and delete the route. | |
| 126 for (StubMap::const_iterator iter(&stubs_); !iter.IsAtEnd(); iter.Advance()) { | |
| 127 if (iter.GetCurrentValue()->render_view_id() == render_view_id) { | |
| 128 OnDestroyCommandBuffer(iter.GetCurrentKey()); | |
| 129 return; | |
| 130 } | |
| 131 } | |
| 132 } | |
| 133 #endif | |
| 134 | |
| 135 bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) { | |
| 136 bool handled = true; | |
| 137 IPC_BEGIN_MESSAGE_MAP(GpuChannel, msg) | |
| 138 IPC_MESSAGE_HANDLER(GpuChannelMsg_Initialize, OnInitialize) | |
| 139 IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateOffscreenCommandBuffer, | |
| 140 OnCreateOffscreenCommandBuffer) | |
| 141 IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyCommandBuffer, | |
| 142 OnDestroyCommandBuffer) | |
| 143 IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateVideoDecoder, | |
| 144 OnCreateVideoDecoder) | |
| 145 IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyVideoDecoder, | |
| 146 OnDestroyVideoDecoder) | |
| 147 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 148 IPC_END_MESSAGE_MAP() | |
| 149 DCHECK(handled); | |
| 150 return handled; | |
| 151 } | |
| 152 | |
| 153 int GpuChannel::GenerateRouteID() { | |
| 154 static int last_id = 0; | |
| 155 return ++last_id; | |
| 156 } | |
| 157 | |
| 158 void GpuChannel::OnInitialize(base::ProcessHandle renderer_process) { | |
| 159 // Initialize should only happen once. | |
| 160 DCHECK(!renderer_process_); | |
| 161 | |
| 162 // Verify that the renderer has passed its own process handle. | |
| 163 if (base::GetProcId(renderer_process) == renderer_pid_) | |
| 164 renderer_process_ = renderer_process; | |
| 165 } | |
| 166 | |
| 167 void GpuChannel::OnCreateOffscreenCommandBuffer( | |
| 168 int32 parent_route_id, | |
| 169 const gfx::Size& size, | |
| 170 const GPUCreateCommandBufferConfig& init_params, | |
| 171 uint32 parent_texture_id, | |
| 172 int32* route_id) { | |
| 173 content::GetContentClient()->SetActiveURL(init_params.active_url); | |
| 174 #if defined(ENABLE_GPU) | |
| 175 *route_id = GenerateRouteID(); | |
| 176 GpuCommandBufferStub* parent_stub = NULL; | |
| 177 if (parent_route_id != 0) | |
| 178 parent_stub = stubs_.Lookup(parent_route_id); | |
| 179 | |
| 180 scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub( | |
| 181 this, | |
| 182 gfx::kNullPluginWindow, | |
| 183 parent_stub, | |
| 184 size, | |
| 185 disallowed_extensions_, | |
| 186 init_params.allowed_extensions, | |
| 187 init_params.attribs, | |
| 188 parent_texture_id, | |
| 189 *route_id, | |
| 190 0, 0, watchdog_thread_)); | |
| 191 router_.AddRoute(*route_id, stub.get()); | |
| 192 stubs_.AddWithID(stub.release(), *route_id); | |
| 193 #else | |
| 194 *route_id = MSG_ROUTING_NONE; | |
| 195 #endif | |
| 196 } | |
| 197 | |
| 198 void GpuChannel::OnDestroyCommandBuffer(int32 route_id) { | |
| 199 #if defined(ENABLE_GPU) | |
| 200 if (router_.ResolveRoute(route_id)) { | |
| 201 router_.RemoveRoute(route_id); | |
| 202 stubs_.Remove(route_id); | |
| 203 } | |
| 204 #endif | |
| 205 } | |
| 206 | |
| 207 void GpuChannel::OnCreateVideoDecoder(int32 context_route_id, | |
| 208 int32 decoder_host_id) { | |
| 209 // TODO(cevans): do NOT re-enable this until GpuVideoService has been checked | |
| 210 // for integer overflows, including the classic "width * height" overflow. | |
| 211 #if 0 | |
| 212 VLOG(1) << "GpuChannel::OnCreateVideoDecoder"; | |
| 213 GpuVideoService* service = GpuVideoService::GetInstance(); | |
| 214 if (service == NULL) { | |
| 215 // TODO(hclam): Need to send a failure message. | |
| 216 return; | |
| 217 } | |
| 218 | |
| 219 // The context ID corresponds to the command buffer used. | |
| 220 GpuCommandBufferStub* stub = stubs_.Lookup(context_route_id); | |
| 221 int32 decoder_id = GenerateRouteID(); | |
| 222 | |
| 223 // TODO(hclam): Need to be careful about the lifetime of the command buffer | |
| 224 // decoder. | |
| 225 bool ret = service->CreateVideoDecoder( | |
| 226 this, &router_, decoder_host_id, decoder_id, | |
| 227 stub->processor()->decoder()); | |
| 228 DCHECK(ret) << "Failed to create a GpuVideoDecoder"; | |
| 229 #endif | |
| 230 } | |
| 231 | |
| 232 void GpuChannel::OnDestroyVideoDecoder(int32 decoder_id) { | |
| 233 #if defined(ENABLE_GPU) | |
| 234 LOG(ERROR) << "GpuChannel::OnDestroyVideoDecoder"; | |
| 235 GpuVideoService* service = GpuVideoService::GetInstance(); | |
| 236 if (service == NULL) | |
| 237 return; | |
| 238 service->DestroyVideoDecoder(&router_, decoder_id); | |
| 239 #endif | |
| 240 } | |
| 241 | |
| 242 bool GpuChannel::Init(MessageLoop* io_message_loop, | |
| 243 base::WaitableEvent* shutdown_event) { | |
| 244 // Check whether we're already initialized. | |
| 245 if (channel_.get()) | |
| 246 return true; | |
| 247 | |
| 248 // Map renderer ID to a (single) channel to that process. | |
| 249 std::string channel_name = GetChannelName(); | |
| 250 channel_.reset(new IPC::SyncChannel( | |
| 251 channel_name, | |
| 252 IPC::Channel::MODE_SERVER, | |
| 253 this, | |
| 254 io_message_loop, | |
| 255 false, | |
| 256 shutdown_event)); | |
| 257 | |
| 258 return true; | |
| 259 } | |
| 260 | |
| 261 std::string GpuChannel::GetChannelName() { | |
| 262 return StringPrintf("%d.r%d.gpu", base::GetCurrentProcId(), renderer_id_); | |
| 263 } | |
| 264 | |
| 265 #if defined(OS_POSIX) | |
| 266 int GpuChannel::GetRendererFileDescriptor() { | |
| 267 int fd = -1; | |
| 268 if (channel_.get()) { | |
| 269 fd = channel_->GetClientFileDescriptor(); | |
| 270 } | |
| 271 return fd; | |
| 272 } | |
| 273 #endif // defined(OS_POSIX) | |
| OLD | NEW |