| Index: cc/scheduler/scheduler.cc
|
| diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
|
| index 5ffd59c095e62e1c67acc15acf582acdb3ce0f2c..57651c581f874f523e221ac63ff29493b7d7e01b 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) {
|
| + 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()) {
|
| @@ -395,12 +405,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();
|
| @@ -506,10 +510,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_.last_swap_ack_came_after_begin_impl_frame()) {
|
| + // Skip this BeginImplFrame by returning early.
|
| + state_machine_.DidSkipBeginImplFrameToReduceLatency();
|
| + return;
|
| }
|
|
|
| BeginImplFrame();
|
| @@ -821,15 +835,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 ||
|
|
|