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) { |
| 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 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 BeginImplFrameWithDeadline(adjusted_args); | 398 BeginImplFrameWithDeadline(adjusted_args); |
389 } | 399 } |
390 return true; | 400 return true; |
391 } | 401 } |
392 | 402 |
393 void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) { | 403 void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) { |
394 state_machine_.SetChildrenNeedBeginFrames(children_need_begin_frames); | 404 state_machine_.SetChildrenNeedBeginFrames(children_need_begin_frames); |
395 ProcessScheduledActions(); | 405 ProcessScheduledActions(); |
396 } | 406 } |
397 | 407 |
398 void Scheduler::SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) { | |
399 authoritative_vsync_interval_ = interval; | |
400 if (vsync_observer_) | |
401 vsync_observer_->OnUpdateVSyncParameters(last_vsync_timebase_, interval); | |
402 } | |
403 | |
404 void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) { | 408 void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) { |
405 state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames); | 409 state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames); |
406 ProcessScheduledActions(); | 410 ProcessScheduledActions(); |
407 } | 411 } |
408 | 412 |
409 void Scheduler::OnDrawForOutputSurface() { | 413 void Scheduler::OnDrawForOutputSurface() { |
410 DCHECK(settings_.using_synchronous_renderer_compositor); | 414 DCHECK(settings_.using_synchronous_renderer_compositor); |
411 DCHECK_EQ(state_machine_.begin_impl_frame_state(), | 415 DCHECK_EQ(state_machine_.begin_impl_frame_state(), |
412 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 416 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
413 DCHECK(!BeginImplFrameDeadlinePending()); | 417 DCHECK(!BeginImplFrameDeadlinePending()); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 args.AsValue(), "main_thread_is_high_latency", | 503 args.AsValue(), "main_thread_is_high_latency", |
500 main_thread_is_in_high_latency_mode); | 504 main_thread_is_in_high_latency_mode); |
501 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 505 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
502 "MainThreadLatency", main_thread_is_in_high_latency_mode); | 506 "MainThreadLatency", main_thread_is_in_high_latency_mode); |
503 | 507 |
504 advance_commit_state_task_.Cancel(); | 508 advance_commit_state_task_.Cancel(); |
505 | 509 |
506 begin_impl_frame_args_ = args; | 510 begin_impl_frame_args_ = args; |
507 begin_impl_frame_args_.deadline -= client_->DrawDurationEstimate(); | 511 begin_impl_frame_args_.deadline -= client_->DrawDurationEstimate(); |
508 | 512 |
| 513 // Prioritize skipping the main thread's latency first so we can keep the |
| 514 // main and impl threads synchronized. Then skip an impl frame if it makes |
| 515 // sense. This avoids skipping both at the same time to avoid strange |
| 516 // interactions/oscillations since CanDrawBeforeDeadline() depends on |
| 517 // whether the main thread is in a high latency mode or not. |
509 if (!state_machine_.impl_latency_takes_priority() && | 518 if (!state_machine_.impl_latency_takes_priority() && |
510 main_thread_is_in_high_latency_mode && | 519 main_thread_is_in_high_latency_mode && |
511 CanCommitAndActivateBeforeDeadline()) { | 520 CanCommitAndActivateBeforeDeadline()) { |
512 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); | 521 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); |
| 522 } else if (CanDrawBeforeDeadline() && |
| 523 state_machine_.last_swap_ack_came_after_begin_impl_frame()) { |
| 524 // Skip this BeginImplFrame by returning early. |
| 525 state_machine_.DidSkipBeginImplFrameToReduceLatency(); |
| 526 return; |
513 } | 527 } |
514 | 528 |
515 BeginImplFrame(); | 529 BeginImplFrame(); |
516 | 530 |
517 // The deadline will be scheduled in ProcessScheduledActions. | 531 // The deadline will be scheduled in ProcessScheduledActions. |
518 state_machine_.OnBeginImplFrameDeadlinePending(); | 532 state_machine_.OnBeginImplFrameDeadlinePending(); |
519 ProcessScheduledActions(); | 533 ProcessScheduledActions(); |
520 } | 534 } |
521 | 535 |
522 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { | 536 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
814 bool Scheduler::CanCommitAndActivateBeforeDeadline() const { | 828 bool Scheduler::CanCommitAndActivateBeforeDeadline() const { |
815 // Check if the main thread computation and commit can be finished before the | 829 // Check if the main thread computation and commit can be finished before the |
816 // impl thread's deadline. | 830 // impl thread's deadline. |
817 base::TimeTicks estimated_draw_time = | 831 base::TimeTicks estimated_draw_time = |
818 begin_impl_frame_args_.frame_time + | 832 begin_impl_frame_args_.frame_time + |
819 client_->BeginMainFrameToCommitDurationEstimate() + | 833 client_->BeginMainFrameToCommitDurationEstimate() + |
820 client_->CommitToActivateDurationEstimate(); | 834 client_->CommitToActivateDurationEstimate(); |
821 | 835 |
822 TRACE_EVENT2( | 836 TRACE_EVENT2( |
823 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 837 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
824 "CanCommitAndActivateBeforeDeadline", | 838 "CanCommitAndActivateBeforeDeadline", "est_time_left_after_drawing_ms", |
825 "time_left_after_drawing_ms", | |
826 (begin_impl_frame_args_.deadline - estimated_draw_time).InMillisecondsF(), | 839 (begin_impl_frame_args_.deadline - estimated_draw_time).InMillisecondsF(), |
827 "state", | 840 "state", AsValue()); |
828 AsValue()); | |
829 | 841 |
830 return estimated_draw_time < begin_impl_frame_args_.deadline; | 842 return estimated_draw_time < begin_impl_frame_args_.deadline; |
831 } | 843 } |
832 | 844 |
| 845 bool Scheduler::CanDrawBeforeDeadline() const { |
| 846 bool main_thread_is_in_high_latency_mode = |
| 847 state_machine_.MainThreadIsInHighLatencyMode(); |
| 848 |
| 849 // Check if the main thread computation and commit can be finished before the |
| 850 // impl thread's deadline. |
| 851 base::TimeTicks estimated_draw_time = begin_impl_frame_args_.frame_time; |
| 852 if (!main_thread_is_in_high_latency_mode) { |
| 853 estimated_draw_time += client_->BeginMainFrameToCommitDurationEstimate() + |
| 854 client_->CommitToActivateDurationEstimate(); |
| 855 } |
| 856 |
| 857 base::TimeDelta time_left_after_drawing = |
| 858 begin_impl_frame_args_.deadline - estimated_draw_time; |
| 859 |
| 860 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
| 861 "CanDrawBeforeDeadline", "time_left_after_drawing_ms", |
| 862 time_left_after_drawing.InMillisecondsF(), "state", AsValue()); |
| 863 |
| 864 // Ideally we could use a threshold of 0, but our deadlines are currently |
| 865 // just estimates, so we are extra careful not to skip frames if we aren't |
| 866 // absolutely sure the Impl thread can run in a low latency mode. |
| 867 // TODO(mithro): Replace this with SwapNack logic. |
| 868 base::TimeDelta threshold = BeginFrameArgs::DefaultEstimatedParentDrawTime(); |
| 869 |
| 870 return time_left_after_drawing > threshold; |
| 871 } |
| 872 |
833 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 873 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
834 return (state_machine_.commit_state() == | 874 return (state_machine_.commit_state() == |
835 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || | 875 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |
836 state_machine_.commit_state() == | 876 state_machine_.commit_state() == |
837 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); | 877 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); |
838 } | 878 } |
839 | 879 |
840 } // namespace cc | 880 } // namespace cc |
OLD | NEW |