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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 Scheduler::Scheduler( | 72 Scheduler::Scheduler( |
72 SchedulerClient* client, | 73 SchedulerClient* client, |
73 const SchedulerSettings& scheduler_settings, | 74 const SchedulerSettings& scheduler_settings, |
74 int layer_tree_host_id, | 75 int layer_tree_host_id, |
75 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) | 76 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) |
76 : settings_(scheduler_settings), | 77 : settings_(scheduler_settings), |
77 client_(client), | 78 client_(client), |
78 layer_tree_host_id_(layer_tree_host_id), | 79 layer_tree_host_id_(layer_tree_host_id), |
79 task_runner_(task_runner), | 80 task_runner_(task_runner), |
80 vsync_interval_(BeginFrameArgs::DefaultInterval()), | 81 vsync_interval_(BeginFrameArgs::DefaultInterval()), |
| 82 authoritative_vsync_interval_(base::TimeDelta()), |
81 last_set_needs_begin_frame_(false), | 83 last_set_needs_begin_frame_(false), |
82 begin_unthrottled_frame_posted_(false), | 84 begin_unthrottled_frame_posted_(false), |
83 begin_retro_frame_posted_(false), | 85 begin_retro_frame_posted_(false), |
84 state_machine_(scheduler_settings), | 86 state_machine_(scheduler_settings), |
85 inside_process_scheduled_actions_(false), | 87 inside_process_scheduled_actions_(false), |
86 inside_action_(SchedulerStateMachine::ACTION_NONE), | 88 inside_action_(SchedulerStateMachine::ACTION_NONE), |
87 weak_factory_(this) { | 89 weak_factory_(this) { |
88 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 90 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
89 "Scheduler::Scheduler", | 91 "Scheduler::Scheduler", |
90 "settings", | 92 "settings", |
91 settings_.AsValue()); | 93 settings_.AsValue()); |
92 DCHECK(client_); | 94 DCHECK(client_); |
93 DCHECK(!state_machine_.BeginFrameNeeded()); | 95 DCHECK(!state_machine_.BeginFrameNeeded()); |
94 if (settings_.main_frame_before_activation_enabled) { | 96 if (settings_.main_frame_before_activation_enabled) { |
95 DCHECK(settings_.main_frame_before_draw_enabled); | 97 DCHECK(settings_.main_frame_before_draw_enabled); |
96 } | 98 } |
97 | |
98 begin_retro_frame_closure_ = | 99 begin_retro_frame_closure_ = |
99 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); | 100 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); |
100 begin_unthrottled_frame_closure_ = | 101 begin_unthrottled_frame_closure_ = |
101 base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr()); | 102 base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr()); |
102 begin_impl_frame_deadline_closure_ = base::Bind( | 103 begin_impl_frame_deadline_closure_ = base::Bind( |
103 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); | 104 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); |
104 poll_for_draw_triggers_closure_ = base::Bind( | 105 poll_for_draw_triggers_closure_ = base::Bind( |
105 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); | 106 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); |
106 advance_commit_state_closure_ = base::Bind( | 107 advance_commit_state_closure_ = base::Bind( |
107 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); | 108 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); |
108 | 109 |
109 if (!settings_.begin_frame_scheduling_enabled) { | 110 if (!settings_.begin_frame_receiver) |
110 SetupSyntheticBeginFrames(); | 111 SetupSyntheticBeginFrames(); |
111 } | |
112 } | 112 } |
113 | 113 |
114 Scheduler::~Scheduler() { | 114 Scheduler::~Scheduler() { |
115 if (synthetic_begin_frame_source_) { | 115 if (synthetic_begin_frame_source_) { |
116 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, | 116 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, |
117 &begin_retro_frame_args_); | 117 &begin_retro_frame_args_); |
118 } | 118 } |
119 } | 119 } |
120 | 120 |
121 void Scheduler::SetupSyntheticBeginFrames() { | 121 void Scheduler::SetupSyntheticBeginFrames() { |
122 scoped_refptr<DelayBasedTimeSource> time_source; | 122 scoped_refptr<DelayBasedTimeSource> time_source; |
123 if (gfx::FrameTime::TimestampsAreHighRes()) { | 123 if (gfx::FrameTime::TimestampsAreHighRes()) { |
124 time_source = DelayBasedTimeSourceHighRes::Create(VSyncInterval(), | 124 time_source = DelayBasedTimeSourceHighRes::Create(VSyncInterval(), |
125 task_runner_.get()); | 125 task_runner_.get()); |
126 } else { | 126 } else { |
127 time_source = | 127 time_source = |
128 DelayBasedTimeSource::Create(VSyncInterval(), task_runner_.get()); | 128 DelayBasedTimeSource::Create(VSyncInterval(), task_runner_.get()); |
129 } | 129 } |
130 DCHECK(!synthetic_begin_frame_source_); | 130 DCHECK(!synthetic_begin_frame_source_); |
131 synthetic_begin_frame_source_.reset( | 131 synthetic_begin_frame_source_.reset( |
132 new SyntheticBeginFrameSource(this, time_source)); | 132 new SyntheticBeginFrameSource(this, time_source)); |
133 } | 133 } |
134 | 134 |
135 base::TimeTicks Scheduler::Now() const { | 135 base::TimeTicks Scheduler::Now() const { |
136 return gfx::FrameTime::Now(); | 136 return gfx::FrameTime::Now(); |
137 } | 137 } |
138 | 138 |
139 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, | 139 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, |
140 base::TimeDelta interval) { | 140 base::TimeDelta interval) { |
141 // TODO(brianderson): We should not be receiving 0 intervals. | 141 if (authoritative_vsync_interval_ == base::TimeDelta()) { |
142 if (interval == base::TimeDelta()) | 142 // TODO(brianderson): We should not be receiving 0 intervals. |
143 interval = BeginFrameArgs::DefaultInterval(); | 143 if (interval == base::TimeDelta()) |
144 vsync_interval_ = interval; | 144 interval = BeginFrameArgs::DefaultInterval(); |
145 if (!settings_.begin_frame_scheduling_enabled) | 145 vsync_interval_ = interval; |
146 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval); | 146 } else { |
| 147 vsync_interval_ = authoritative_vsync_interval_; |
| 148 } |
| 149 |
| 150 last_timebase_ = timebase; |
| 151 |
| 152 if (!settings_.begin_frame_receiver) { |
| 153 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, |
| 154 vsync_interval_); |
| 155 } |
147 } | 156 } |
148 | 157 |
149 void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { | 158 void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { |
150 DCHECK_GE(draw_time.ToInternalValue(), 0); | 159 DCHECK_GE(draw_time.ToInternalValue(), 0); |
151 estimated_parent_draw_time_ = draw_time; | 160 estimated_parent_draw_time_ = draw_time; |
152 } | 161 } |
153 | 162 |
154 void Scheduler::SetCanStart() { | 163 void Scheduler::SetCanStart() { |
155 state_machine_.SetCanStart(); | 164 state_machine_.SetCanStart(); |
156 ProcessScheduledActions(); | 165 ProcessScheduledActions(); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 } | 243 } |
235 | 244 |
236 void Scheduler::DidManageTiles() { | 245 void Scheduler::DidManageTiles() { |
237 state_machine_.DidManageTiles(); | 246 state_machine_.DidManageTiles(); |
238 } | 247 } |
239 | 248 |
240 void Scheduler::DidLoseOutputSurface() { | 249 void Scheduler::DidLoseOutputSurface() { |
241 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); | 250 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); |
242 state_machine_.DidLoseOutputSurface(); | 251 state_machine_.DidLoseOutputSurface(); |
243 last_set_needs_begin_frame_ = false; | 252 last_set_needs_begin_frame_ = false; |
244 if (!settings_.begin_frame_scheduling_enabled) { | 253 if (!settings_.begin_frame_receiver) { |
245 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, | 254 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, |
246 &begin_retro_frame_args_); | 255 &begin_retro_frame_args_); |
247 } | 256 } |
248 begin_retro_frame_args_.clear(); | 257 begin_retro_frame_args_.clear(); |
249 ProcessScheduledActions(); | 258 ProcessScheduledActions(); |
250 } | 259 } |
251 | 260 |
252 void Scheduler::DidCreateAndInitializeOutputSurface() { | 261 void Scheduler::DidCreateAndInitializeOutputSurface() { |
253 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); | 262 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); |
254 DCHECK(!last_set_needs_begin_frame_); | 263 DCHECK(!last_set_needs_begin_frame_); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 state_machine_.begin_impl_frame_state() == | 309 state_machine_.begin_impl_frame_state() == |
301 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; | 310 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; |
302 | 311 |
303 bool should_call_set_needs_begin_frame = | 312 bool should_call_set_needs_begin_frame = |
304 // Always request the BeginFrame immediately if it wasn't needed before. | 313 // Always request the BeginFrame immediately if it wasn't needed before. |
305 (needs_begin_frame && !last_set_needs_begin_frame_) || | 314 (needs_begin_frame && !last_set_needs_begin_frame_) || |
306 // Only stop requesting BeginFrames after a deadline. | 315 // Only stop requesting BeginFrames after a deadline. |
307 (!needs_begin_frame && last_set_needs_begin_frame_ && at_end_of_deadline); | 316 (!needs_begin_frame && last_set_needs_begin_frame_ && at_end_of_deadline); |
308 | 317 |
309 if (should_call_set_needs_begin_frame) { | 318 if (should_call_set_needs_begin_frame) { |
310 if (settings_.begin_frame_scheduling_enabled) { | 319 if (settings_.begin_frame_receiver) { |
311 client_->SetNeedsBeginFrame(needs_begin_frame); | 320 client_->SetNeedsBeginFrame(needs_begin_frame); |
312 } else { | 321 } else { |
313 synthetic_begin_frame_source_->SetNeedsBeginFrame( | 322 synthetic_begin_frame_source_->SetNeedsBeginFrame( |
314 needs_begin_frame, &begin_retro_frame_args_); | 323 needs_begin_frame, &begin_retro_frame_args_); |
315 } | 324 } |
316 last_set_needs_begin_frame_ = needs_begin_frame; | 325 last_set_needs_begin_frame_ = needs_begin_frame; |
317 } | 326 } |
318 | 327 |
319 PostBeginRetroFrameIfNeeded(); | 328 PostBeginRetroFrameIfNeeded(); |
320 } | 329 } |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 | 415 |
407 // BeginFrame is the mechanism that tells us that now is a good time to start | 416 // BeginFrame is the mechanism that tells us that now is a good time to start |
408 // making a frame. Usually this means that user input for the frame is complete. | 417 // making a frame. Usually this means that user input for the frame is complete. |
409 // If the scheduler is busy, we queue the BeginFrame to be handled later as | 418 // If the scheduler is busy, we queue the BeginFrame to be handled later as |
410 // a BeginRetroFrame. | 419 // a BeginRetroFrame. |
411 void Scheduler::BeginFrame(const BeginFrameArgs& args) { | 420 void Scheduler::BeginFrame(const BeginFrameArgs& args) { |
412 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue()); | 421 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue()); |
413 DCHECK(settings_.throttle_frame_production); | 422 DCHECK(settings_.throttle_frame_production); |
414 | 423 |
415 BeginFrameArgs adjusted_args(args); | 424 BeginFrameArgs adjusted_args(args); |
| 425 |
| 426 if (settings_.begin_frame_publisher && |
| 427 state_machine_.children_need_begin_frames()) { |
| 428 // Adjust a dealine for child schedulers. |
| 429 // TODO(simonhong): Once we have commitless update, we can get rid of |
| 430 // BeginMainFrameToCommitDurationEstimate() + |
| 431 // CommitToActivateDurationEstimate(). |
| 432 adjusted_args.deadline -= |
| 433 (client_->BeginMainFrameToCommitDurationEstimate() + |
| 434 client_->CommitToActivateDurationEstimate() + |
| 435 client_->DrawDurationEstimate() + EstimatedParentDrawTime()); |
| 436 client_->SendBeginFrameToChildren(args); |
| 437 } |
| 438 |
416 adjusted_args.deadline -= EstimatedParentDrawTime(); | 439 adjusted_args.deadline -= EstimatedParentDrawTime(); |
417 | 440 |
418 bool should_defer_begin_frame; | 441 bool should_defer_begin_frame; |
419 if (settings_.using_synchronous_renderer_compositor) { | 442 if (settings_.using_synchronous_renderer_compositor) { |
420 should_defer_begin_frame = false; | 443 should_defer_begin_frame = false; |
421 } else { | 444 } else { |
422 should_defer_begin_frame = | 445 should_defer_begin_frame = |
423 !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ || | 446 !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ || |
424 !last_set_needs_begin_frame_ || | 447 !last_set_needs_begin_frame_ || |
425 (state_machine_.begin_impl_frame_state() != | 448 (state_machine_.begin_impl_frame_state() != |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 ProcessScheduledActions(); | 640 ProcessScheduledActions(); |
618 state_machine_.DidLeavePollForAnticipatedDrawTriggers(); | 641 state_machine_.DidLeavePollForAnticipatedDrawTriggers(); |
619 } | 642 } |
620 | 643 |
621 void Scheduler::PollToAdvanceCommitState() { | 644 void Scheduler::PollToAdvanceCommitState() { |
622 TRACE_EVENT0("cc", "Scheduler::PollToAdvanceCommitState"); | 645 TRACE_EVENT0("cc", "Scheduler::PollToAdvanceCommitState"); |
623 advance_commit_state_task_.Cancel(); | 646 advance_commit_state_task_.Cancel(); |
624 ProcessScheduledActions(); | 647 ProcessScheduledActions(); |
625 } | 648 } |
626 | 649 |
| 650 void Scheduler::SetChildrenNeedBeginFrames(bool need_begin_frame) { |
| 651 DCHECK(settings_.begin_frame_publisher); |
| 652 |
| 653 state_machine_.SetChildrenNeedBeginFrames(need_begin_frame); |
| 654 ProcessScheduledActions(); |
| 655 } |
| 656 |
| 657 void Scheduler::SetAuthoritativeVSyncInterval(base::TimeDelta interval) { |
| 658 authoritative_vsync_interval_ = interval; |
| 659 vsync_interval_ = interval; |
| 660 |
| 661 if (!settings_.begin_frame_receiver) { |
| 662 synthetic_begin_frame_source_->CommitVSyncParameters(last_timebase_, |
| 663 interval); |
| 664 } |
| 665 } |
| 666 |
627 void Scheduler::DrawAndSwapIfPossible() { | 667 void Scheduler::DrawAndSwapIfPossible() { |
628 DrawResult result = client_->ScheduledActionDrawAndSwapIfPossible(); | 668 DrawResult result = client_->ScheduledActionDrawAndSwapIfPossible(); |
629 state_machine_.DidDrawIfPossibleCompleted(result); | 669 state_machine_.DidDrawIfPossibleCompleted(result); |
630 } | 670 } |
631 | 671 |
632 void Scheduler::ProcessScheduledActions() { | 672 void Scheduler::ProcessScheduledActions() { |
633 // We do not allow ProcessScheduledActions to be recursive. | 673 // We do not allow ProcessScheduledActions to be recursive. |
634 // The top-level call will iteratively execute the next action for us anyway. | 674 // The top-level call will iteratively execute the next action for us anyway. |
635 if (inside_process_scheduled_actions_) | 675 if (inside_process_scheduled_actions_) |
636 return; | 676 return; |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 } | 813 } |
774 | 814 |
775 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 815 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
776 return (state_machine_.commit_state() == | 816 return (state_machine_.commit_state() == |
777 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || | 817 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |
778 state_machine_.commit_state() == | 818 state_machine_.commit_state() == |
779 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); | 819 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); |
780 } | 820 } |
781 | 821 |
782 } // namespace cc | 822 } // namespace cc |
OLD | NEW |