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 c74d4377693855de5493f5e1da6fb8536a511d54..3b717e2cc5404015b3731eeadb59f822e369cffc 100644 |
--- a/content/common/gpu/gpu_command_buffer_stub.cc |
+++ b/content/common/gpu/gpu_command_buffer_stub.cc |
@@ -91,6 +91,9 @@ void FastSetActiveURL(const GURL& url, size_t url_hash) { |
const int64 kHandleMoreWorkPeriodMs = 2; |
const int64 kHandleMoreWorkPeriodBusyMs = 1; |
Sami
2013/03/14 15:18:07
This seems unused now?
reveman
2013/03/14 19:21:47
Oh, thanks for noticing this. Latest patch makes s
|
+// Prevents idle work from being starved. |
+const int64 kMaxTimeSinceIdleMs = 10; |
+ |
} // namespace |
GpuCommandBufferStub::GpuCommandBufferStub( |
@@ -126,6 +129,7 @@ GpuCommandBufferStub::GpuCommandBufferStub( |
watchdog_(watchdog), |
sync_point_wait_count_(0), |
delayed_work_scheduled_(false), |
+ previous_messages_processed_(0), |
active_url_(active_url), |
total_gpu_memory_(0) { |
active_url_hash_ = base::Hash(active_url.possibly_invalid_spec()); |
@@ -211,7 +215,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(); |
DCHECK(handled); |
return handled; |
@@ -235,9 +239,35 @@ void GpuCommandBufferStub::PollWork() { |
FastSetActiveURL(active_url_, active_url_hash_); |
if (decoder_.get() && !MakeCurrent()) |
return; |
- if (scheduler_.get()) |
- scheduler_->PollUnscheduleFences(); |
- ScheduleDelayedWork(kHandleMoreWorkPeriodBusyMs); |
+ |
+ if (scheduler_.get()) { |
+ bool fences_complete = scheduler_->PollUnscheduleFences(); |
+ // Perform idle work if all fences are complete. |
+ if (fences_complete) { |
+ uint64 current_messages_processed = |
+ channel()->gpu_channel_manager()->MessagesProcessed(); |
+ // We're idle when no messages were processed or scheduled. |
+ bool is_idle = |
+ (previous_messages_processed_ == current_messages_processed) && |
+ !channel()->gpu_channel_manager()->HandleMessagesScheduled(); |
+ if (!is_idle && !last_idle_time_.is_null()) { |
+ base::TimeDelta time_since_idle = base::TimeTicks::Now() - |
+ last_idle_time_; |
+ base::TimeDelta max_time_since_idle = |
+ base::TimeDelta::FromMilliseconds(kMaxTimeSinceIdleMs); |
+ |
+ // Force idle when it's been too long since last time we were idle. |
+ if (time_since_idle > max_time_since_idle) |
+ is_idle = true; |
+ } |
+ |
+ if (is_idle) { |
+ last_idle_time_ = base::TimeTicks::Now(); |
+ scheduler_->PerformIdleWork(); |
+ } |
+ } |
+ } |
+ ScheduleDelayedWork(); |
} |
bool GpuCommandBufferStub::HasUnprocessedCommands() { |
@@ -249,15 +279,37 @@ bool GpuCommandBufferStub::HasUnprocessedCommands() { |
return false; |
} |
-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)); |
+void GpuCommandBufferStub::ScheduleDelayedWork() { |
+ if (!HasMoreWork()) { |
+ last_idle_time_ = base::TimeTicks(); |
+ return; |
} |
+ |
+ if (delayed_work_scheduled_) |
+ return; |
+ delayed_work_scheduled_ = true; |
+ |
+ // Idle when no messages are processed between now and when |
+ // PollWork is called. |
+ previous_messages_processed_ = |
+ channel()->gpu_channel_manager()->MessagesProcessed(); |
+ if (last_idle_time_.is_null()) |
+ last_idle_time_ = base::TimeTicks::Now(); |
+ |
+ int64 delay = kHandleMoreWorkPeriodMs; |
+ // No need for a delay when there's idle work to be done and we're |
epenner
2013/03/14 18:23:24
I think I get this, but would help to have "becaus
reveman
2013/03/14 19:21:47
I've updated this comment to make it more clear wh
|
+ // not waiting on unschedule fences. |
Sami
2013/03/14 15:18:07
Typo: unschedule
reveman
2013/03/14 19:21:47
It sounds awkward but this is what we currently ca
|
+ if (scheduler_.get() && |
+ scheduler_->IsScheduled() && |
+ scheduler_->HasMoreIdleWork()) { |
+ delay = 0; |
+ } |
+ |
+ MessageLoop::current()->PostDelayedTask( |
+ FROM_HERE, |
+ base::Bind(&GpuCommandBufferStub::PollWork, |
+ AsWeakPtr()), |
+ base::TimeDelta::FromMilliseconds(delay)); |
} |
void GpuCommandBufferStub::OnEcho(const IPC::Message& message) { |