| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 13 #include "base/debug/trace_event.h" | 13 #include "base/debug/trace_event.h" |
| 14 #include "base/message_loop_proxy.h" | 14 #include "base/message_loop_proxy.h" |
| 15 #include "base/process_util.h" | 15 #include "base/process_util.h" |
| 16 #include "base/rand_util.h" | 16 #include "base/rand_util.h" |
| 17 #include "base/string_util.h" | 17 #include "base/string_util.h" |
| 18 #include "base/timer.h" |
| 18 #include "content/common/child_process.h" | 19 #include "content/common/child_process.h" |
| 19 #include "content/common/gpu/gpu_channel_manager.h" | 20 #include "content/common/gpu/gpu_channel_manager.h" |
| 20 #include "content/common/gpu/gpu_messages.h" | 21 #include "content/common/gpu/gpu_messages.h" |
| 21 #include "content/common/gpu/sync_point_manager.h" | 22 #include "content/common/gpu/sync_point_manager.h" |
| 22 #include "content/public/common/content_switches.h" | 23 #include "content/public/common/content_switches.h" |
| 23 #include "crypto/hmac.h" | 24 #include "crypto/hmac.h" |
| 24 #include "gpu/command_buffer/service/image_manager.h" | 25 #include "gpu/command_buffer/service/image_manager.h" |
| 25 #include "gpu/command_buffer/service/mailbox_manager.h" | 26 #include "gpu/command_buffer/service/mailbox_manager.h" |
| 26 #include "gpu/command_buffer/service/gpu_scheduler.h" | 27 #include "gpu/command_buffer/service/gpu_scheduler.h" |
| 27 #include "ipc/ipc_channel.h" | 28 #include "ipc/ipc_channel.h" |
| 28 #include "ipc/ipc_channel_proxy.h" | 29 #include "ipc/ipc_channel_proxy.h" |
| 29 #include "ui/gl/gl_context.h" | 30 #include "ui/gl/gl_context.h" |
| 30 #include "ui/gl/gl_image.h" | 31 #include "ui/gl/gl_image.h" |
| 31 #include "ui/gl/gl_surface.h" | 32 #include "ui/gl/gl_surface.h" |
| 32 | 33 |
| 33 #if defined(OS_POSIX) | 34 #if defined(OS_POSIX) |
| 34 #include "ipc/ipc_channel_posix.h" | 35 #include "ipc/ipc_channel_posix.h" |
| 35 #endif | 36 #endif |
| 36 | 37 |
| 37 #if defined(OS_ANDROID) | 38 #if defined(OS_ANDROID) |
| 38 #include "content/common/gpu/stream_texture_manager_android.h" | 39 #include "content/common/gpu/stream_texture_manager_android.h" |
| 39 #endif | 40 #endif |
| 40 | 41 |
| 41 namespace content { | 42 namespace content { |
| 42 namespace { | 43 namespace { |
| 44 |
| 45 // How long to wait for an IPC on this channel to be processed before |
| 46 // signaling the need for a preemption. |
| 47 // TODO(backer): This should really be the time between vblank on |
| 48 // platforms that provide this information. |
| 49 const int64 kPreemptPeriodMs = 16; |
| 50 |
| 51 // Generates mailbox names for clients of the GPU process on the IO thread. |
| 52 class MailboxMessageFilter : public IPC::ChannelProxy::MessageFilter { |
| 53 public: |
| 54 explicit MailboxMessageFilter(const std::string& private_key) |
| 55 : channel_(NULL), |
| 56 hmac_(crypto::HMAC::SHA256) { |
| 57 bool success = hmac_.Init(base::StringPiece(private_key)); |
| 58 DCHECK(success); |
| 59 } |
| 60 |
| 61 virtual void OnFilterAdded(IPC::Channel* channel) { |
| 62 DCHECK(!channel_); |
| 63 channel_ = channel; |
| 64 } |
| 65 |
| 66 virtual void OnFilterRemoved() { |
| 67 DCHECK(channel_); |
| 68 channel_ = NULL; |
| 69 } |
| 70 |
| 71 virtual bool OnMessageReceived(const IPC::Message& message) { |
| 72 DCHECK(channel_); |
| 73 |
| 74 bool handled = true; |
| 75 IPC_BEGIN_MESSAGE_MAP(MailboxMessageFilter, message) |
| 76 IPC_MESSAGE_HANDLER(GpuChannelMsg_GenerateMailboxNames, |
| 77 OnGenerateMailboxNames) |
| 78 IPC_MESSAGE_HANDLER(GpuChannelMsg_GenerateMailboxNamesAsync, |
| 79 OnGenerateMailboxNamesAsync) |
| 80 IPC_MESSAGE_UNHANDLED(handled = false) |
| 81 IPC_END_MESSAGE_MAP() |
| 82 |
| 83 return handled; |
| 84 } |
| 85 |
| 86 bool Send(IPC::Message* message) { |
| 87 return channel_->Send(message); |
| 88 } |
| 89 |
| 90 private: |
| 91 ~MailboxMessageFilter() { |
| 92 } |
| 93 |
| 94 // Message handlers. |
| 95 void OnGenerateMailboxNames(unsigned num, std::vector<std::string>* result) { |
| 96 TRACE_EVENT1("gpu", "OnGenerateMailboxNames", "num", num); |
| 97 |
| 98 result->resize(num); |
| 99 |
| 100 for (unsigned i = 0; i < num; ++i) { |
| 101 char name[GL_MAILBOX_SIZE_CHROMIUM]; |
| 102 base::RandBytes(name, sizeof(name) / 2); |
| 103 |
| 104 bool success = hmac_.Sign( |
| 105 base::StringPiece(name, sizeof(name) / 2), |
| 106 reinterpret_cast<unsigned char*>(name) + sizeof(name) / 2, |
| 107 sizeof(name) / 2); |
| 108 DCHECK(success); |
| 109 |
| 110 (*result)[i].assign(name, sizeof(name)); |
| 111 } |
| 112 } |
| 113 |
| 114 void OnGenerateMailboxNamesAsync(unsigned num) { |
| 115 std::vector<std::string> names; |
| 116 OnGenerateMailboxNames(num, &names); |
| 117 Send(new GpuChannelMsg_GenerateMailboxNamesReply(names)); |
| 118 } |
| 119 |
| 120 IPC::Channel* channel_; |
| 121 crypto::HMAC hmac_; |
| 122 }; |
| 123 } // anonymous namespace |
| 124 |
| 43 // This filter does two things: | 125 // This filter does two things: |
| 44 // - it counts the number of messages coming in on the channel | 126 // - it counts the number of messages coming in on the channel |
| 45 // - it handles the GpuCommandBufferMsg_InsertSyncPoint message on the IO | 127 // - it handles the GpuCommandBufferMsg_InsertSyncPoint message on the IO |
| 46 // thread, generating the sync point ID and responding immediately, and then | 128 // thread, generating the sync point ID and responding immediately, and then |
| 47 // posting a task to insert the GpuCommandBufferMsg_RetireSyncPoint message | 129 // posting a task to insert the GpuCommandBufferMsg_RetireSyncPoint message |
| 48 // into the channel's queue. | 130 // into the channel's queue. |
| 49 class SyncPointMessageFilter : public IPC::ChannelProxy::MessageFilter { | 131 class SyncPointMessageFilter : public IPC::ChannelProxy::MessageFilter { |
| 50 public: | 132 public: |
| 51 // Takes ownership of gpu_channel (see below). | 133 // Takes ownership of gpu_channel (see below). |
| 52 SyncPointMessageFilter(base::WeakPtr<GpuChannel>* gpu_channel, | 134 SyncPointMessageFilter(base::WeakPtr<GpuChannel>* gpu_channel, |
| 53 scoped_refptr<SyncPointManager> sync_point_manager, | 135 scoped_refptr<SyncPointManager> sync_point_manager, |
| 54 scoped_refptr<base::MessageLoopProxy> message_loop, | 136 scoped_refptr<base::MessageLoopProxy> message_loop, |
| 55 scoped_refptr<gpu::RefCountedCounter> | 137 scoped_refptr<gpu::PreemptionFlag> processing_stalled, |
| 56 unprocessed_messages) | 138 base::AtomicRefCount* unprocessed_messages) |
| 57 : gpu_channel_(gpu_channel), | 139 : gpu_channel_(gpu_channel), |
| 58 channel_(NULL), | 140 channel_(NULL), |
| 59 sync_point_manager_(sync_point_manager), | 141 sync_point_manager_(sync_point_manager), |
| 60 message_loop_(message_loop), | 142 message_loop_(message_loop), |
| 143 processing_stalled_(processing_stalled), |
| 61 unprocessed_messages_(unprocessed_messages) { | 144 unprocessed_messages_(unprocessed_messages) { |
| 62 } | 145 } |
| 63 | 146 |
| 64 virtual void OnFilterAdded(IPC::Channel* channel) { | 147 virtual void OnFilterAdded(IPC::Channel* channel) { |
| 65 DCHECK(!channel_); | 148 DCHECK(!channel_); |
| 66 channel_ = channel; | 149 channel_ = channel; |
| 67 } | 150 } |
| 68 | 151 |
| 69 virtual void OnFilterRemoved() { | 152 virtual void OnFilterRemoved() { |
| 70 DCHECK(channel_); | 153 DCHECK(channel_); |
| 71 channel_ = NULL; | 154 channel_ = NULL; |
| 72 } | 155 } |
| 73 | 156 |
| 74 virtual bool OnMessageReceived(const IPC::Message& message) { | 157 virtual bool OnMessageReceived(const IPC::Message& message) { |
| 75 DCHECK(channel_); | 158 DCHECK(channel_); |
| 76 unprocessed_messages_->IncCount(); | 159 base::AtomicRefCountInc(unprocessed_messages_.get()); |
| 160 if (!timer_.IsRunning()) |
| 161 timer_.Start(FROM_HERE, |
| 162 base::TimeDelta::FromMilliseconds(kPreemptPeriodMs), |
| 163 this, &SyncPointMessageFilter::TriggerPreemption); |
| 77 if (message.type() == GpuCommandBufferMsg_InsertSyncPoint::ID) { | 164 if (message.type() == GpuCommandBufferMsg_InsertSyncPoint::ID) { |
| 78 uint32 sync_point = sync_point_manager_->GenerateSyncPoint(); | 165 uint32 sync_point = sync_point_manager_->GenerateSyncPoint(); |
| 79 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message); | 166 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message); |
| 80 GpuCommandBufferMsg_InsertSyncPoint::WriteReplyParams(reply, sync_point); | 167 GpuCommandBufferMsg_InsertSyncPoint::WriteReplyParams(reply, sync_point); |
| 81 channel_->Send(reply); | 168 channel_->Send(reply); |
| 82 message_loop_->PostTask(FROM_HERE, base::Bind( | 169 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 83 &SyncPointMessageFilter::InsertSyncPointOnMainThread, | 170 &SyncPointMessageFilter::InsertSyncPointOnMainThread, |
| 84 gpu_channel_, | 171 gpu_channel_, |
| 85 sync_point_manager_, | 172 sync_point_manager_, |
| 86 message.routing_id(), | 173 message.routing_id(), |
| 87 sync_point, | 174 sync_point, |
| 88 unprocessed_messages_)); | 175 unprocessed_messages_.get())); |
| 89 return true; | 176 return true; |
| 90 } else if (message.type() == GpuCommandBufferMsg_RetireSyncPoint::ID) { | 177 } else if (message.type() == GpuCommandBufferMsg_RetireSyncPoint::ID) { |
| 91 // This message should not be sent explicitly by the renderer. | 178 // This message should not be sent explicitly by the renderer. |
| 92 NOTREACHED(); | 179 NOTREACHED(); |
| 93 unprocessed_messages_->DecCount(); | 180 base::AtomicRefCountDec(unprocessed_messages_.get()); |
| 94 return true; | 181 return true; |
| 95 } else { | 182 } else { |
| 96 return false; | 183 return false; |
| 97 } | 184 } |
| 98 } | 185 } |
| 99 | 186 |
| 187 void TriggerPreemption() { |
| 188 if (!base::AtomicRefCountIsZero(unprocessed_messages_.get())) |
| 189 processing_stalled_->Set(); |
| 190 } |
| 191 |
| 192 void ReschedulePreemption() { |
| 193 processing_stalled_->Reset(); |
| 194 if (timer_.IsRunning()) |
| 195 timer_.Reset(); |
| 196 } |
| 197 |
| 100 protected: | 198 protected: |
| 101 virtual ~SyncPointMessageFilter() { | 199 virtual ~SyncPointMessageFilter() { |
| 102 message_loop_->PostTask(FROM_HERE, base::Bind( | 200 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 103 &SyncPointMessageFilter::DeleteWeakPtrOnMainThread, gpu_channel_)); | 201 &SyncPointMessageFilter::DeleteWeakPtrOnMainThread, gpu_channel_)); |
| 104 } | 202 } |
| 105 | 203 |
| 106 private: | 204 private: |
| 107 static void InsertSyncPointOnMainThread( | 205 static void InsertSyncPointOnMainThread( |
| 108 base::WeakPtr<GpuChannel>* gpu_channel, | 206 base::WeakPtr<GpuChannel>* gpu_channel, |
| 109 scoped_refptr<SyncPointManager> manager, | 207 scoped_refptr<SyncPointManager> manager, |
| 110 int32 routing_id, | 208 int32 routing_id, |
| 111 uint32 sync_point, | 209 uint32 sync_point, |
| 112 scoped_refptr<gpu::RefCountedCounter> unprocessed_messages_) { | 210 base::AtomicRefCount* unprocessed_messages) { |
| 113 // This function must ensure that the sync point will be retired. Normally | 211 // This function must ensure that the sync point will be retired. Normally |
| 114 // we'll find the stub based on the routing ID, and associate the sync point | 212 // we'll find the stub based on the routing ID, and associate the sync point |
| 115 // with it, but if that fails for any reason (channel or stub already | 213 // with it, but if that fails for any reason (channel or stub already |
| 116 // deleted, invalid routing id), we need to retire the sync point | 214 // deleted, invalid routing id), we need to retire the sync point |
| 117 // immediately. | 215 // immediately. |
| 118 if (gpu_channel->get()) { | 216 if (gpu_channel->get()) { |
| 119 GpuCommandBufferStub* stub = gpu_channel->get()->LookupCommandBuffer( | 217 GpuCommandBufferStub* stub = gpu_channel->get()->LookupCommandBuffer( |
| 120 routing_id); | 218 routing_id); |
| 121 if (stub) { | 219 if (stub) { |
| 122 stub->AddSyncPoint(sync_point); | 220 stub->AddSyncPoint(sync_point); |
| 123 GpuCommandBufferMsg_RetireSyncPoint message(routing_id, sync_point); | 221 GpuCommandBufferMsg_RetireSyncPoint message(routing_id, sync_point); |
| 124 gpu_channel->get()->OnMessageReceived(message); | 222 gpu_channel->get()->OnMessageReceived(message); |
| 125 return; | 223 return; |
| 126 } else { | 224 } else { |
| 127 unprocessed_messages_->DecCount(); | 225 base::AtomicRefCountDec(unprocessed_messages); |
| 128 } | 226 } |
| 129 } | 227 } |
| 130 manager->RetireSyncPoint(sync_point); | 228 manager->RetireSyncPoint(sync_point); |
| 131 } | 229 } |
| 132 | 230 |
| 133 static void DeleteWeakPtrOnMainThread( | 231 static void DeleteWeakPtrOnMainThread( |
| 134 base::WeakPtr<GpuChannel>* gpu_channel) { | 232 base::WeakPtr<GpuChannel>* gpu_channel) { |
| 135 delete gpu_channel; | 233 delete gpu_channel; |
| 136 } | 234 } |
| 137 | 235 |
| 138 // NOTE: this is a pointer to a weak pointer. It is never dereferenced on the | 236 // NOTE: this is a pointer to a weak pointer. It is never dereferenced on the |
| 139 // IO thread, it's only passed through - therefore the WeakPtr assumptions are | 237 // IO thread, it's only passed through - therefore the WeakPtr assumptions are |
| 140 // respected. | 238 // respected. |
| 141 base::WeakPtr<GpuChannel>* gpu_channel_; | 239 base::WeakPtr<GpuChannel>* gpu_channel_; |
| 142 IPC::Channel* channel_; | 240 IPC::Channel* channel_; |
| 143 scoped_refptr<SyncPointManager> sync_point_manager_; | 241 scoped_refptr<SyncPointManager> sync_point_manager_; |
| 144 scoped_refptr<base::MessageLoopProxy> message_loop_; | 242 scoped_refptr<base::MessageLoopProxy> message_loop_; |
| 145 scoped_refptr<gpu::RefCountedCounter> unprocessed_messages_; | 243 scoped_refptr<gpu::PreemptionFlag> processing_stalled_; |
| 244 scoped_ptr<base::AtomicRefCount> unprocessed_messages_; |
| 245 base::OneShotTimer<SyncPointMessageFilter> timer_; |
| 146 }; | 246 }; |
| 147 | 247 |
| 148 // Generates mailbox names for clients of the GPU process on the IO thread. | |
| 149 class MailboxMessageFilter : public IPC::ChannelProxy::MessageFilter { | |
| 150 public: | |
| 151 explicit MailboxMessageFilter(const std::string& private_key) | |
| 152 : channel_(NULL), | |
| 153 hmac_(crypto::HMAC::SHA256) { | |
| 154 bool success = hmac_.Init(base::StringPiece(private_key)); | |
| 155 DCHECK(success); | |
| 156 } | |
| 157 | |
| 158 virtual void OnFilterAdded(IPC::Channel* channel) { | |
| 159 DCHECK(!channel_); | |
| 160 channel_ = channel; | |
| 161 } | |
| 162 | |
| 163 virtual void OnFilterRemoved() { | |
| 164 DCHECK(channel_); | |
| 165 channel_ = NULL; | |
| 166 } | |
| 167 | |
| 168 virtual bool OnMessageReceived(const IPC::Message& message) { | |
| 169 DCHECK(channel_); | |
| 170 | |
| 171 bool handled = true; | |
| 172 IPC_BEGIN_MESSAGE_MAP(MailboxMessageFilter, message) | |
| 173 IPC_MESSAGE_HANDLER(GpuChannelMsg_GenerateMailboxNames, | |
| 174 OnGenerateMailboxNames) | |
| 175 IPC_MESSAGE_HANDLER(GpuChannelMsg_GenerateMailboxNamesAsync, | |
| 176 OnGenerateMailboxNamesAsync) | |
| 177 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 178 IPC_END_MESSAGE_MAP() | |
| 179 | |
| 180 return handled; | |
| 181 } | |
| 182 | |
| 183 bool Send(IPC::Message* message) { | |
| 184 return channel_->Send(message); | |
| 185 } | |
| 186 | |
| 187 private: | |
| 188 ~MailboxMessageFilter() { | |
| 189 } | |
| 190 | |
| 191 // Message handlers. | |
| 192 void OnGenerateMailboxNames(unsigned num, std::vector<std::string>* result) { | |
| 193 TRACE_EVENT1("gpu", "OnGenerateMailboxNames", "num", num); | |
| 194 | |
| 195 result->resize(num); | |
| 196 | |
| 197 for (unsigned i = 0; i < num; ++i) { | |
| 198 char name[GL_MAILBOX_SIZE_CHROMIUM]; | |
| 199 base::RandBytes(name, sizeof(name) / 2); | |
| 200 | |
| 201 bool success = hmac_.Sign( | |
| 202 base::StringPiece(name, sizeof(name) / 2), | |
| 203 reinterpret_cast<unsigned char*>(name) + sizeof(name) / 2, | |
| 204 sizeof(name) / 2); | |
| 205 DCHECK(success); | |
| 206 | |
| 207 (*result)[i].assign(name, sizeof(name)); | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 void OnGenerateMailboxNamesAsync(unsigned num) { | |
| 212 std::vector<std::string> names; | |
| 213 OnGenerateMailboxNames(num, &names); | |
| 214 Send(new GpuChannelMsg_GenerateMailboxNamesReply(names)); | |
| 215 } | |
| 216 | |
| 217 IPC::Channel* channel_; | |
| 218 crypto::HMAC hmac_; | |
| 219 }; | |
| 220 } // anonymous namespace | |
| 221 | |
| 222 GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, | 248 GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, |
| 223 GpuWatchdog* watchdog, | 249 GpuWatchdog* watchdog, |
| 224 gfx::GLShareGroup* share_group, | 250 gfx::GLShareGroup* share_group, |
| 225 gpu::gles2::MailboxManager* mailbox, | 251 gpu::gles2::MailboxManager* mailbox, |
| 226 int client_id, | 252 int client_id, |
| 227 bool software) | 253 bool software) |
| 228 : gpu_channel_manager_(gpu_channel_manager), | 254 : gpu_channel_manager_(gpu_channel_manager), |
| 229 unprocessed_messages_(new gpu::RefCountedCounter), | 255 unprocessed_messages_(NULL), |
| 256 processing_stalled_(new gpu::PreemptionFlag), |
| 230 client_id_(client_id), | 257 client_id_(client_id), |
| 231 share_group_(share_group ? share_group : new gfx::GLShareGroup), | 258 share_group_(share_group ? share_group : new gfx::GLShareGroup), |
| 232 mailbox_manager_(mailbox ? mailbox : new gpu::gles2::MailboxManager), | 259 mailbox_manager_(mailbox ? mailbox : new gpu::gles2::MailboxManager), |
| 233 image_manager_(new gpu::gles2::ImageManager), | 260 image_manager_(new gpu::gles2::ImageManager), |
| 234 watchdog_(watchdog), | 261 watchdog_(watchdog), |
| 235 software_(software), | 262 software_(software), |
| 236 handle_messages_scheduled_(false), | 263 handle_messages_scheduled_(false), |
| 237 processed_get_state_fast_(false), | 264 processed_get_state_fast_(false), |
| 238 currently_processing_message_(NULL), | 265 currently_processing_message_(NULL), |
| 239 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 266 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 259 channel_.reset(new IPC::SyncChannel( | 286 channel_.reset(new IPC::SyncChannel( |
| 260 channel_id_, | 287 channel_id_, |
| 261 IPC::Channel::MODE_SERVER, | 288 IPC::Channel::MODE_SERVER, |
| 262 this, | 289 this, |
| 263 io_message_loop, | 290 io_message_loop, |
| 264 false, | 291 false, |
| 265 shutdown_event)); | 292 shutdown_event)); |
| 266 | 293 |
| 267 base::WeakPtr<GpuChannel>* weak_ptr(new base::WeakPtr<GpuChannel>( | 294 base::WeakPtr<GpuChannel>* weak_ptr(new base::WeakPtr<GpuChannel>( |
| 268 weak_factory_.GetWeakPtr())); | 295 weak_factory_.GetWeakPtr())); |
| 269 scoped_refptr<SyncPointMessageFilter> filter(new SyncPointMessageFilter( | 296 unprocessed_messages_ = new base::AtomicRefCount(0); |
| 297 filter_ = new SyncPointMessageFilter( |
| 270 weak_ptr, | 298 weak_ptr, |
| 271 gpu_channel_manager_->sync_point_manager(), | 299 gpu_channel_manager_->sync_point_manager(), |
| 272 base::MessageLoopProxy::current(), | 300 base::MessageLoopProxy::current(), |
| 273 unprocessed_messages_)); | 301 processing_stalled_, |
| 274 channel_->AddFilter(filter); | 302 unprocessed_messages_); |
| 303 io_message_loop_ = io_message_loop; |
| 304 channel_->AddFilter(filter_); |
| 275 | 305 |
| 276 channel_->AddFilter( | 306 channel_->AddFilter( |
| 277 new MailboxMessageFilter(mailbox_manager_->private_key())); | 307 new MailboxMessageFilter(mailbox_manager_->private_key())); |
| 278 | 308 |
| 279 return true; | 309 return true; |
| 280 } | 310 } |
| 281 | 311 |
| 282 std::string GpuChannel::GetChannelName() { | 312 std::string GpuChannel::GetChannelName() { |
| 283 return channel_id_; | 313 return channel_id_; |
| 284 } | 314 } |
| 285 | 315 |
| 286 #if defined(OS_POSIX) | 316 #if defined(OS_POSIX) |
| 287 int GpuChannel::TakeRendererFileDescriptor() { | 317 int GpuChannel::TakeRendererFileDescriptor() { |
| 288 if (!channel_.get()) { | 318 if (!channel_.get()) { |
| 289 NOTREACHED(); | 319 NOTREACHED(); |
| 290 return -1; | 320 return -1; |
| 291 } | 321 } |
| 292 return channel_->TakeClientFileDescriptor(); | 322 return channel_->TakeClientFileDescriptor(); |
| 293 } | 323 } |
| 294 #endif // defined(OS_POSIX) | 324 #endif // defined(OS_POSIX) |
| 295 | 325 |
| 296 bool GpuChannel::OnMessageReceived(const IPC::Message& message) { | 326 bool GpuChannel::OnMessageReceived(const IPC::Message& message) { |
| 297 // Drop the count that was incremented on the IO thread because we are | |
| 298 // about to process that message. | |
| 299 unprocessed_messages_->DecCount(); | |
| 300 if (log_messages_) { | 327 if (log_messages_) { |
| 301 DVLOG(1) << "received message @" << &message << " on channel @" << this | 328 DVLOG(1) << "received message @" << &message << " on channel @" << this |
| 302 << " with type " << message.type(); | 329 << " with type " << message.type(); |
| 303 } | 330 } |
| 304 | 331 |
| 305 // Control messages are not deferred and can be handled out of order with | 332 // Control messages are not deferred and can be handled out of order with |
| 306 // respect to routed ones. | 333 // respect to routed ones. |
| 307 if (message.routing_id() == MSG_ROUTING_CONTROL) | 334 if (message.routing_id() == MSG_ROUTING_CONTROL) { |
| 335 MessageProcessed(); |
| 308 return OnControlMessageReceived(message); | 336 return OnControlMessageReceived(message); |
| 337 } |
| 309 | 338 |
| 339 bool message_processed = true; |
| 310 if (message.type() == GpuCommandBufferMsg_GetStateFast::ID) { | 340 if (message.type() == GpuCommandBufferMsg_GetStateFast::ID) { |
| 311 if (processed_get_state_fast_) { | 341 if (processed_get_state_fast_) { |
| 312 // Require a non-GetStateFast message in between two GetStateFast | 342 // Require a non-GetStateFast message in between two GetStateFast |
| 313 // messages, to ensure progress is made. | 343 // messages, to ensure progress is made. |
| 314 std::deque<IPC::Message*>::iterator point = deferred_messages_.begin(); | 344 std::deque<IPC::Message*>::iterator point = deferred_messages_.begin(); |
| 315 | 345 |
| 316 while (point != deferred_messages_.end() && | 346 while (point != deferred_messages_.end() && |
| 317 (*point)->type() == GpuCommandBufferMsg_GetStateFast::ID) { | 347 (*point)->type() == GpuCommandBufferMsg_GetStateFast::ID) { |
| 318 ++point; | 348 ++point; |
| 319 } | 349 } |
| 320 | 350 |
| 321 if (point != deferred_messages_.end()) { | 351 if (point != deferred_messages_.end()) { |
| 322 ++point; | 352 ++point; |
| 323 } | 353 } |
| 324 | 354 |
| 325 deferred_messages_.insert(point, new IPC::Message(message)); | 355 deferred_messages_.insert(point, new IPC::Message(message)); |
| 326 unprocessed_messages_->IncCount(); | 356 message_processed = false; |
| 327 } else { | 357 } else { |
| 328 // Move GetStateFast commands to the head of the queue, so the renderer | 358 // Move GetStateFast commands to the head of the queue, so the renderer |
| 329 // doesn't have to wait any longer than necessary. | 359 // doesn't have to wait any longer than necessary. |
| 330 deferred_messages_.push_front(new IPC::Message(message)); | 360 deferred_messages_.push_front(new IPC::Message(message)); |
| 331 unprocessed_messages_->IncCount(); | 361 message_processed = false; |
| 332 } | 362 } |
| 333 } else { | 363 } else { |
| 334 deferred_messages_.push_back(new IPC::Message(message)); | 364 deferred_messages_.push_back(new IPC::Message(message)); |
| 335 unprocessed_messages_->IncCount(); | 365 message_processed = false; |
| 336 } | 366 } |
| 337 | 367 |
| 368 if (message_processed) |
| 369 MessageProcessed(); |
| 370 |
| 338 OnScheduled(); | 371 OnScheduled(); |
| 339 | 372 |
| 340 return true; | 373 return true; |
| 341 } | 374 } |
| 342 | 375 |
| 343 void GpuChannel::OnChannelError() { | 376 void GpuChannel::OnChannelError() { |
| 344 gpu_channel_manager_->RemoveChannel(client_id_); | 377 gpu_channel_manager_->RemoveChannel(client_id_); |
| 345 } | 378 } |
| 346 | 379 |
| 347 bool GpuChannel::Send(IPC::Message* message) { | 380 bool GpuChannel::Send(IPC::Message* message) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 358 return false; | 391 return false; |
| 359 } | 392 } |
| 360 | 393 |
| 361 return channel_->Send(message); | 394 return channel_->Send(message); |
| 362 } | 395 } |
| 363 | 396 |
| 364 void GpuChannel::RequeueMessage() { | 397 void GpuChannel::RequeueMessage() { |
| 365 DCHECK(currently_processing_message_); | 398 DCHECK(currently_processing_message_); |
| 366 deferred_messages_.push_front( | 399 deferred_messages_.push_front( |
| 367 new IPC::Message(*currently_processing_message_)); | 400 new IPC::Message(*currently_processing_message_)); |
| 368 unprocessed_messages_->IncCount(); | 401 base::AtomicRefCountInc(unprocessed_messages_); |
| 369 currently_processing_message_ = NULL; | 402 currently_processing_message_ = NULL; |
| 370 } | 403 } |
| 371 | 404 |
| 372 void GpuChannel::OnScheduled() { | 405 void GpuChannel::OnScheduled() { |
| 373 if (handle_messages_scheduled_) | 406 if (handle_messages_scheduled_) |
| 374 return; | 407 return; |
| 375 // Post a task to handle any deferred messages. The deferred message queue is | 408 // Post a task to handle any deferred messages. The deferred message queue is |
| 376 // not emptied here, which ensures that OnMessageReceived will continue to | 409 // not emptied here, which ensures that OnMessageReceived will continue to |
| 377 // defer newly received messages until the ones in the queue have all been | 410 // defer newly received messages until the ones in the queue have all been |
| 378 // handled by HandleMessage. HandleMessage is invoked as a | 411 // handled by HandleMessage. HandleMessage is invoked as a |
| (...skipping 30 matching lines...) Expand all Loading... |
| 409 gfx::Size(), | 442 gfx::Size(), |
| 410 disallowed_features_, | 443 disallowed_features_, |
| 411 init_params.allowed_extensions, | 444 init_params.allowed_extensions, |
| 412 init_params.attribs, | 445 init_params.attribs, |
| 413 init_params.gpu_preference, | 446 init_params.gpu_preference, |
| 414 *route_id, | 447 *route_id, |
| 415 surface_id, | 448 surface_id, |
| 416 watchdog_, | 449 watchdog_, |
| 417 software_, | 450 software_, |
| 418 init_params.active_url)); | 451 init_params.active_url)); |
| 419 if (preempt_by_counter_.get()) | 452 if (preemption_flag_.get()) |
| 420 stub->SetPreemptByCounter(preempt_by_counter_); | 453 stub->SetPreemptByFlag(preemption_flag_); |
| 421 router_.AddRoute(*route_id, stub.get()); | 454 router_.AddRoute(*route_id, stub.get()); |
| 422 stubs_.AddWithID(stub.release(), *route_id); | 455 stubs_.AddWithID(stub.release(), *route_id); |
| 423 #endif // ENABLE_GPU | 456 #endif // ENABLE_GPU |
| 424 } | 457 } |
| 425 | 458 |
| 426 GpuCommandBufferStub* GpuChannel::LookupCommandBuffer(int32 route_id) { | 459 GpuCommandBufferStub* GpuChannel::LookupCommandBuffer(int32 route_id) { |
| 427 return stubs_.Lookup(route_id); | 460 return stubs_.Lookup(route_id); |
| 428 } | 461 } |
| 429 | 462 |
| 430 void GpuChannel::CreateImage( | 463 void GpuChannel::CreateImage( |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 } | 508 } |
| 476 | 509 |
| 477 void GpuChannel::AddRoute(int32 route_id, IPC::Listener* listener) { | 510 void GpuChannel::AddRoute(int32 route_id, IPC::Listener* listener) { |
| 478 router_.AddRoute(route_id, listener); | 511 router_.AddRoute(route_id, listener); |
| 479 } | 512 } |
| 480 | 513 |
| 481 void GpuChannel::RemoveRoute(int32 route_id) { | 514 void GpuChannel::RemoveRoute(int32 route_id) { |
| 482 router_.RemoveRoute(route_id); | 515 router_.RemoveRoute(route_id); |
| 483 } | 516 } |
| 484 | 517 |
| 485 void GpuChannel::SetPreemptByCounter( | 518 void GpuChannel::SetPreemptByFlag( |
| 486 scoped_refptr<gpu::RefCountedCounter> preempt_by_counter) { | 519 scoped_refptr<gpu::PreemptionFlag> preemption_flag) { |
| 487 preempt_by_counter_ = preempt_by_counter; | 520 preemption_flag_ = preemption_flag; |
| 488 | 521 |
| 489 for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_); | 522 for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_); |
| 490 !it.IsAtEnd(); it.Advance()) { | 523 !it.IsAtEnd(); it.Advance()) { |
| 491 it.GetCurrentValue()->SetPreemptByCounter(preempt_by_counter_); | 524 it.GetCurrentValue()->SetPreemptByFlag(preemption_flag_); |
| 492 } | 525 } |
| 493 } | 526 } |
| 494 | 527 |
| 495 GpuChannel::~GpuChannel() { | 528 GpuChannel::~GpuChannel() { |
| 496 unprocessed_messages_->Reset(); | 529 processing_stalled_->Reset(); |
| 497 } | 530 } |
| 498 | 531 |
| 499 void GpuChannel::OnDestroy() { | 532 void GpuChannel::OnDestroy() { |
| 500 TRACE_EVENT0("gpu", "GpuChannel::OnDestroy"); | 533 TRACE_EVENT0("gpu", "GpuChannel::OnDestroy"); |
| 501 gpu_channel_manager_->RemoveChannel(client_id_); | 534 gpu_channel_manager_->RemoveChannel(client_id_); |
| 502 } | 535 } |
| 503 | 536 |
| 504 bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) { | 537 bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) { |
| 505 // Always use IPC_MESSAGE_HANDLER_DELAY_REPLY for synchronous message handlers | 538 // Always use IPC_MESSAGE_HANDLER_DELAY_REPLY for synchronous message handlers |
| 506 // here. This is so the reply can be delayed if the scheduler is unscheduled. | 539 // here. This is so the reply can be delayed if the scheduler is unscheduled. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 529 handle_messages_scheduled_ = false; | 562 handle_messages_scheduled_ = false; |
| 530 | 563 |
| 531 if (!deferred_messages_.empty()) { | 564 if (!deferred_messages_.empty()) { |
| 532 IPC::Message* m = deferred_messages_.front(); | 565 IPC::Message* m = deferred_messages_.front(); |
| 533 GpuCommandBufferStub* stub = stubs_.Lookup(m->routing_id()); | 566 GpuCommandBufferStub* stub = stubs_.Lookup(m->routing_id()); |
| 534 | 567 |
| 535 if (stub && !stub->IsScheduled()) { | 568 if (stub && !stub->IsScheduled()) { |
| 536 if (m->type() == GpuCommandBufferMsg_Echo::ID) { | 569 if (m->type() == GpuCommandBufferMsg_Echo::ID) { |
| 537 stub->DelayEcho(m); | 570 stub->DelayEcho(m); |
| 538 deferred_messages_.pop_front(); | 571 deferred_messages_.pop_front(); |
| 539 unprocessed_messages_->DecCount(); | 572 MessageProcessed(); |
| 540 if (!deferred_messages_.empty()) | 573 if (!deferred_messages_.empty()) |
| 541 OnScheduled(); | 574 OnScheduled(); |
| 542 } | 575 } |
| 543 return; | 576 return; |
| 544 } | 577 } |
| 545 | 578 |
| 579 if (stub && stub->IsPreempted()) { |
| 580 OnScheduled(); |
| 581 return; |
| 582 } |
| 583 |
| 546 scoped_ptr<IPC::Message> message(m); | 584 scoped_ptr<IPC::Message> message(m); |
| 547 deferred_messages_.pop_front(); | 585 deferred_messages_.pop_front(); |
| 548 unprocessed_messages_->DecCount(); | 586 bool message_processed = true; |
| 549 | 587 |
| 550 processed_get_state_fast_ = | 588 processed_get_state_fast_ = |
| 551 (message->type() == GpuCommandBufferMsg_GetStateFast::ID); | 589 (message->type() == GpuCommandBufferMsg_GetStateFast::ID); |
| 552 | 590 |
| 553 currently_processing_message_ = message.get(); | 591 currently_processing_message_ = message.get(); |
| 554 bool result = router_.RouteMessage(*message); | 592 bool result = router_.RouteMessage(*message); |
| 555 currently_processing_message_ = NULL; | 593 currently_processing_message_ = NULL; |
| 556 | 594 |
| 557 // Handle deferred control messages. | 595 // Handle deferred control messages. |
| 558 if (!result) { | 596 if (!result) { |
| 559 // Respond to sync messages even if router failed to route. | 597 // Respond to sync messages even if router failed to route. |
| 560 if (message->is_sync()) { | 598 if (message->is_sync()) { |
| 561 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&*message); | 599 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&*message); |
| 562 reply->set_reply_error(); | 600 reply->set_reply_error(); |
| 563 Send(reply); | 601 Send(reply); |
| 564 } | 602 } |
| 565 } else { | 603 } else { |
| 566 // If the command buffer becomes unscheduled as a result of handling the | 604 // If the command buffer becomes unscheduled as a result of handling the |
| 567 // message but still has more commands to process, synthesize an IPC | 605 // message but still has more commands to process, synthesize an IPC |
| 568 // message to flush that command buffer. | 606 // message to flush that command buffer. |
| 569 if (stub) { | 607 if (stub) { |
| 570 if (stub->HasUnprocessedCommands()) { | 608 if (stub->HasUnprocessedCommands()) { |
| 571 deferred_messages_.push_front(new GpuCommandBufferMsg_Rescheduled( | 609 deferred_messages_.push_front(new GpuCommandBufferMsg_Rescheduled( |
| 572 stub->route_id())); | 610 stub->route_id())); |
| 573 unprocessed_messages_->IncCount(); | 611 message_processed = false; |
| 574 } | 612 } |
| 575 } | 613 } |
| 576 } | 614 } |
| 615 if (message_processed) |
| 616 MessageProcessed(); |
| 577 } | 617 } |
| 578 | 618 |
| 579 if (!deferred_messages_.empty()) { | 619 if (!deferred_messages_.empty()) { |
| 580 OnScheduled(); | 620 OnScheduled(); |
| 581 } | 621 } |
| 582 } | 622 } |
| 583 | 623 |
| 584 void GpuChannel::OnCreateOffscreenCommandBuffer( | 624 void GpuChannel::OnCreateOffscreenCommandBuffer( |
| 585 const gfx::Size& size, | 625 const gfx::Size& size, |
| 586 const GPUCreateCommandBufferConfig& init_params, | 626 const GPUCreateCommandBufferConfig& init_params, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 602 image_manager_.get(), | 642 image_manager_.get(), |
| 603 size, | 643 size, |
| 604 disallowed_features_, | 644 disallowed_features_, |
| 605 init_params.allowed_extensions, | 645 init_params.allowed_extensions, |
| 606 init_params.attribs, | 646 init_params.attribs, |
| 607 init_params.gpu_preference, | 647 init_params.gpu_preference, |
| 608 route_id, | 648 route_id, |
| 609 0, watchdog_, | 649 0, watchdog_, |
| 610 software_, | 650 software_, |
| 611 init_params.active_url)); | 651 init_params.active_url)); |
| 612 if (preempt_by_counter_.get()) | 652 if (preemption_flag_.get()) |
| 613 stub->SetPreemptByCounter(preempt_by_counter_); | 653 stub->SetPreemptByFlag(preemption_flag_); |
| 614 router_.AddRoute(route_id, stub.get()); | 654 router_.AddRoute(route_id, stub.get()); |
| 615 stubs_.AddWithID(stub.release(), route_id); | 655 stubs_.AddWithID(stub.release(), route_id); |
| 616 TRACE_EVENT1("gpu", "GpuChannel::OnCreateOffscreenCommandBuffer", | 656 TRACE_EVENT1("gpu", "GpuChannel::OnCreateOffscreenCommandBuffer", |
| 617 "route_id", route_id); | 657 "route_id", route_id); |
| 618 #endif | 658 #endif |
| 619 | 659 |
| 620 GpuChannelMsg_CreateOffscreenCommandBuffer::WriteReplyParams( | 660 GpuChannelMsg_CreateOffscreenCommandBuffer::WriteReplyParams( |
| 621 reply_message, | 661 reply_message, |
| 622 route_id); | 662 route_id); |
| 623 Send(reply_message); | 663 Send(reply_message); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 stats.total_processing_commands_time += total_processing_commands_time; | 725 stats.total_processing_commands_time += total_processing_commands_time; |
| 686 } | 726 } |
| 687 } | 727 } |
| 688 | 728 |
| 689 GpuChannelMsg_CollectRenderingStatsForSurface::WriteReplyParams( | 729 GpuChannelMsg_CollectRenderingStatsForSurface::WriteReplyParams( |
| 690 reply_message, | 730 reply_message, |
| 691 stats); | 731 stats); |
| 692 Send(reply_message); | 732 Send(reply_message); |
| 693 } | 733 } |
| 694 | 734 |
| 735 void GpuChannel::MessageProcessed() { |
| 736 base::AtomicRefCountDec(unprocessed_messages_); |
| 737 io_message_loop_->PostTask( |
| 738 FROM_HERE, |
| 739 base::Bind(&SyncPointMessageFilter::ReschedulePreemption, filter_)); |
| 740 } |
| 741 |
| 695 } // namespace content | 742 } // namespace content |
| OLD | NEW |