Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: content/common/gpu/gpu_channel.cc

Issue 12226039: Reland 179911 and 179910 (Closed) Base URL: svn://svn.chromium.org/chrome/branches/1364/src
Patch Set: Delta from original landing that's necessary for M25 (not ToT) Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/common/gpu/gpu_channel.h ('k') | content/common/gpu/gpu_command_buffer_stub.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « content/common/gpu/gpu_channel.h ('k') | content/common/gpu/gpu_command_buffer_stub.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698