OLD | NEW |
---|---|
1 // Copyright 2011 The Chromium Authors. All rights reserved. | 1 // Copyright 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/scheduler/scheduler.h" | 5 #include "cc/scheduler/scheduler.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
122 | 122 |
123 base::TimeTicks Scheduler::Now() const { | 123 base::TimeTicks Scheduler::Now() const { |
124 base::TimeTicks now = gfx::FrameTime::Now(); | 124 base::TimeTicks now = gfx::FrameTime::Now(); |
125 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now"), | 125 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now"), |
126 "Scheduler::Now", | 126 "Scheduler::Now", |
127 "now", | 127 "now", |
128 now); | 128 now); |
129 return now; | 129 return now; |
130 } | 130 } |
131 | 131 |
132 void Scheduler::SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) { | |
brianderson
2015/05/08 16:52:50
SetAuthoritativeVSyncInterval changes are unrelate
| |
133 authoritative_vsync_interval_ = interval; | |
134 if (vsync_observer_) | |
135 vsync_observer_->OnUpdateVSyncParameters(last_vsync_timebase_, interval); | |
136 } | |
137 | |
132 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, | 138 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, |
133 base::TimeDelta interval) { | 139 base::TimeDelta interval) { |
140 TRACE_EVENT2("cc", "Scheduler::CommitVSyncParameters", "timebase", | |
141 (timebase - base::TimeTicks()).InSecondsF(), "interval", | |
142 interval.InSecondsF()); | |
143 | |
134 if (authoritative_vsync_interval_ != base::TimeDelta()) { | 144 if (authoritative_vsync_interval_ != base::TimeDelta()) { |
135 interval = authoritative_vsync_interval_; | 145 interval = authoritative_vsync_interval_; |
136 } else if (interval == base::TimeDelta()) { | 146 } else if (interval == base::TimeDelta()) { |
137 // TODO(brianderson): We should not be receiving 0 intervals. | 147 // TODO(brianderson): We should not be receiving 0 intervals. |
138 interval = BeginFrameArgs::DefaultInterval(); | 148 interval = BeginFrameArgs::DefaultInterval(); |
139 } | 149 } |
140 | 150 |
141 last_vsync_timebase_ = timebase; | 151 last_vsync_timebase_ = timebase; |
142 | 152 |
143 if (vsync_observer_) | 153 if (vsync_observer_) |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
380 BeginImplFrameWithDeadline(adjusted_args); | 390 BeginImplFrameWithDeadline(adjusted_args); |
381 } | 391 } |
382 return true; | 392 return true; |
383 } | 393 } |
384 | 394 |
385 void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) { | 395 void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) { |
386 state_machine_.SetChildrenNeedBeginFrames(children_need_begin_frames); | 396 state_machine_.SetChildrenNeedBeginFrames(children_need_begin_frames); |
387 ProcessScheduledActions(); | 397 ProcessScheduledActions(); |
388 } | 398 } |
389 | 399 |
390 void Scheduler::SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) { | |
391 authoritative_vsync_interval_ = interval; | |
392 if (vsync_observer_) | |
393 vsync_observer_->OnUpdateVSyncParameters(last_vsync_timebase_, interval); | |
394 } | |
395 | |
396 void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) { | 400 void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) { |
397 state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames); | 401 state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames); |
398 ProcessScheduledActions(); | 402 ProcessScheduledActions(); |
399 } | 403 } |
400 | 404 |
401 void Scheduler::OnDrawForOutputSurface() { | 405 void Scheduler::OnDrawForOutputSurface() { |
402 DCHECK(settings_.using_synchronous_renderer_compositor); | 406 DCHECK(settings_.using_synchronous_renderer_compositor); |
403 DCHECK_EQ(state_machine_.begin_impl_frame_state(), | 407 DCHECK_EQ(state_machine_.begin_impl_frame_state(), |
404 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 408 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
405 DCHECK(!BeginImplFrameDeadlinePending()); | 409 DCHECK(!BeginImplFrameDeadlinePending()); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
491 args.AsValue(), "main_thread_is_high_latency", | 495 args.AsValue(), "main_thread_is_high_latency", |
492 main_thread_is_in_high_latency_mode); | 496 main_thread_is_in_high_latency_mode); |
493 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 497 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
494 "MainThreadLatency", main_thread_is_in_high_latency_mode); | 498 "MainThreadLatency", main_thread_is_in_high_latency_mode); |
495 | 499 |
496 advance_commit_state_task_.Cancel(); | 500 advance_commit_state_task_.Cancel(); |
497 | 501 |
498 begin_impl_frame_args_ = args; | 502 begin_impl_frame_args_ = args; |
499 begin_impl_frame_args_.deadline -= client_->DrawDurationEstimate(); | 503 begin_impl_frame_args_.deadline -= client_->DrawDurationEstimate(); |
500 | 504 |
505 // Prioritize skipping the main thread's latency first so we can keep the | |
506 // main and impl threads synchronized. Then skip an impl frame if it makes | |
507 // sense. This avoids skipping both at the same time to avoid strange | |
508 // interactions/oscillations since CanDrawBeforeDeadline() depends on | |
509 // whether the main thread is in a high latency mode or not. | |
501 if (!state_machine_.impl_latency_takes_priority() && | 510 if (!state_machine_.impl_latency_takes_priority() && |
502 main_thread_is_in_high_latency_mode && | 511 main_thread_is_in_high_latency_mode && |
503 CanCommitAndActivateBeforeDeadline()) { | 512 CanCommitAndActivateBeforeDeadline()) { |
504 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); | 513 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); |
514 } else if (CanDrawBeforeDeadline() && | |
515 state_machine_.swaps_are_likely_high_latency()) { | |
516 // Skip this BeginImplFrame by returning early. | |
517 state_machine_.DidSkipBeginImplFrameToReduceLatency(); | |
518 return; | |
505 } | 519 } |
506 | 520 |
507 BeginImplFrame(); | 521 BeginImplFrame(); |
508 | 522 |
509 // The deadline will be scheduled in ProcessScheduledActions. | 523 // The deadline will be scheduled in ProcessScheduledActions. |
510 state_machine_.OnBeginImplFrameDeadlinePending(); | 524 state_machine_.OnBeginImplFrameDeadlinePending(); |
511 ProcessScheduledActions(); | 525 ProcessScheduledActions(); |
512 } | 526 } |
513 | 527 |
514 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { | 528 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
806 bool Scheduler::CanCommitAndActivateBeforeDeadline() const { | 820 bool Scheduler::CanCommitAndActivateBeforeDeadline() const { |
807 // Check if the main thread computation and commit can be finished before the | 821 // Check if the main thread computation and commit can be finished before the |
808 // impl thread's deadline. | 822 // impl thread's deadline. |
809 base::TimeTicks estimated_draw_time = | 823 base::TimeTicks estimated_draw_time = |
810 begin_impl_frame_args_.frame_time + | 824 begin_impl_frame_args_.frame_time + |
811 client_->BeginMainFrameToCommitDurationEstimate() + | 825 client_->BeginMainFrameToCommitDurationEstimate() + |
812 client_->CommitToActivateDurationEstimate(); | 826 client_->CommitToActivateDurationEstimate(); |
813 | 827 |
814 TRACE_EVENT2( | 828 TRACE_EVENT2( |
815 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 829 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
816 "CanCommitAndActivateBeforeDeadline", | 830 "CanCommitAndActivateBeforeDeadline", "est_time_left_after_drawing_ms", |
817 "time_left_after_drawing_ms", | |
818 (begin_impl_frame_args_.deadline - estimated_draw_time).InMillisecondsF(), | 831 (begin_impl_frame_args_.deadline - estimated_draw_time).InMillisecondsF(), |
819 "state", | 832 "state", AsValue()); |
820 AsValue()); | |
821 | 833 |
822 return estimated_draw_time < begin_impl_frame_args_.deadline; | 834 return estimated_draw_time < begin_impl_frame_args_.deadline; |
823 } | 835 } |
824 | 836 |
837 bool Scheduler::CanDrawBeforeDeadline() const { | |
838 bool main_thread_is_in_high_latency_mode = | |
839 state_machine_.MainThreadIsInHighLatencyMode(); | |
840 | |
841 // Check if the main thread computation and commit can be finished before the | |
842 // impl thread's deadline. | |
843 base::TimeTicks estimated_draw_time = begin_impl_frame_args_.frame_time; | |
844 if (!main_thread_is_in_high_latency_mode) { | |
845 estimated_draw_time += client_->BeginMainFrameToCommitDurationEstimate() + | |
846 client_->CommitToActivateDurationEstimate(); | |
847 } | |
848 | |
849 base::TimeDelta time_left_after_drawing = | |
850 begin_impl_frame_args_.deadline - estimated_draw_time; | |
851 | |
852 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | |
853 "CanDrawBeforeDeadline", "time_left_after_drawing_ms", | |
854 time_left_after_drawing.InMillisecondsF(), "state", AsValue()); | |
855 | |
856 // Ideally we could use a threshold of 0, but our deadlines are currently | |
857 // just estimates, so we are extra careful not to skip frames if we aren't | |
858 // absolutely sure the Impl thread can run in a low latency mode. | |
859 // TODO(mithro): Replace this with SwapNack logic. | |
860 base::TimeDelta threshold = BeginFrameArgs::DefaultEstimatedParentDrawTime(); | |
861 | |
862 return time_left_after_drawing > threshold; | |
863 } | |
864 | |
825 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 865 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
826 return (state_machine_.commit_state() == | 866 return (state_machine_.commit_state() == |
827 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || | 867 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |
828 state_machine_.commit_state() == | 868 state_machine_.commit_state() == |
829 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); | 869 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); |
830 } | 870 } |
831 | 871 |
832 } // namespace cc | 872 } // namespace cc |
OLD | NEW |