Chromium Code Reviews| Index: content/common/gpu/gpu_command_buffer_stub.cc |
| diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc |
| index 7e539969cf33d195c377cdd21083c8369208a50a..306408f1d84e50c3716cafd2b4104d59763d06fe 100644 |
| --- a/content/common/gpu/gpu_command_buffer_stub.cc |
| +++ b/content/common/gpu/gpu_command_buffer_stub.cc |
| @@ -88,8 +88,13 @@ void FastSetActiveURL(const GURL& url, size_t url_hash) { |
| // The first time polling a fence, delay some extra time to allow other |
| // stubs to process some work, or else the timing of the fences could |
| // allow a pattern of alternating fast and slow frames to occur. |
| -const int64 kHandleMoreWorkPeriodMs = 2; |
| -const int64 kHandleMoreWorkPeriodBusyMs = 1; |
| +const int64 kHandleMoreWorkPeriodMicroseconds = 2000; |
| +const int64 kHandleMoreWorkPeriodBusyMicroseconds = 1000; |
| + |
| +// Use a shorter delay when there'ss idle work to be done. |
|
Sami
2013/03/07 16:57:19
Typo: there'ss
reveman
2013/03/07 20:21:04
Done.
|
| +const int64 kHandleMoreIdleWorkPeriodBusyMicroseconds = 100; |
| +// Prevents idle work from being starved. |
| +const int64 kMaxTimeSinceIdleMicroseconds = 10000; |
| } // namespace |
| @@ -126,6 +131,7 @@ GpuCommandBufferStub::GpuCommandBufferStub( |
| watchdog_(watchdog), |
| sync_point_wait_count_(0), |
| delayed_work_scheduled_(false), |
| + is_idle_(false), |
| active_url_(active_url), |
| total_gpu_memory_(0) { |
| active_url_hash_ = base::Hash(active_url.possibly_invalid_spec()); |
| @@ -166,6 +172,8 @@ bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) { |
| return false; |
| } |
| + is_idle_ = false; |
| + |
| // Always use IPC_MESSAGE_HANDLER_DELAY_REPLY for synchronous message handlers |
| // here. This is so the reply can be delayed if the scheduler is unscheduled. |
| bool handled = true; |
| @@ -211,7 +219,7 @@ bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) { |
| IPC_END_MESSAGE_MAP() |
| // Ensure that any delayed work that was created will be handled. |
| - ScheduleDelayedWork(kHandleMoreWorkPeriodMs); |
| + ScheduleDelayedWork(kHandleMoreWorkPeriodMicroseconds); |
| DCHECK(handled); |
| return handled; |
| @@ -235,9 +243,28 @@ void GpuCommandBufferStub::PollWork() { |
| FastSetActiveURL(active_url_, active_url_hash_); |
| if (decoder_.get() && !MakeCurrent()) |
| return; |
| - if (scheduler_.get()) |
| - scheduler_->PollUnscheduleFences(); |
| - ScheduleDelayedWork(kHandleMoreWorkPeriodBusyMs); |
| + int64 delay = kHandleMoreWorkPeriodBusyMicroseconds; |
| + if (scheduler_.get()) { |
| + bool fences_complete = scheduler_->PollUnscheduleFences(); |
| + // Perform idle work if all fences are complete. |
| + if (fences_complete) { |
| + DCHECK(!last_idle_time_.is_null()); |
| + base::TimeDelta time_since_idle = base::TimeTicks::Now() - |
| + last_idle_time_; |
| + base::TimeDelta max_time_since_idle = |
| + base::TimeDelta::FromMicroseconds(kMaxTimeSinceIdleMicroseconds); |
| + |
| + // Perform some idle work if idle or it's been too long since |
| + // last time we were idle. |
| + if (is_idle_ || time_since_idle > max_time_since_idle) { |
| + last_idle_time_ = base::TimeTicks::Now(); |
| + // Use idle work period delay when there's more idle work pending. |
| + if (scheduler_->PerformIdleWork()) |
| + delay = kHandleMoreIdleWorkPeriodBusyMicroseconds; |
| + } |
| + } |
| + } |
| + ScheduleDelayedWork(delay); |
| } |
| bool GpuCommandBufferStub::HasUnprocessedCommands() { |
| @@ -250,14 +277,26 @@ bool GpuCommandBufferStub::HasUnprocessedCommands() { |
| } |
| void GpuCommandBufferStub::ScheduleDelayedWork(int64 delay) { |
| - if (HasMoreWork() && !delayed_work_scheduled_) { |
| - delayed_work_scheduled_ = true; |
| - MessageLoop::current()->PostDelayedTask( |
| - FROM_HERE, |
| - base::Bind(&GpuCommandBufferStub::PollWork, |
| - AsWeakPtr()), |
| - base::TimeDelta::FromMilliseconds(delay)); |
| + if (!HasMoreWork()) { |
| + last_idle_time_ = base::TimeTicks(); |
| + return; |
| } |
| + |
| + if (delayed_work_scheduled_) |
| + return; |
| + delayed_work_scheduled_ = true; |
| + |
| + // Consider the command buffer idle if no messages are received between |
| + // now and when PollWork is called. |
| + is_idle_ = true; |
| + if (last_idle_time_.is_null()) |
| + last_idle_time_ = base::TimeTicks::Now(); |
| + |
| + MessageLoop::current()->PostDelayedTask( |
| + FROM_HERE, |
| + base::Bind(&GpuCommandBufferStub::PollWork, |
| + AsWeakPtr()), |
| + base::TimeDelta::FromMicroseconds(delay)); |
| } |
| void GpuCommandBufferStub::OnEcho(const IPC::Message& message) { |