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 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
150 public: | 150 public: |
151 // Takes ownership of gpu_channel (see below). | 151 // Takes ownership of gpu_channel (see below). |
152 SyncPointMessageFilter(base::WeakPtr<GpuChannel>* gpu_channel, | 152 SyncPointMessageFilter(base::WeakPtr<GpuChannel>* gpu_channel, |
153 scoped_refptr<SyncPointManager> sync_point_manager, | 153 scoped_refptr<SyncPointManager> sync_point_manager, |
154 scoped_refptr<base::MessageLoopProxy> message_loop) | 154 scoped_refptr<base::MessageLoopProxy> message_loop) |
155 : preemption_state_(IDLE), | 155 : preemption_state_(IDLE), |
156 gpu_channel_(gpu_channel), | 156 gpu_channel_(gpu_channel), |
157 channel_(NULL), | 157 channel_(NULL), |
158 sync_point_manager_(sync_point_manager), | 158 sync_point_manager_(sync_point_manager), |
159 message_loop_(message_loop), | 159 message_loop_(message_loop), |
160 messages_received_(0) { | 160 messages_received_(0), |
161 a_stub_is_descheduled_(false) { | |
161 } | 162 } |
162 | 163 |
163 virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE { | 164 virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE { |
164 DCHECK(!channel_); | 165 DCHECK(!channel_); |
165 channel_ = channel; | 166 channel_ = channel; |
166 } | 167 } |
167 | 168 |
168 virtual void OnFilterRemoved() OVERRIDE { | 169 virtual void OnFilterRemoved() OVERRIDE { |
169 DCHECK(channel_); | 170 DCHECK(channel_); |
170 channel_ = NULL; | 171 channel_ = NULL; |
(...skipping 29 matching lines...) Expand all Loading... | |
200 } | 201 } |
201 } | 202 } |
202 | 203 |
203 void MessageProcessed(uint64 messages_processed) { | 204 void MessageProcessed(uint64 messages_processed) { |
204 while (!pending_messages_.empty() && | 205 while (!pending_messages_.empty() && |
205 pending_messages_.front().message_number <= messages_processed) | 206 pending_messages_.front().message_number <= messages_processed) |
206 pending_messages_.pop(); | 207 pending_messages_.pop(); |
207 UpdatePreemptionState(); | 208 UpdatePreemptionState(); |
208 } | 209 } |
209 | 210 |
210 void SetPreemptingFlag(gpu::PreemptionFlag* preempting_flag) { | 211 void SetPreemptingFlagAndSchedulingState( |
212 gpu::PreemptionFlag* preempting_flag, | |
213 bool a_stub_is_descheduled) { | |
211 preempting_flag_ = preempting_flag; | 214 preempting_flag_ = preempting_flag; |
215 a_stub_is_descheduled_ = a_stub_is_descheduled; | |
216 } | |
217 | |
218 void UpdateStubSchedulingState(bool a_stub_is_descheduled) { | |
piman
2013/02/27 21:54:43
I'm afraid this will kick preemption more than you
jonathan.backer
2013/02/28 21:43:56
Done.
| |
219 a_stub_is_descheduled_ = a_stub_is_descheduled; | |
220 if (preemption_state_ == PREEMPTING) { | |
221 if (a_stub_is_descheduled_) | |
222 preempting_flag_->Reset(); | |
223 else | |
224 preempting_flag_->Set(); | |
225 } | |
212 } | 226 } |
213 | 227 |
214 protected: | 228 protected: |
215 virtual ~SyncPointMessageFilter() { | 229 virtual ~SyncPointMessageFilter() { |
216 message_loop_->PostTask(FROM_HERE, base::Bind( | 230 message_loop_->PostTask(FROM_HERE, base::Bind( |
217 &SyncPointMessageFilter::DeleteWeakPtrOnMainThread, gpu_channel_)); | 231 &SyncPointMessageFilter::DeleteWeakPtrOnMainThread, gpu_channel_)); |
218 } | 232 } |
219 | 233 |
220 private: | 234 private: |
221 enum PreemptionState { | 235 enum PreemptionState { |
222 // Either there's no other channel to preempt, there are no messages | 236 // Either there's no other channel to preempt, there are no messages |
223 // pending processing, or we just finished preempting and have to wait | 237 // pending processing, or we just finished preempting and have to wait |
224 // before preempting again. | 238 // before preempting again. |
225 IDLE, | 239 IDLE, |
226 // We are waiting kPreemptWaitTimeMs before checking if we should preempt. | 240 // We are waiting kPreemptWaitTimeMs before checking if we should preempt. |
227 WAITING, | 241 WAITING, |
228 // We can preempt whenever any IPC processing takes more than | 242 // We can preempt whenever any IPC processing takes more than |
229 // kPreemptWaitTimeMs. | 243 // kPreemptWaitTimeMs. |
230 CHECKING, | 244 CHECKING, |
231 // We are currently preempting. | 245 // We are currently preempting if and only if all stubs on this channel |
246 // are scheduled. | |
232 PREEMPTING, | 247 PREEMPTING, |
233 }; | 248 }; |
234 | 249 |
235 PreemptionState preemption_state_; | 250 PreemptionState preemption_state_; |
236 | 251 |
237 struct PendingMessage { | 252 struct PendingMessage { |
238 uint64 message_number; | 253 uint64 message_number; |
239 base::TimeTicks time_received; | 254 base::TimeTicks time_received; |
240 | 255 |
241 explicit PendingMessage(uint64 message_number) | 256 explicit PendingMessage(uint64 message_number) |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
317 } | 332 } |
318 | 333 |
319 void TransitionToPreempting() { | 334 void TransitionToPreempting() { |
320 DCHECK_EQ(preemption_state_, CHECKING); | 335 DCHECK_EQ(preemption_state_, CHECKING); |
321 | 336 |
322 // Stop any pending state update checks that we may have queued | 337 // Stop any pending state update checks that we may have queued |
323 // while CHECKING. | 338 // while CHECKING. |
324 timer_.Stop(); | 339 timer_.Stop(); |
325 | 340 |
326 preemption_state_ = PREEMPTING; | 341 preemption_state_ = PREEMPTING; |
327 preempting_flag_->Set(); | 342 if (!a_stub_is_descheduled_) |
343 preempting_flag_->Set(); | |
328 TRACE_COUNTER_ID1("gpu", "GpuChannel::Preempting", this, 1); | 344 TRACE_COUNTER_ID1("gpu", "GpuChannel::Preempting", this, 1); |
329 | 345 |
330 timer_.Start( | 346 timer_.Start( |
331 FROM_HERE, | 347 FROM_HERE, |
332 base::TimeDelta::FromMilliseconds(kMaxPreemptTimeMs), | 348 base::TimeDelta::FromMilliseconds(kMaxPreemptTimeMs), |
333 this, &SyncPointMessageFilter::TransitionToIdle); | 349 this, &SyncPointMessageFilter::TransitionToIdle); |
334 | 350 |
335 UpdatePreemptionState(); | 351 UpdatePreemptionState(); |
336 } | 352 } |
337 | 353 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
373 scoped_refptr<SyncPointManager> sync_point_manager_; | 389 scoped_refptr<SyncPointManager> sync_point_manager_; |
374 scoped_refptr<base::MessageLoopProxy> message_loop_; | 390 scoped_refptr<base::MessageLoopProxy> message_loop_; |
375 scoped_refptr<gpu::PreemptionFlag> preempting_flag_; | 391 scoped_refptr<gpu::PreemptionFlag> preempting_flag_; |
376 | 392 |
377 std::queue<PendingMessage> pending_messages_; | 393 std::queue<PendingMessage> pending_messages_; |
378 | 394 |
379 // Count of the number of IPCs received on this GpuChannel. | 395 // Count of the number of IPCs received on this GpuChannel. |
380 uint64 messages_received_; | 396 uint64 messages_received_; |
381 | 397 |
382 base::OneShotTimer<SyncPointMessageFilter> timer_; | 398 base::OneShotTimer<SyncPointMessageFilter> timer_; |
399 | |
400 bool a_stub_is_descheduled_; | |
383 }; | 401 }; |
384 | 402 |
385 GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, | 403 GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, |
386 GpuWatchdog* watchdog, | 404 GpuWatchdog* watchdog, |
387 gfx::GLShareGroup* share_group, | 405 gfx::GLShareGroup* share_group, |
388 gpu::gles2::MailboxManager* mailbox, | 406 gpu::gles2::MailboxManager* mailbox, |
389 int client_id, | 407 int client_id, |
390 bool software) | 408 bool software) |
391 : gpu_channel_manager_(gpu_channel_manager), | 409 : gpu_channel_manager_(gpu_channel_manager), |
392 messages_processed_(0), | 410 messages_processed_(0), |
393 client_id_(client_id), | 411 client_id_(client_id), |
394 share_group_(share_group ? share_group : new gfx::GLShareGroup), | 412 share_group_(share_group ? share_group : new gfx::GLShareGroup), |
395 mailbox_manager_(mailbox ? mailbox : new gpu::gles2::MailboxManager), | 413 mailbox_manager_(mailbox ? mailbox : new gpu::gles2::MailboxManager), |
396 image_manager_(new gpu::gles2::ImageManager), | 414 image_manager_(new gpu::gles2::ImageManager), |
397 watchdog_(watchdog), | 415 watchdog_(watchdog), |
398 software_(software), | 416 software_(software), |
399 handle_messages_scheduled_(false), | 417 handle_messages_scheduled_(false), |
400 processed_get_state_fast_(false), | 418 processed_get_state_fast_(false), |
401 currently_processing_message_(NULL), | 419 currently_processing_message_(NULL), |
402 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | 420 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
421 a_stub_is_descheduled_(false) { | |
403 DCHECK(gpu_channel_manager); | 422 DCHECK(gpu_channel_manager); |
404 DCHECK(client_id); | 423 DCHECK(client_id); |
405 | 424 |
406 channel_id_ = IPC::Channel::GenerateVerifiedChannelID("gpu"); | 425 channel_id_ = IPC::Channel::GenerateVerifiedChannelID("gpu"); |
407 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | 426 const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
408 log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages); | 427 log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages); |
409 disallowed_features_.multisampling = | 428 disallowed_features_.multisampling = |
410 command_line->HasSwitch(switches::kDisableGLMultisampling); | 429 command_line->HasSwitch(switches::kDisableGLMultisampling); |
411 #if defined(OS_ANDROID) | 430 #if defined(OS_ANDROID) |
412 stream_texture_manager_.reset(new StreamTextureManagerAndroid(this)); | 431 stream_texture_manager_.reset(new StreamTextureManagerAndroid(this)); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
538 // not emptied here, which ensures that OnMessageReceived will continue to | 557 // not emptied here, which ensures that OnMessageReceived will continue to |
539 // defer newly received messages until the ones in the queue have all been | 558 // defer newly received messages until the ones in the queue have all been |
540 // handled by HandleMessage. HandleMessage is invoked as a | 559 // handled by HandleMessage. HandleMessage is invoked as a |
541 // task to prevent reentrancy. | 560 // task to prevent reentrancy. |
542 MessageLoop::current()->PostTask( | 561 MessageLoop::current()->PostTask( |
543 FROM_HERE, | 562 FROM_HERE, |
544 base::Bind(&GpuChannel::HandleMessage, weak_factory_.GetWeakPtr())); | 563 base::Bind(&GpuChannel::HandleMessage, weak_factory_.GetWeakPtr())); |
545 handle_messages_scheduled_ = true; | 564 handle_messages_scheduled_ = true; |
546 } | 565 } |
547 | 566 |
567 void GpuChannel::StubSchedulingChanged() { | |
568 bool a_stub_is_descheduled = false; | |
569 for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_); | |
570 !it.IsAtEnd(); it.Advance()) { | |
piman
2013/02/27 21:54:43
Could we count scheduled stubs? If we fix the call
jonathan.backer
2013/02/28 21:43:56
Done. I'm concerned about teardown. I think I've h
| |
571 if (!it.GetCurrentValue()->IsScheduled()) { | |
572 a_stub_is_descheduled = true; | |
573 break; | |
574 } | |
575 } | |
576 if (a_stub_is_descheduled != a_stub_is_descheduled_) { | |
577 a_stub_is_descheduled_ = a_stub_is_descheduled; | |
578 if (preempting_flag_.get()) { | |
579 io_message_loop_->PostTask( | |
580 FROM_HERE, | |
581 base::Bind(&SyncPointMessageFilter::UpdateStubSchedulingState, | |
582 filter_, a_stub_is_descheduled)); | |
583 } | |
584 } | |
585 } | |
586 | |
548 void GpuChannel::CreateViewCommandBuffer( | 587 void GpuChannel::CreateViewCommandBuffer( |
549 const gfx::GLSurfaceHandle& window, | 588 const gfx::GLSurfaceHandle& window, |
550 int32 surface_id, | 589 int32 surface_id, |
551 const GPUCreateCommandBufferConfig& init_params, | 590 const GPUCreateCommandBufferConfig& init_params, |
552 int32* route_id) { | 591 int32* route_id) { |
553 TRACE_EVENT1("gpu", | 592 TRACE_EVENT1("gpu", |
554 "GpuChannel::CreateViewCommandBuffer", | 593 "GpuChannel::CreateViewCommandBuffer", |
555 "surface_id", | 594 "surface_id", |
556 surface_id); | 595 surface_id); |
557 | 596 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
642 | 681 |
643 void GpuChannel::RemoveRoute(int32 route_id) { | 682 void GpuChannel::RemoveRoute(int32 route_id) { |
644 router_.RemoveRoute(route_id); | 683 router_.RemoveRoute(route_id); |
645 } | 684 } |
646 | 685 |
647 gpu::PreemptionFlag* GpuChannel::GetPreemptionFlag() { | 686 gpu::PreemptionFlag* GpuChannel::GetPreemptionFlag() { |
648 if (!preempting_flag_.get()) { | 687 if (!preempting_flag_.get()) { |
649 preempting_flag_ = new gpu::PreemptionFlag; | 688 preempting_flag_ = new gpu::PreemptionFlag; |
650 io_message_loop_->PostTask( | 689 io_message_loop_->PostTask( |
651 FROM_HERE, | 690 FROM_HERE, |
652 base::Bind(&SyncPointMessageFilter::SetPreemptingFlag, | 691 base::Bind(&SyncPointMessageFilter::SetPreemptingFlagAndSchedulingState, |
653 filter_, preempting_flag_)); | 692 filter_, preempting_flag_, a_stub_is_descheduled_)); |
654 } | 693 } |
655 return preempting_flag_.get(); | 694 return preempting_flag_.get(); |
656 } | 695 } |
657 | 696 |
658 void GpuChannel::SetPreemptByFlag( | 697 void GpuChannel::SetPreemptByFlag( |
659 scoped_refptr<gpu::PreemptionFlag> preempted_flag) { | 698 scoped_refptr<gpu::PreemptionFlag> preempted_flag) { |
660 preempted_flag_ = preempted_flag; | 699 preempted_flag_ = preempted_flag; |
661 | 700 |
662 for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_); | 701 for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_); |
663 !it.IsAtEnd(); it.Advance()) { | 702 !it.IsAtEnd(); it.Advance()) { |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
850 messages_processed_++; | 889 messages_processed_++; |
851 if (preempting_flag_.get()) { | 890 if (preempting_flag_.get()) { |
852 io_message_loop_->PostTask( | 891 io_message_loop_->PostTask( |
853 FROM_HERE, | 892 FROM_HERE, |
854 base::Bind(&SyncPointMessageFilter::MessageProcessed, | 893 base::Bind(&SyncPointMessageFilter::MessageProcessed, |
855 filter_, messages_processed_)); | 894 filter_, messages_processed_)); |
856 } | 895 } |
857 } | 896 } |
858 | 897 |
859 } // namespace content | 898 } // namespace content |
OLD | NEW |