| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2010 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 "chrome/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 "chrome/gpu/gpu_thread.h" | |
| 15 #include "chrome/gpu/gpu_video_service.h" | |
| 16 #include "content/common/child_process.h" | |
| 17 #include "content/common/content_switches.h" | |
| 18 #include "content/common/gpu_messages.h" | |
| 19 | |
| 20 #if defined(OS_POSIX) | |
| 21 #include "ipc/ipc_channel_posix.h" | |
| 22 #endif | |
| 23 | |
| 24 GpuChannel::GpuChannel(GpuThread* gpu_thread, | |
| 25 int renderer_id) | |
| 26 : gpu_thread_(gpu_thread), | |
| 27 renderer_id_(renderer_id), | |
| 28 renderer_process_(NULL), | |
| 29 renderer_pid_(NULL) { | |
| 30 DCHECK(gpu_thread); | |
| 31 DCHECK(renderer_id); | |
| 32 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | |
| 33 log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages); | |
| 34 } | |
| 35 | |
| 36 GpuChannel::~GpuChannel() { | |
| 37 #if defined(OS_WIN) | |
| 38 if (renderer_process_) | |
| 39 CloseHandle(renderer_process_); | |
| 40 #endif | |
| 41 } | |
| 42 | |
| 43 bool GpuChannel::OnMessageReceived(const IPC::Message& message) { | |
| 44 if (log_messages_) { | |
| 45 VLOG(1) << "received message @" << &message << " on channel @" << this | |
| 46 << " with type " << message.type(); | |
| 47 } | |
| 48 | |
| 49 if (message.routing_id() == MSG_ROUTING_CONTROL) | |
| 50 return OnControlMessageReceived(message); | |
| 51 | |
| 52 if (!router_.RouteMessage(message)) { | |
| 53 // Respond to sync messages even if router failed to route. | |
| 54 if (message.is_sync()) { | |
| 55 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message); | |
| 56 reply->set_reply_error(); | |
| 57 Send(reply); | |
| 58 } | |
| 59 return false; | |
| 60 } | |
| 61 | |
| 62 return true; | |
| 63 } | |
| 64 | |
| 65 void GpuChannel::OnChannelError() { | |
| 66 gpu_thread_->RemoveChannel(renderer_id_); | |
| 67 } | |
| 68 | |
| 69 void GpuChannel::OnChannelConnected(int32 peer_pid) { | |
| 70 renderer_pid_ = peer_pid; | |
| 71 } | |
| 72 | |
| 73 bool GpuChannel::Send(IPC::Message* message) { | |
| 74 if (log_messages_) { | |
| 75 VLOG(1) << "sending message @" << message << " on channel @" << this | |
| 76 << " with type " << message->type(); | |
| 77 } | |
| 78 | |
| 79 if (!channel_.get()) { | |
| 80 delete message; | |
| 81 return false; | |
| 82 } | |
| 83 | |
| 84 return channel_->Send(message); | |
| 85 } | |
| 86 | |
| 87 void GpuChannel::CreateViewCommandBuffer( | |
| 88 gfx::PluginWindowHandle window, | |
| 89 int32 render_view_id, | |
| 90 const GPUCreateCommandBufferConfig& init_params, | |
| 91 int32* route_id) { | |
| 92 *route_id = MSG_ROUTING_NONE; | |
| 93 | |
| 94 #if defined(ENABLE_GPU) | |
| 95 *route_id = GenerateRouteID(); | |
| 96 scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub( | |
| 97 this, window, NULL, gfx::Size(), init_params.allowed_extensions, | |
| 98 init_params.attribs, 0, *route_id, renderer_id_, render_view_id)); | |
| 99 router_.AddRoute(*route_id, stub.get()); | |
| 100 stubs_.AddWithID(stub.release(), *route_id); | |
| 101 #endif // ENABLE_GPU | |
| 102 } | |
| 103 | |
| 104 #if defined(OS_MACOSX) | |
| 105 void GpuChannel::AcceleratedSurfaceBuffersSwapped( | |
| 106 int32 route_id, uint64 swap_buffers_count) { | |
| 107 GpuCommandBufferStub* stub = stubs_.Lookup(route_id); | |
| 108 if (stub == NULL) | |
| 109 return; | |
| 110 stub->AcceleratedSurfaceBuffersSwapped(swap_buffers_count); | |
| 111 } | |
| 112 | |
| 113 void GpuChannel::DidDestroySurface(int32 renderer_route_id) { | |
| 114 // Since acclerated views are created in the renderer process and then sent | |
| 115 // to the browser process during GPU channel construction, it is possible that | |
| 116 // this is called before a GpuCommandBufferStub for |renderer_route_id| was | |
| 117 // put into |stubs_|. Hence, do not walk |stubs_| here but instead remember | |
| 118 // all |renderer_route_id|s this was called for and use them later. | |
| 119 destroyed_renderer_routes_.insert(renderer_route_id); | |
| 120 } | |
| 121 | |
| 122 bool GpuChannel::IsRenderViewGone(int32 renderer_route_id) { | |
| 123 return destroyed_renderer_routes_.count(renderer_route_id) > 0; | |
| 124 } | |
| 125 #endif | |
| 126 | |
| 127 bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) { | |
| 128 bool handled = true; | |
| 129 IPC_BEGIN_MESSAGE_MAP(GpuChannel, msg) | |
| 130 IPC_MESSAGE_HANDLER(GpuChannelMsg_Initialize, OnInitialize) | |
| 131 IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateOffscreenCommandBuffer, | |
| 132 OnCreateOffscreenCommandBuffer) | |
| 133 IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyCommandBuffer, | |
| 134 OnDestroyCommandBuffer) | |
| 135 IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateVideoDecoder, | |
| 136 OnCreateVideoDecoder) | |
| 137 IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyVideoDecoder, | |
| 138 OnDestroyVideoDecoder) | |
| 139 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 140 IPC_END_MESSAGE_MAP() | |
| 141 DCHECK(handled); | |
| 142 return handled; | |
| 143 } | |
| 144 | |
| 145 int GpuChannel::GenerateRouteID() { | |
| 146 static int last_id = 0; | |
| 147 return ++last_id; | |
| 148 } | |
| 149 | |
| 150 void GpuChannel::OnInitialize(base::ProcessHandle renderer_process) { | |
| 151 // Initialize should only happen once. | |
| 152 DCHECK(!renderer_process_); | |
| 153 | |
| 154 // Verify that the renderer has passed its own process handle. | |
| 155 if (base::GetProcId(renderer_process) == renderer_pid_) | |
| 156 renderer_process_ = renderer_process; | |
| 157 } | |
| 158 | |
| 159 void GpuChannel::OnCreateOffscreenCommandBuffer( | |
| 160 int32 parent_route_id, | |
| 161 const gfx::Size& size, | |
| 162 const GPUCreateCommandBufferConfig& init_params, | |
| 163 uint32 parent_texture_id, | |
| 164 int32* route_id) { | |
| 165 #if defined(ENABLE_GPU) | |
| 166 *route_id = GenerateRouteID(); | |
| 167 GpuCommandBufferStub* parent_stub = NULL; | |
| 168 if (parent_route_id != 0) | |
| 169 parent_stub = stubs_.Lookup(parent_route_id); | |
| 170 | |
| 171 scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub( | |
| 172 this, | |
| 173 gfx::kNullPluginWindow, | |
| 174 parent_stub, | |
| 175 size, | |
| 176 init_params.allowed_extensions, | |
| 177 init_params.attribs, | |
| 178 parent_texture_id, | |
| 179 *route_id, | |
| 180 0, 0)); | |
| 181 router_.AddRoute(*route_id, stub.get()); | |
| 182 stubs_.AddWithID(stub.release(), *route_id); | |
| 183 #else | |
| 184 *route_id = MSG_ROUTING_NONE; | |
| 185 #endif | |
| 186 } | |
| 187 | |
| 188 void GpuChannel::OnDestroyCommandBuffer(int32 route_id) { | |
| 189 #if defined(ENABLE_GPU) | |
| 190 if (router_.ResolveRoute(route_id)) { | |
| 191 router_.RemoveRoute(route_id); | |
| 192 stubs_.Remove(route_id); | |
| 193 } | |
| 194 #endif | |
| 195 } | |
| 196 | |
| 197 void GpuChannel::OnCreateVideoDecoder(int32 context_route_id, | |
| 198 int32 decoder_host_id) { | |
| 199 // TODO(cevans): do NOT re-enable this until GpuVideoService has been checked | |
| 200 // for integer overflows, including the classic "width * height" overflow. | |
| 201 #if 0 | |
| 202 VLOG(1) << "GpuChannel::OnCreateVideoDecoder"; | |
| 203 GpuVideoService* service = GpuVideoService::GetInstance(); | |
| 204 if (service == NULL) { | |
| 205 // TODO(hclam): Need to send a failure message. | |
| 206 return; | |
| 207 } | |
| 208 | |
| 209 // The context ID corresponds to the command buffer used. | |
| 210 GpuCommandBufferStub* stub = stubs_.Lookup(context_route_id); | |
| 211 int32 decoder_id = GenerateRouteID(); | |
| 212 | |
| 213 // TODO(hclam): Need to be careful about the lifetime of the command buffer | |
| 214 // decoder. | |
| 215 bool ret = service->CreateVideoDecoder( | |
| 216 this, &router_, decoder_host_id, decoder_id, | |
| 217 stub->processor()->decoder()); | |
| 218 DCHECK(ret) << "Failed to create a GpuVideoDecoder"; | |
| 219 #endif | |
| 220 } | |
| 221 | |
| 222 void GpuChannel::OnDestroyVideoDecoder(int32 decoder_id) { | |
| 223 #if defined(ENABLE_GPU) | |
| 224 LOG(ERROR) << "GpuChannel::OnDestroyVideoDecoder"; | |
| 225 GpuVideoService* service = GpuVideoService::GetInstance(); | |
| 226 if (service == NULL) | |
| 227 return; | |
| 228 service->DestroyVideoDecoder(&router_, decoder_id); | |
| 229 #endif | |
| 230 } | |
| 231 | |
| 232 bool GpuChannel::Init() { | |
| 233 // Check whether we're already initialized. | |
| 234 if (channel_.get()) | |
| 235 return true; | |
| 236 | |
| 237 // Map renderer ID to a (single) channel to that process. | |
| 238 std::string channel_name = GetChannelName(); | |
| 239 channel_.reset(new IPC::SyncChannel( | |
| 240 channel_name, IPC::Channel::MODE_SERVER, this, | |
| 241 ChildProcess::current()->io_message_loop(), false, | |
| 242 ChildProcess::current()->GetShutDownEvent())); | |
| 243 | |
| 244 return true; | |
| 245 } | |
| 246 | |
| 247 std::string GpuChannel::GetChannelName() { | |
| 248 return StringPrintf("%d.r%d.gpu", base::GetCurrentProcId(), renderer_id_); | |
| 249 } | |
| 250 | |
| 251 #if defined(OS_POSIX) | |
| 252 int GpuChannel::GetRendererFileDescriptor() { | |
| 253 int fd = -1; | |
| 254 if (channel_.get()) { | |
| 255 fd = channel_->GetClientFileDescriptor(); | |
| 256 } | |
| 257 return fd; | |
| 258 } | |
| 259 #endif // defined(OS_POSIX) | |
| 260 | |
| OLD | NEW |