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