Chromium Code Reviews| Index: cc/scheduler/scheduler.cc |
| diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc |
| index afc908d6a6d4baebf4d8eb84f11e9012a0e9bdb2..3242af7009288f1392603e95176ededb7f604847 100644 |
| --- a/cc/scheduler/scheduler.cc |
| +++ b/cc/scheduler/scheduler.cc |
| @@ -129,8 +129,18 @@ base::TimeTicks Scheduler::Now() const { |
| return now; |
| } |
| +void Scheduler::SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) { |
|
brianderson
2015/05/08 16:52:50
SetAuthoritativeVSyncInterval changes are unrelate
|
| + authoritative_vsync_interval_ = interval; |
| + if (vsync_observer_) |
| + vsync_observer_->OnUpdateVSyncParameters(last_vsync_timebase_, interval); |
| +} |
| + |
| void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, |
| base::TimeDelta interval) { |
| + TRACE_EVENT2("cc", "Scheduler::CommitVSyncParameters", "timebase", |
| + (timebase - base::TimeTicks()).InSecondsF(), "interval", |
| + interval.InSecondsF()); |
| + |
| if (authoritative_vsync_interval_ != base::TimeDelta()) { |
| interval = authoritative_vsync_interval_; |
| } else if (interval == base::TimeDelta()) { |
| @@ -387,12 +397,6 @@ void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) { |
| ProcessScheduledActions(); |
| } |
| -void Scheduler::SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) { |
| - authoritative_vsync_interval_ = interval; |
| - if (vsync_observer_) |
| - vsync_observer_->OnUpdateVSyncParameters(last_vsync_timebase_, interval); |
| -} |
| - |
| void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) { |
| state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames); |
| ProcessScheduledActions(); |
| @@ -498,10 +502,20 @@ void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) { |
| begin_impl_frame_args_ = args; |
| begin_impl_frame_args_.deadline -= client_->DrawDurationEstimate(); |
| + // Prioritize skipping the main thread's latency first so we can keep the |
| + // main and impl threads synchronized. Then skip an impl frame if it makes |
| + // sense. This avoids skipping both at the same time to avoid strange |
| + // interactions/oscillations since CanDrawBeforeDeadline() depends on |
| + // whether the main thread is in a high latency mode or not. |
| if (!state_machine_.impl_latency_takes_priority() && |
| main_thread_is_in_high_latency_mode && |
| CanCommitAndActivateBeforeDeadline()) { |
| state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); |
| + } else if (CanDrawBeforeDeadline() && |
| + state_machine_.swaps_are_likely_high_latency()) { |
| + // Skip this BeginImplFrame by returning early. |
| + state_machine_.DidSkipBeginImplFrameToReduceLatency(); |
| + return; |
| } |
| BeginImplFrame(); |
| @@ -813,15 +827,41 @@ bool Scheduler::CanCommitAndActivateBeforeDeadline() const { |
| TRACE_EVENT2( |
| TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
| - "CanCommitAndActivateBeforeDeadline", |
| - "time_left_after_drawing_ms", |
| + "CanCommitAndActivateBeforeDeadline", "est_time_left_after_drawing_ms", |
| (begin_impl_frame_args_.deadline - estimated_draw_time).InMillisecondsF(), |
| - "state", |
| - AsValue()); |
| + "state", AsValue()); |
| return estimated_draw_time < begin_impl_frame_args_.deadline; |
| } |
| +bool Scheduler::CanDrawBeforeDeadline() const { |
| + bool main_thread_is_in_high_latency_mode = |
| + state_machine_.MainThreadIsInHighLatencyMode(); |
| + |
| + // Check if the main thread computation and commit can be finished before the |
| + // impl thread's deadline. |
| + base::TimeTicks estimated_draw_time = begin_impl_frame_args_.frame_time; |
| + if (!main_thread_is_in_high_latency_mode) { |
| + estimated_draw_time += client_->BeginMainFrameToCommitDurationEstimate() + |
| + client_->CommitToActivateDurationEstimate(); |
| + } |
| + |
| + base::TimeDelta time_left_after_drawing = |
| + begin_impl_frame_args_.deadline - estimated_draw_time; |
| + |
| + TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
| + "CanDrawBeforeDeadline", "time_left_after_drawing_ms", |
| + time_left_after_drawing.InMillisecondsF(), "state", AsValue()); |
| + |
| + // Ideally we could use a threshold of 0, but our deadlines are currently |
| + // just estimates, so we are extra careful not to skip frames if we aren't |
| + // absolutely sure the Impl thread can run in a low latency mode. |
| + // TODO(mithro): Replace this with SwapNack logic. |
| + base::TimeDelta threshold = BeginFrameArgs::DefaultEstimatedParentDrawTime(); |
| + |
| + return time_left_after_drawing > threshold; |
| +} |
| + |
| bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
| return (state_machine_.commit_state() == |
| SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |