| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if defined(OS_WIN) | 5 #if defined(OS_WIN) |
| 6 #include <windows.h> | 6 #include <windows.h> |
| 7 #endif | 7 #endif |
| 8 | 8 |
| 9 #include "content/common/gpu/gpu_channel.h" | 9 #include "content/common/gpu/gpu_channel.h" |
| 10 | 10 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 #endif | 26 #endif |
| 27 | 27 |
| 28 GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, | 28 GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, |
| 29 GpuWatchdog* watchdog, | 29 GpuWatchdog* watchdog, |
| 30 int renderer_id) | 30 int renderer_id) |
| 31 : gpu_channel_manager_(gpu_channel_manager), | 31 : gpu_channel_manager_(gpu_channel_manager), |
| 32 renderer_id_(renderer_id), | 32 renderer_id_(renderer_id), |
| 33 renderer_process_(base::kNullProcessHandle), | 33 renderer_process_(base::kNullProcessHandle), |
| 34 renderer_pid_(base::kNullProcessId), | 34 renderer_pid_(base::kNullProcessId), |
| 35 share_group_(new gfx::GLShareGroup), | 35 share_group_(new gfx::GLShareGroup), |
| 36 watchdog_(watchdog) { | 36 watchdog_(watchdog), |
| 37 task_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 37 DCHECK(gpu_channel_manager); | 38 DCHECK(gpu_channel_manager); |
| 38 DCHECK(renderer_id); | 39 DCHECK(renderer_id); |
| 39 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | 40 const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 40 log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages); | 41 log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages); |
| 41 disallowed_extensions_.multisampling = | 42 disallowed_extensions_.multisampling = |
| 42 command_line->HasSwitch(switches::kDisableGLMultisampling); | 43 command_line->HasSwitch(switches::kDisableGLMultisampling); |
| 43 } | 44 } |
| 44 | 45 |
| 45 GpuChannel::~GpuChannel() { | 46 GpuChannel::~GpuChannel() { |
| 46 #if defined(OS_WIN) | 47 #if defined(OS_WIN) |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 } | 80 } |
| 80 #endif | 81 #endif |
| 81 } | 82 } |
| 82 | 83 |
| 83 bool GpuChannel::OnMessageReceived(const IPC::Message& message) { | 84 bool GpuChannel::OnMessageReceived(const IPC::Message& message) { |
| 84 if (log_messages_) { | 85 if (log_messages_) { |
| 85 VLOG(1) << "received message @" << &message << " on channel @" << this | 86 VLOG(1) << "received message @" << &message << " on channel @" << this |
| 86 << " with type " << message.type(); | 87 << " with type " << message.type(); |
| 87 } | 88 } |
| 88 | 89 |
| 90 // Control messages are not deferred and can be handled out of order with |
| 91 // respect to routed ones. |
| 89 if (message.routing_id() == MSG_ROUTING_CONTROL) | 92 if (message.routing_id() == MSG_ROUTING_CONTROL) |
| 90 return OnControlMessageReceived(message); | 93 return OnControlMessageReceived(message); |
| 91 | 94 |
| 95 // If the channel is unscheduled, defer sync and async messages until it is |
| 96 // rescheduled. Also, even if the channel is scheduled, do not allow newly |
| 97 // received messages to be handled before previously received deferred ones; |
| 98 // append them to the deferred queue as well. |
| 99 if (!IsScheduled() || !deferred_messages_.empty()) { |
| 100 deferred_messages_.push(new IPC::Message(message)); |
| 101 return true; |
| 102 } |
| 103 |
| 92 if (!router_.RouteMessage(message)) { | 104 if (!router_.RouteMessage(message)) { |
| 93 // Respond to sync messages even if router failed to route. | 105 // Respond to sync messages even if router failed to route. |
| 94 if (message.is_sync()) { | 106 if (message.is_sync()) { |
| 95 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message); | 107 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message); |
| 96 reply->set_reply_error(); | 108 reply->set_reply_error(); |
| 97 Send(reply); | 109 Send(reply); |
| 98 } | 110 } |
| 99 return false; | 111 return false; |
| 100 } | 112 } |
| 101 | 113 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 120 } | 132 } |
| 121 | 133 |
| 122 if (!channel_.get()) { | 134 if (!channel_.get()) { |
| 123 delete message; | 135 delete message; |
| 124 return false; | 136 return false; |
| 125 } | 137 } |
| 126 | 138 |
| 127 return channel_->Send(message); | 139 return channel_->Send(message); |
| 128 } | 140 } |
| 129 | 141 |
| 142 bool GpuChannel::IsScheduled() { |
| 143 for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_); |
| 144 !it.IsAtEnd(); |
| 145 it.Advance()) { |
| 146 GpuCommandBufferStub* stub = it.GetCurrentValue(); |
| 147 if (!stub->IsScheduled()) |
| 148 return false; |
| 149 } |
| 150 |
| 151 return true; |
| 152 } |
| 153 |
| 154 void GpuChannel::OnScheduled() { |
| 155 // Post a task to handle any deferred messages. The deferred message queue is |
| 156 // not emptied here, which ensures that OnMessageReceived will continue to |
| 157 // defer newly received messages until the ones in the queue have all been |
| 158 // handled by HandleDeferredMessages. HandleDeferredMessages is invoked as a |
| 159 // task to prevent reentrancy. |
| 160 MessageLoop::current()->PostTask( |
| 161 FROM_HERE, |
| 162 task_factory_.NewRunnableMethod( |
| 163 &GpuChannel::HandleDeferredMessages)); |
| 164 } |
| 165 |
| 130 void GpuChannel::LoseAllContexts() { | 166 void GpuChannel::LoseAllContexts() { |
| 131 gpu_channel_manager_->LoseAllContexts(); | 167 gpu_channel_manager_->LoseAllContexts(); |
| 132 } | 168 } |
| 133 | 169 |
| 134 void GpuChannel::DestroySoon() { | 170 void GpuChannel::DestroySoon() { |
| 135 MessageLoop::current()->PostTask( | 171 MessageLoop::current()->PostTask( |
| 136 FROM_HERE, NewRunnableMethod(this, | 172 FROM_HERE, NewRunnableMethod(this, |
| 137 &GpuChannel::OnDestroy)); | 173 &GpuChannel::OnDestroy)); |
| 138 } | 174 } |
| 139 | 175 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 #endif | 247 #endif |
| 212 | 248 |
| 213 #if defined(OS_MACOSX) | 249 #if defined(OS_MACOSX) |
| 214 void GpuChannel::DestroyCommandBufferByViewId(int32 render_view_id) { | 250 void GpuChannel::DestroyCommandBufferByViewId(int32 render_view_id) { |
| 215 // This responds to a message from the browser process to destroy the command | 251 // This responds to a message from the browser process to destroy the command |
| 216 // buffer when the window with a GpuScheduler is closed (see | 252 // buffer when the window with a GpuScheduler is closed (see |
| 217 // RenderWidgetHostViewMac::DeallocFakePluginWindowHandle). Find the route id | 253 // RenderWidgetHostViewMac::DeallocFakePluginWindowHandle). Find the route id |
| 218 // that matches the given render_view_id and delete the route. | 254 // that matches the given render_view_id and delete the route. |
| 219 for (StubMap::const_iterator iter(&stubs_); !iter.IsAtEnd(); iter.Advance()) { | 255 for (StubMap::const_iterator iter(&stubs_); !iter.IsAtEnd(); iter.Advance()) { |
| 220 if (iter.GetCurrentValue()->render_view_id() == render_view_id) { | 256 if (iter.GetCurrentValue()->render_view_id() == render_view_id) { |
| 221 OnDestroyCommandBuffer(iter.GetCurrentKey()); | 257 OnDestroyCommandBuffer(iter.GetCurrentKey(), NULL); |
| 222 return; | 258 return; |
| 223 } | 259 } |
| 224 } | 260 } |
| 225 } | 261 } |
| 226 #endif | 262 #endif |
| 227 | 263 |
| 228 bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) { | 264 bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) { |
| 265 // Always use IPC_MESSAGE_HANDLER_DELAY_REPLY for synchronous message handlers |
| 266 // here. This is so the reply can be delayed if the scheduler is unscheduled. |
| 229 bool handled = true; | 267 bool handled = true; |
| 230 IPC_BEGIN_MESSAGE_MAP(GpuChannel, msg) | 268 IPC_BEGIN_MESSAGE_MAP(GpuChannel, msg) |
| 231 IPC_MESSAGE_HANDLER(GpuChannelMsg_Initialize, OnInitialize) | 269 IPC_MESSAGE_HANDLER(GpuChannelMsg_Initialize, OnInitialize) |
| 232 IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateOffscreenCommandBuffer, | 270 IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuChannelMsg_CreateOffscreenCommandBuffer, |
| 233 OnCreateOffscreenCommandBuffer) | 271 OnCreateOffscreenCommandBuffer) |
| 234 IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyCommandBuffer, | 272 IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuChannelMsg_DestroyCommandBuffer, |
| 235 OnDestroyCommandBuffer) | 273 OnDestroyCommandBuffer) |
| 236 IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateOffscreenSurface, | 274 IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuChannelMsg_CreateOffscreenSurface, |
| 237 OnCreateOffscreenSurface) | 275 OnCreateOffscreenSurface) |
| 238 IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroySurface, OnDestroySurface) | 276 IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroySurface, OnDestroySurface) |
| 239 IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateTransportTexture, | 277 IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateTransportTexture, |
| 240 OnCreateTransportTexture) | 278 OnCreateTransportTexture) |
| 241 IPC_MESSAGE_UNHANDLED(handled = false) | 279 IPC_MESSAGE_UNHANDLED(handled = false) |
| 242 IPC_END_MESSAGE_MAP() | 280 IPC_END_MESSAGE_MAP() |
| 243 DCHECK(handled) << msg.type(); | 281 DCHECK(handled) << msg.type(); |
| 244 return handled; | 282 return handled; |
| 245 } | 283 } |
| 246 | 284 |
| 285 void GpuChannel::HandleDeferredMessages() { |
| 286 // Empty the deferred queue so OnMessageRecieved does not defer on that |
| 287 // account and to prevent an infinite loop if the scheduler is unscheduled |
| 288 // as a result of handling already deferred messages. |
| 289 std::queue<IPC::Message*> deferred_messages_copy; |
| 290 std::swap(deferred_messages_copy, deferred_messages_); |
| 291 |
| 292 while (!deferred_messages_copy.empty()) { |
| 293 scoped_ptr<IPC::Message> message(deferred_messages_copy.front()); |
| 294 deferred_messages_copy.pop(); |
| 295 |
| 296 OnMessageReceived(*message); |
| 297 } |
| 298 } |
| 299 |
| 247 int GpuChannel::GenerateRouteID() { | 300 int GpuChannel::GenerateRouteID() { |
| 248 static int last_id = 0; | 301 static int last_id = 0; |
| 249 return ++last_id; | 302 return ++last_id; |
| 250 } | 303 } |
| 251 | 304 |
| 252 void GpuChannel::OnInitialize(base::ProcessHandle renderer_process) { | 305 void GpuChannel::OnInitialize(base::ProcessHandle renderer_process) { |
| 253 // Initialize should only happen once. | 306 // Initialize should only happen once. |
| 254 DCHECK(!renderer_process_); | 307 DCHECK(!renderer_process_); |
| 255 | 308 |
| 256 // Verify that the renderer has passed its own process handle. | 309 // Verify that the renderer has passed its own process handle. |
| 257 if (base::GetProcId(renderer_process) == renderer_pid_) | 310 if (base::GetProcId(renderer_process) == renderer_pid_) |
| 258 renderer_process_ = renderer_process; | 311 renderer_process_ = renderer_process; |
| 259 } | 312 } |
| 260 | 313 |
| 261 void GpuChannel::OnCreateOffscreenCommandBuffer( | 314 void GpuChannel::OnCreateOffscreenCommandBuffer( |
| 262 const gfx::Size& size, | 315 const gfx::Size& size, |
| 263 const GPUCreateCommandBufferConfig& init_params, | 316 const GPUCreateCommandBufferConfig& init_params, |
| 264 int32* route_id) { | 317 IPC::Message* reply_message) { |
| 318 int32 route_id = MSG_ROUTING_NONE; |
| 319 |
| 265 content::GetContentClient()->SetActiveURL(init_params.active_url); | 320 content::GetContentClient()->SetActiveURL(init_params.active_url); |
| 266 #if defined(ENABLE_GPU) | 321 #if defined(ENABLE_GPU) |
| 267 *route_id = GenerateRouteID(); | 322 route_id = GenerateRouteID(); |
| 268 | 323 |
| 269 scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub( | 324 scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub( |
| 270 this, | 325 this, |
| 271 gfx::kNullPluginWindow, | 326 gfx::kNullPluginWindow, |
| 272 size, | 327 size, |
| 273 disallowed_extensions_, | 328 disallowed_extensions_, |
| 274 init_params.allowed_extensions, | 329 init_params.allowed_extensions, |
| 275 init_params.attribs, | 330 init_params.attribs, |
| 276 *route_id, | 331 route_id, |
| 277 0, 0, watchdog_)); | 332 0, 0, watchdog_)); |
| 278 router_.AddRoute(*route_id, stub.get()); | 333 router_.AddRoute(route_id, stub.get()); |
| 279 stubs_.AddWithID(stub.release(), *route_id); | 334 stubs_.AddWithID(stub.release(), route_id); |
| 280 TRACE_EVENT1("gpu", "GpuChannel::OnCreateOffscreenCommandBuffer", | 335 TRACE_EVENT1("gpu", "GpuChannel::OnCreateOffscreenCommandBuffer", |
| 281 "route_id", route_id); | 336 "route_id", route_id); |
| 282 #else | |
| 283 *route_id = MSG_ROUTING_NONE; | |
| 284 #endif | 337 #endif |
| 338 |
| 339 GpuChannelMsg_CreateOffscreenCommandBuffer::WriteReplyParams( |
| 340 reply_message, |
| 341 route_id); |
| 342 Send(reply_message); |
| 285 } | 343 } |
| 286 | 344 |
| 287 void GpuChannel::OnDestroyCommandBuffer(int32 route_id) { | 345 void GpuChannel::OnDestroyCommandBuffer(int32 route_id, |
| 346 IPC::Message* reply_message) { |
| 288 #if defined(ENABLE_GPU) | 347 #if defined(ENABLE_GPU) |
| 289 TRACE_EVENT1("gpu", "GpuChannel::OnDestroyCommandBuffer", | 348 TRACE_EVENT1("gpu", "GpuChannel::OnDestroyCommandBuffer", |
| 290 "route_id", route_id); | 349 "route_id", route_id); |
| 291 if (router_.ResolveRoute(route_id)) { | 350 if (router_.ResolveRoute(route_id)) { |
| 292 GpuCommandBufferStub* stub = stubs_.Lookup(route_id); | |
| 293 // In case the renderer is currently blocked waiting for a sync reply from | |
| 294 // the stub, allow the stub to clean up and unblock pending messages here: | |
| 295 if (stub != NULL) | |
| 296 stub->CommandBufferWasDestroyed(); | |
| 297 router_.RemoveRoute(route_id); | 351 router_.RemoveRoute(route_id); |
| 298 stubs_.Remove(route_id); | 352 stubs_.Remove(route_id); |
| 299 } | 353 } |
| 300 #endif | 354 #endif |
| 355 |
| 356 if (reply_message) |
| 357 Send(reply_message); |
| 301 } | 358 } |
| 302 | 359 |
| 303 void GpuChannel::OnCreateOffscreenSurface(const gfx::Size& size, | 360 void GpuChannel::OnCreateOffscreenSurface(const gfx::Size& size, |
| 304 int* route_id) { | 361 IPC::Message* reply_message) { |
| 305 *route_id = MSG_ROUTING_NONE; | 362 int route_id = MSG_ROUTING_NONE; |
| 306 | 363 |
| 307 #if defined(ENABLE_GPU) | 364 #if defined(ENABLE_GPU) |
| 308 scoped_refptr<gfx::GLSurface> surface( | 365 scoped_refptr<gfx::GLSurface> surface( |
| 309 gfx::GLSurface::CreateOffscreenGLSurface(size)); | 366 gfx::GLSurface::CreateOffscreenGLSurface(size)); |
| 310 if (!surface.get()) | 367 if (!surface.get()) |
| 311 return; | 368 return; |
| 312 | 369 |
| 313 *route_id = GenerateRouteID(); | 370 route_id = GenerateRouteID(); |
| 314 | 371 |
| 315 scoped_ptr<GpuSurfaceStub> stub (new GpuSurfaceStub(this, | 372 scoped_ptr<GpuSurfaceStub> stub (new GpuSurfaceStub(this, |
| 316 *route_id, | 373 route_id, |
| 317 surface.release())); | 374 surface.release())); |
| 318 | 375 |
| 319 router_.AddRoute(*route_id, stub.get()); | 376 router_.AddRoute(route_id, stub.get()); |
| 320 surfaces_.AddWithID(stub.release(), *route_id); | 377 surfaces_.AddWithID(stub.release(), route_id); |
| 321 #endif | 378 #endif |
| 379 |
| 380 GpuChannelMsg_CreateOffscreenSurface::WriteReplyParams(reply_message, |
| 381 route_id); |
| 382 Send(reply_message); |
| 322 } | 383 } |
| 323 | 384 |
| 324 void GpuChannel::OnDestroySurface(int route_id) { | 385 void GpuChannel::OnDestroySurface(int route_id) { |
| 325 #if defined(ENABLE_GPU) | 386 #if defined(ENABLE_GPU) |
| 326 if (router_.ResolveRoute(route_id)) { | 387 if (router_.ResolveRoute(route_id)) { |
| 327 router_.RemoveRoute(route_id); | 388 router_.RemoveRoute(route_id); |
| 328 surfaces_.Remove(route_id); | 389 surfaces_.Remove(route_id); |
| 329 } | 390 } |
| 330 #endif | 391 #endif |
| 331 } | 392 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 373 | 434 |
| 374 #if defined(OS_POSIX) | 435 #if defined(OS_POSIX) |
| 375 int GpuChannel::GetRendererFileDescriptor() { | 436 int GpuChannel::GetRendererFileDescriptor() { |
| 376 int fd = -1; | 437 int fd = -1; |
| 377 if (channel_.get()) { | 438 if (channel_.get()) { |
| 378 fd = channel_->GetClientFileDescriptor(); | 439 fd = channel_->GetClientFileDescriptor(); |
| 379 } | 440 } |
| 380 return fd; | 441 return fd; |
| 381 } | 442 } |
| 382 #endif // defined(OS_POSIX) | 443 #endif // defined(OS_POSIX) |
| OLD | NEW |