| 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 18 matching lines...) Expand all Loading... |
| 29 GpuWatchdog* watchdog, | 29 GpuWatchdog* watchdog, |
| 30 int renderer_id, | 30 int renderer_id, |
| 31 bool software) | 31 bool software) |
| 32 : gpu_channel_manager_(gpu_channel_manager), | 32 : gpu_channel_manager_(gpu_channel_manager), |
| 33 renderer_id_(renderer_id), | 33 renderer_id_(renderer_id), |
| 34 renderer_process_(base::kNullProcessHandle), | 34 renderer_process_(base::kNullProcessHandle), |
| 35 renderer_pid_(base::kNullProcessId), | 35 renderer_pid_(base::kNullProcessId), |
| 36 share_group_(new gfx::GLShareGroup), | 36 share_group_(new gfx::GLShareGroup), |
| 37 watchdog_(watchdog), | 37 watchdog_(watchdog), |
| 38 software_(software), | 38 software_(software), |
| 39 handle_messages_scheduled_(false), |
| 39 task_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 40 task_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| 40 DCHECK(gpu_channel_manager); | 41 DCHECK(gpu_channel_manager); |
| 41 DCHECK(renderer_id); | 42 DCHECK(renderer_id); |
| 42 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | 43 const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 43 log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages); | 44 log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages); |
| 44 disallowed_features_.multisampling = | 45 disallowed_features_.multisampling = |
| 45 command_line->HasSwitch(switches::kDisableGLMultisampling); | 46 command_line->HasSwitch(switches::kDisableGLMultisampling); |
| 46 disallowed_features_.driver_bug_workarounds = | 47 disallowed_features_.driver_bug_workarounds = |
| 47 command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds); | 48 command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds); |
| 48 } | 49 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 69 << " with type " << message.type(); | 70 << " with type " << message.type(); |
| 70 } | 71 } |
| 71 | 72 |
| 72 // Control messages are not deferred and can be handled out of order with | 73 // Control messages are not deferred and can be handled out of order with |
| 73 // respect to routed ones. Except for Echo, which must be deferred in order | 74 // respect to routed ones. Except for Echo, which must be deferred in order |
| 74 // to respect the asynchronous Mac SwapBuffers. | 75 // to respect the asynchronous Mac SwapBuffers. |
| 75 if (message.routing_id() == MSG_ROUTING_CONTROL && | 76 if (message.routing_id() == MSG_ROUTING_CONTROL && |
| 76 message.type() != GpuChannelMsg_Echo::ID) | 77 message.type() != GpuChannelMsg_Echo::ID) |
| 77 return OnControlMessageReceived(message); | 78 return OnControlMessageReceived(message); |
| 78 | 79 |
| 79 // If the channel is unscheduled, defer sync and async messages until it is | 80 if (message.type() == GpuCommandBufferMsg_GetStateFast::ID) { |
| 80 // rescheduled. Also, even if the channel is scheduled, do not allow newly | 81 // Move GetStateFast commands to the head of the queue, so the renderer |
| 81 // received messages to be handled before previously received deferred ones; | 82 // doesn't have to wait any longer than necessary. |
| 82 // append them to the deferred queue as well. | 83 deferred_messages_.push_front(new IPC::Message(message)); |
| 83 if (!IsScheduled() || !deferred_messages_.empty()) { | 84 } else { |
| 84 deferred_messages_.push(new IPC::Message(message)); | 85 deferred_messages_.push_back(new IPC::Message(message)); |
| 85 return true; | |
| 86 } | 86 } |
| 87 | 87 |
| 88 // Handle deferred control messages. | 88 if (IsScheduled()) |
| 89 if (message.routing_id() == MSG_ROUTING_CONTROL) | 89 OnScheduled(); |
| 90 return OnControlMessageReceived(message); | |
| 91 | |
| 92 if (!router_.RouteMessage(message)) { | |
| 93 // Respond to sync messages even if router failed to route. | |
| 94 if (message.is_sync()) { | |
| 95 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message); | |
| 96 reply->set_reply_error(); | |
| 97 Send(reply); | |
| 98 } | |
| 99 return false; | |
| 100 } | |
| 101 | |
| 102 // If the channel becomes unscheduled as a result of handling the message, | |
| 103 // synthesize an IPC message to flush the command buffer that became | |
| 104 // unscheduled. | |
| 105 for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_); | |
| 106 !it.IsAtEnd(); | |
| 107 it.Advance()) { | |
| 108 GpuCommandBufferStub* stub = it.GetCurrentValue(); | |
| 109 if (!stub->IsScheduled()) { | |
| 110 DCHECK(deferred_messages_.empty()); | |
| 111 deferred_messages_.push(new GpuCommandBufferMsg_Rescheduled( | |
| 112 stub->route_id())); | |
| 113 } | |
| 114 } | |
| 115 | 90 |
| 116 return true; | 91 return true; |
| 117 } | 92 } |
| 118 | 93 |
| 119 void GpuChannel::OnChannelError() { | 94 void GpuChannel::OnChannelError() { |
| 120 gpu_channel_manager_->RemoveChannel(renderer_id_); | 95 gpu_channel_manager_->RemoveChannel(renderer_id_); |
| 121 } | 96 } |
| 122 | 97 |
| 123 void GpuChannel::OnChannelConnected(int32 peer_pid) { | 98 void GpuChannel::OnChannelConnected(int32 peer_pid) { |
| 124 renderer_pid_ = peer_pid; | 99 renderer_pid_ = peer_pid; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 147 it.Advance()) { | 122 it.Advance()) { |
| 148 GpuCommandBufferStub* stub = it.GetCurrentValue(); | 123 GpuCommandBufferStub* stub = it.GetCurrentValue(); |
| 149 if (!stub->IsScheduled()) | 124 if (!stub->IsScheduled()) |
| 150 return false; | 125 return false; |
| 151 } | 126 } |
| 152 | 127 |
| 153 return true; | 128 return true; |
| 154 } | 129 } |
| 155 | 130 |
| 156 void GpuChannel::OnScheduled() { | 131 void GpuChannel::OnScheduled() { |
| 132 if (handle_messages_scheduled_) |
| 133 return; |
| 157 // Post a task to handle any deferred messages. The deferred message queue is | 134 // Post a task to handle any deferred messages. The deferred message queue is |
| 158 // not emptied here, which ensures that OnMessageReceived will continue to | 135 // not emptied here, which ensures that OnMessageReceived will continue to |
| 159 // defer newly received messages until the ones in the queue have all been | 136 // defer newly received messages until the ones in the queue have all been |
| 160 // handled by HandleDeferredMessages. HandleDeferredMessages is invoked as a | 137 // handled by HandleDeferredMessages. HandleDeferredMessages is invoked as a |
| 161 // task to prevent reentrancy. | 138 // task to prevent reentrancy. |
| 162 MessageLoop::current()->PostTask( | 139 MessageLoop::current()->PostTask( |
| 163 FROM_HERE, | 140 FROM_HERE, |
| 164 task_factory_.NewRunnableMethod( | 141 task_factory_.NewRunnableMethod( |
| 165 &GpuChannel::HandleDeferredMessages)); | 142 &GpuChannel::HandleMessage)); |
| 143 handle_messages_scheduled_ = true; |
| 166 } | 144 } |
| 167 | 145 |
| 168 void GpuChannel::LoseAllContexts() { | 146 void GpuChannel::LoseAllContexts() { |
| 169 gpu_channel_manager_->LoseAllContexts(); | 147 gpu_channel_manager_->LoseAllContexts(); |
| 170 } | 148 } |
| 171 | 149 |
| 172 void GpuChannel::DestroySoon() { | 150 void GpuChannel::DestroySoon() { |
| 173 MessageLoop::current()->PostTask( | 151 MessageLoop::current()->PostTask( |
| 174 FROM_HERE, NewRunnableMethod(this, | 152 FROM_HERE, NewRunnableMethod(this, |
| 175 &GpuChannel::OnDestroy)); | 153 &GpuChannel::OnDestroy)); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 OnDestroyCommandBuffer) | 227 OnDestroyCommandBuffer) |
| 250 IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateTransportTexture, | 228 IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateTransportTexture, |
| 251 OnCreateTransportTexture) | 229 OnCreateTransportTexture) |
| 252 IPC_MESSAGE_HANDLER(GpuChannelMsg_Echo, OnEcho); | 230 IPC_MESSAGE_HANDLER(GpuChannelMsg_Echo, OnEcho); |
| 253 IPC_MESSAGE_UNHANDLED(handled = false) | 231 IPC_MESSAGE_UNHANDLED(handled = false) |
| 254 IPC_END_MESSAGE_MAP() | 232 IPC_END_MESSAGE_MAP() |
| 255 DCHECK(handled) << msg.type(); | 233 DCHECK(handled) << msg.type(); |
| 256 return handled; | 234 return handled; |
| 257 } | 235 } |
| 258 | 236 |
| 259 void GpuChannel::HandleDeferredMessages() { | 237 void GpuChannel::HandleMessage() { |
| 260 // Empty the deferred queue so OnMessageRecieved does not defer on that | 238 handle_messages_scheduled_ = false; |
| 261 // account and to prevent an infinite loop if the scheduler is unscheduled | 239 if (!IsScheduled()) |
| 262 // as a result of handling already deferred messages. | 240 return; |
| 263 std::queue<IPC::Message*> deferred_messages_copy; | |
| 264 std::swap(deferred_messages_copy, deferred_messages_); | |
| 265 | 241 |
| 266 while (!deferred_messages_copy.empty()) { | 242 if (!deferred_messages_.empty()) { |
| 267 scoped_ptr<IPC::Message> message(deferred_messages_copy.front()); | 243 scoped_ptr<IPC::Message> message(deferred_messages_.front()); |
| 268 deferred_messages_copy.pop(); | 244 deferred_messages_.pop_front(); |
| 245 // Handle deferred control messages. |
| 246 if (message->routing_id() == MSG_ROUTING_CONTROL) |
| 247 OnControlMessageReceived(*message); |
| 248 else if (!router_.RouteMessage(*message)) { |
| 249 // Respond to sync messages even if router failed to route. |
| 250 if (message->is_sync()) { |
| 251 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&*message); |
| 252 reply->set_reply_error(); |
| 253 Send(reply); |
| 254 } |
| 255 } else { |
| 256 // If the channel becomes unscheduled as a result of handling the message, |
| 257 // synthesize an IPC message to flush the command buffer that became |
| 258 // unscheduled. |
| 259 for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_); |
| 260 !it.IsAtEnd(); |
| 261 it.Advance()) { |
| 262 GpuCommandBufferStub* stub = it.GetCurrentValue(); |
| 263 if (!stub->IsScheduled()) { |
| 264 deferred_messages_.push_front(new GpuCommandBufferMsg_Rescheduled( |
| 265 stub->route_id())); |
| 266 } |
| 267 } |
| 268 } |
| 269 } |
| 269 | 270 |
| 270 OnMessageReceived(*message); | 271 if (IsScheduled() && !deferred_messages_.empty()) { |
| 272 OnScheduled(); |
| 271 } | 273 } |
| 272 } | 274 } |
| 273 | 275 |
| 274 int GpuChannel::GenerateRouteID() { | 276 int GpuChannel::GenerateRouteID() { |
| 275 static int last_id = 0; | 277 static int last_id = 0; |
| 276 return ++last_id; | 278 return ++last_id; |
| 277 } | 279 } |
| 278 | 280 |
| 279 void GpuChannel::AddRoute(int32 route_id, IPC::Channel::Listener* listener) { | 281 void GpuChannel::AddRoute(int32 route_id, IPC::Channel::Listener* listener) { |
| 280 router_.AddRoute(route_id, listener); | 282 router_.AddRoute(route_id, listener); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 | 399 |
| 398 #if defined(OS_POSIX) | 400 #if defined(OS_POSIX) |
| 399 int GpuChannel::TakeRendererFileDescriptor() { | 401 int GpuChannel::TakeRendererFileDescriptor() { |
| 400 if (!channel_.get()) { | 402 if (!channel_.get()) { |
| 401 NOTREACHED(); | 403 NOTREACHED(); |
| 402 return -1; | 404 return -1; |
| 403 } | 405 } |
| 404 return channel_->TakeClientFileDescriptor(); | 406 return channel_->TakeClientFileDescriptor(); |
| 405 } | 407 } |
| 406 #endif // defined(OS_POSIX) | 408 #endif // defined(OS_POSIX) |
| OLD | NEW |