Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(782)

Side by Side Diff: cc/scheduler/scheduler.cc

Issue 1133673004: cc: Heuristic for Renderer latency recovery (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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;
sunnyps 2015/05/12 00:36:25 BeginFrameSource::DidFinishFrame needs to be calle
brianderson 2015/05/12 19:25:17 Ah, good catch! I should make sure this logic int
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
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) {
sunnyps 2015/05/12 00:36:25 This should depend on if we care about main thread
brianderson 2015/05/12 19:25:17 main_thread_is_in_high_latency_mode will become tr
brianderson 2015/05/12 22:19:00 Actually, I think I do need to look into impl_late
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();
sunnyps 2015/05/12 00:36:25 begin_impl_frame_args_.deadline already has the pa
brianderson 2015/05/12 19:25:17 I should probably rename CanDrawBeforeDeadline to
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698