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 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
9 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
10 #include "base/debug/trace_event_argument.h" | 11 #include "base/debug/trace_event_argument.h" |
11 #include "base/logging.h" | 12 #include "base/logging.h" |
12 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
13 #include "cc/debug/devtools_instrumentation.h" | 14 #include "cc/debug/devtools_instrumentation.h" |
14 #include "cc/debug/traced_value.h" | 15 #include "cc/debug/traced_value.h" |
15 #include "cc/scheduler/delay_based_time_source.h" | 16 #include "cc/scheduler/delay_based_time_source.h" |
16 #include "ui/gfx/frame_time.h" | 17 #include "ui/gfx/frame_time.h" |
17 | 18 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
78 Scheduler::Scheduler( | 79 Scheduler::Scheduler( |
79 SchedulerClient* client, | 80 SchedulerClient* client, |
80 const SchedulerSettings& scheduler_settings, | 81 const SchedulerSettings& scheduler_settings, |
81 int layer_tree_host_id, | 82 int layer_tree_host_id, |
82 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) | 83 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) |
83 : settings_(scheduler_settings), | 84 : settings_(scheduler_settings), |
84 client_(client), | 85 client_(client), |
85 layer_tree_host_id_(layer_tree_host_id), | 86 layer_tree_host_id_(layer_tree_host_id), |
86 task_runner_(task_runner), | 87 task_runner_(task_runner), |
87 vsync_interval_(BeginFrameArgs::DefaultInterval()), | 88 vsync_interval_(BeginFrameArgs::DefaultInterval()), |
89 authoritative_vsync_interval_(base::TimeDelta()), | |
88 last_set_needs_begin_frame_(false), | 90 last_set_needs_begin_frame_(false), |
89 begin_unthrottled_frame_posted_(false), | 91 begin_unthrottled_frame_posted_(false), |
90 begin_retro_frame_posted_(false), | 92 begin_retro_frame_posted_(false), |
91 state_machine_(scheduler_settings), | 93 state_machine_(scheduler_settings), |
92 inside_process_scheduled_actions_(false), | 94 inside_process_scheduled_actions_(false), |
93 inside_action_(SchedulerStateMachine::ACTION_NONE), | 95 inside_action_(SchedulerStateMachine::ACTION_NONE), |
94 weak_factory_(this) { | 96 weak_factory_(this) { |
95 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 97 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
96 "Scheduler::Scheduler", | 98 "Scheduler::Scheduler", |
97 "settings", | 99 "settings", |
98 settings_.AsValue()); | 100 settings_.AsValue()); |
99 DCHECK(client_); | 101 DCHECK(client_); |
100 DCHECK(!state_machine_.BeginFrameNeeded()); | 102 DCHECK(!state_machine_.BeginFrameNeeded()); |
101 if (settings_.main_frame_before_activation_enabled) { | 103 if (settings_.main_frame_before_activation_enabled) { |
102 DCHECK(settings_.main_frame_before_draw_enabled); | 104 DCHECK(settings_.main_frame_before_draw_enabled); |
103 } | 105 } |
104 | |
105 begin_retro_frame_closure_ = | 106 begin_retro_frame_closure_ = |
106 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); | 107 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); |
107 begin_unthrottled_frame_closure_ = | 108 begin_unthrottled_frame_closure_ = |
108 base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr()); | 109 base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr()); |
109 begin_impl_frame_deadline_closure_ = base::Bind( | 110 begin_impl_frame_deadline_closure_ = base::Bind( |
110 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); | 111 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); |
111 poll_for_draw_triggers_closure_ = base::Bind( | 112 poll_for_draw_triggers_closure_ = base::Bind( |
112 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); | 113 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); |
113 advance_commit_state_closure_ = base::Bind( | 114 advance_commit_state_closure_ = base::Bind( |
114 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); | 115 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); |
115 | 116 |
116 if (!settings_.begin_frame_scheduling_enabled) { | 117 if (!settings_.begin_frame_receiver) |
117 SetupSyntheticBeginFrames(); | 118 SetupSyntheticBeginFrames(); |
118 } | |
119 } | 119 } |
120 | 120 |
121 Scheduler::~Scheduler() { | 121 Scheduler::~Scheduler() { |
122 if (synthetic_begin_frame_source_) { | 122 if (synthetic_begin_frame_source_) { |
123 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, | 123 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, |
124 &begin_retro_frame_args_); | 124 &begin_retro_frame_args_); |
125 } | 125 } |
126 } | 126 } |
127 | 127 |
128 void Scheduler::SetupSyntheticBeginFrames() { | 128 void Scheduler::SetupSyntheticBeginFrames() { |
129 DCHECK(!synthetic_begin_frame_source_); | 129 DCHECK(!synthetic_begin_frame_source_); |
130 synthetic_begin_frame_source_.reset( | 130 synthetic_begin_frame_source_.reset( |
131 new SyntheticBeginFrameSource(this, task_runner_.get())); | 131 new SyntheticBeginFrameSource(this, task_runner_.get())); |
132 } | 132 } |
133 | 133 |
134 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, | 134 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, |
135 base::TimeDelta interval) { | 135 base::TimeDelta interval) { |
136 // TODO(brianderson): We should not be receiving 0 intervals. | 136 if (authoritative_vsync_interval_ == base::TimeDelta()) { |
brianderson
2014/09/04 18:45:46
nit: I was imagining a form that doesn't require n
| |
137 if (interval == base::TimeDelta()) | 137 // TODO(brianderson): We should not be receiving 0 intervals. |
138 interval = BeginFrameArgs::DefaultInterval(); | 138 if (interval == base::TimeDelta()) |
139 vsync_interval_ = interval; | 139 interval = BeginFrameArgs::DefaultInterval(); |
140 if (!settings_.begin_frame_scheduling_enabled) | 140 vsync_interval_ = interval; |
141 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval); | 141 } else { |
142 vsync_interval_ = authoritative_vsync_interval_; | |
143 } | |
144 | |
145 last_timebase_ = timebase; | |
146 | |
147 if (!settings_.begin_frame_receiver) { | |
148 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, | |
149 vsync_interval_); | |
150 } | |
142 } | 151 } |
143 | 152 |
144 void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { | 153 void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { |
145 DCHECK_GE(draw_time.ToInternalValue(), 0); | 154 DCHECK_GE(draw_time.ToInternalValue(), 0); |
146 estimated_parent_draw_time_ = draw_time; | 155 estimated_parent_draw_time_ = draw_time; |
147 } | 156 } |
148 | 157 |
149 void Scheduler::SetCanStart() { | 158 void Scheduler::SetCanStart() { |
150 state_machine_.SetCanStart(); | 159 state_machine_.SetCanStart(); |
151 ProcessScheduledActions(); | 160 ProcessScheduledActions(); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
229 } | 238 } |
230 | 239 |
231 void Scheduler::DidManageTiles() { | 240 void Scheduler::DidManageTiles() { |
232 state_machine_.DidManageTiles(); | 241 state_machine_.DidManageTiles(); |
233 } | 242 } |
234 | 243 |
235 void Scheduler::DidLoseOutputSurface() { | 244 void Scheduler::DidLoseOutputSurface() { |
236 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); | 245 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); |
237 state_machine_.DidLoseOutputSurface(); | 246 state_machine_.DidLoseOutputSurface(); |
238 last_set_needs_begin_frame_ = false; | 247 last_set_needs_begin_frame_ = false; |
239 if (!settings_.begin_frame_scheduling_enabled) { | 248 if (!settings_.begin_frame_receiver) { |
240 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, | 249 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, |
241 &begin_retro_frame_args_); | 250 &begin_retro_frame_args_); |
242 } | 251 } |
243 begin_retro_frame_args_.clear(); | 252 begin_retro_frame_args_.clear(); |
244 ProcessScheduledActions(); | 253 ProcessScheduledActions(); |
245 } | 254 } |
246 | 255 |
247 void Scheduler::DidCreateAndInitializeOutputSurface() { | 256 void Scheduler::DidCreateAndInitializeOutputSurface() { |
248 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); | 257 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); |
249 DCHECK(!last_set_needs_begin_frame_); | 258 DCHECK(!last_set_needs_begin_frame_); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
295 state_machine_.begin_impl_frame_state() == | 304 state_machine_.begin_impl_frame_state() == |
296 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; | 305 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; |
297 | 306 |
298 bool should_call_set_needs_begin_frame = | 307 bool should_call_set_needs_begin_frame = |
299 // Always request the BeginFrame immediately if it wasn't needed before. | 308 // Always request the BeginFrame immediately if it wasn't needed before. |
300 (needs_begin_frame && !last_set_needs_begin_frame_) || | 309 (needs_begin_frame && !last_set_needs_begin_frame_) || |
301 // Only stop requesting BeginFrames after a deadline. | 310 // Only stop requesting BeginFrames after a deadline. |
302 (!needs_begin_frame && last_set_needs_begin_frame_ && at_end_of_deadline); | 311 (!needs_begin_frame && last_set_needs_begin_frame_ && at_end_of_deadline); |
303 | 312 |
304 if (should_call_set_needs_begin_frame) { | 313 if (should_call_set_needs_begin_frame) { |
305 if (settings_.begin_frame_scheduling_enabled) { | 314 if (settings_.begin_frame_receiver) { |
306 client_->SetNeedsBeginFrame(needs_begin_frame); | 315 client_->SetNeedsBeginFrame(needs_begin_frame); |
307 } else { | 316 } else { |
308 synthetic_begin_frame_source_->SetNeedsBeginFrame( | 317 synthetic_begin_frame_source_->SetNeedsBeginFrame( |
309 needs_begin_frame, &begin_retro_frame_args_); | 318 needs_begin_frame, &begin_retro_frame_args_); |
310 } | 319 } |
311 last_set_needs_begin_frame_ = needs_begin_frame; | 320 last_set_needs_begin_frame_ = needs_begin_frame; |
312 } | 321 } |
313 | 322 |
314 PostBeginRetroFrameIfNeeded(); | 323 PostBeginRetroFrameIfNeeded(); |
315 } | 324 } |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
401 | 410 |
402 // BeginFrame is the mechanism that tells us that now is a good time to start | 411 // BeginFrame is the mechanism that tells us that now is a good time to start |
403 // making a frame. Usually this means that user input for the frame is complete. | 412 // making a frame. Usually this means that user input for the frame is complete. |
404 // If the scheduler is busy, we queue the BeginFrame to be handled later as | 413 // If the scheduler is busy, we queue the BeginFrame to be handled later as |
405 // a BeginRetroFrame. | 414 // a BeginRetroFrame. |
406 void Scheduler::BeginFrame(const BeginFrameArgs& args) { | 415 void Scheduler::BeginFrame(const BeginFrameArgs& args) { |
407 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue()); | 416 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue()); |
408 DCHECK(settings_.throttle_frame_production); | 417 DCHECK(settings_.throttle_frame_production); |
409 | 418 |
410 BeginFrameArgs adjusted_args(args); | 419 BeginFrameArgs adjusted_args(args); |
420 | |
421 if (settings_.begin_frame_publisher && | |
422 state_machine_.children_need_begin_frames()) { | |
423 // Adjust a dealine for child schedulers. | |
424 // TODO(simonhong): Once we have commitless update, we can get rid of | |
425 // BeginMainFrameToCommitDurationEstimate() + | |
426 // CommitToActivateDurationEstimate(). | |
427 adjusted_args.deadline -= | |
428 (client_->BeginMainFrameToCommitDurationEstimate() + | |
429 client_->CommitToActivateDurationEstimate() + | |
430 client_->DrawDurationEstimate() + | |
431 EstimatedParentDrawTime()); | |
432 client_->SendBeginFrameToChildren(args); | |
brianderson
2014/09/04 18:45:46
You need to send the adjusted_args rather than the
| |
433 } | |
434 | |
411 adjusted_args.deadline -= EstimatedParentDrawTime(); | 435 adjusted_args.deadline -= EstimatedParentDrawTime(); |
brianderson
2014/09/04 18:45:46
We'll want two different adjusted_args: one for th
| |
412 | 436 |
413 bool should_defer_begin_frame; | 437 bool should_defer_begin_frame; |
414 if (settings_.using_synchronous_renderer_compositor) { | 438 if (settings_.using_synchronous_renderer_compositor) { |
415 should_defer_begin_frame = false; | 439 should_defer_begin_frame = false; |
416 } else { | 440 } else { |
417 should_defer_begin_frame = | 441 should_defer_begin_frame = |
418 !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ || | 442 !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ || |
419 !last_set_needs_begin_frame_ || | 443 !last_set_needs_begin_frame_ || |
420 (state_machine_.begin_impl_frame_state() != | 444 (state_machine_.begin_impl_frame_state() != |
421 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 445 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
605 TRACE_EVENT0("cc", "Scheduler::PollToAdvanceCommitState"); | 629 TRACE_EVENT0("cc", "Scheduler::PollToAdvanceCommitState"); |
606 advance_commit_state_task_.Cancel(); | 630 advance_commit_state_task_.Cancel(); |
607 ProcessScheduledActions(); | 631 ProcessScheduledActions(); |
608 } | 632 } |
609 | 633 |
610 bool Scheduler::IsBeginMainFrameSent() const { | 634 bool Scheduler::IsBeginMainFrameSent() const { |
611 return state_machine_.commit_state() == | 635 return state_machine_.commit_state() == |
612 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT; | 636 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT; |
613 } | 637 } |
614 | 638 |
639 void Scheduler::SetChildrenNeedBeginFrames(bool need_begin_frame) { | |
640 DCHECK(settings_.begin_frame_publisher); | |
641 | |
642 state_machine_.SetChildrenNeedBeginFrames(need_begin_frame); | |
643 ProcessScheduledActions(); | |
644 } | |
645 | |
646 void Scheduler::SetAuthoritativeVSyncInterval(base::TimeDelta interval) { | |
647 authoritative_vsync_interval_ = interval; | |
648 vsync_interval_ = interval; | |
649 | |
650 if (!settings_.begin_frame_receiver) { | |
651 synthetic_begin_frame_source_->CommitVSyncParameters(last_timebase_, | |
652 interval); | |
653 } | |
654 } | |
655 | |
615 void Scheduler::DrawAndSwapIfPossible() { | 656 void Scheduler::DrawAndSwapIfPossible() { |
616 DrawResult result = client_->ScheduledActionDrawAndSwapIfPossible(); | 657 DrawResult result = client_->ScheduledActionDrawAndSwapIfPossible(); |
617 state_machine_.DidDrawIfPossibleCompleted(result); | 658 state_machine_.DidDrawIfPossibleCompleted(result); |
618 } | 659 } |
619 | 660 |
620 void Scheduler::ProcessScheduledActions() { | 661 void Scheduler::ProcessScheduledActions() { |
621 // We do not allow ProcessScheduledActions to be recursive. | 662 // We do not allow ProcessScheduledActions to be recursive. |
622 // The top-level call will iteratively execute the next action for us anyway. | 663 // The top-level call will iteratively execute the next action for us anyway. |
623 if (inside_process_scheduled_actions_) | 664 if (inside_process_scheduled_actions_) |
624 return; | 665 return; |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
755 } | 796 } |
756 | 797 |
757 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 798 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
758 return (state_machine_.commit_state() == | 799 return (state_machine_.commit_state() == |
759 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || | 800 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |
760 state_machine_.commit_state() == | 801 state_machine_.commit_state() == |
761 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); | 802 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); |
762 } | 803 } |
763 | 804 |
764 } // namespace cc | 805 } // namespace cc |
OLD | NEW |