| 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;
|
|
|
| +// 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
|
| + // not waiting on unschedule fences.
|
| + 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) {
|
|
|