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) { |