[go: nahoru, domu]

blob: 0d90c68214f15a822f66419d899885b7a4e84e56 [file] [log] [blame]
jamesr@chromium.org94f206c12012-08-25 00:09:141// Copyright 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
jamesr@chromium.orgbe4655a2013-03-18 08:36:315#include "cc/scheduler/scheduler.h"
jamesr@chromium.org94f206c12012-08-25 00:09:146
brianderson@chromium.org425e5332013-09-21 04:10:037#include <algorithm>
simonhonga7e3ac42014-11-11 20:50:228
jamesr@chromium.org6331a112012-10-18 11:35:139#include "base/auto_reset.h"
danakj@chromium.org1d993172012-10-18 18:15:0410#include "base/logging.h"
robliaodd25f5b2015-02-27 23:34:0211#include "base/profiler/scoped_tracker.h"
simonhong@chromium.orgb6de3442014-06-05 16:43:1912#include "base/single_thread_task_runner.h"
primianoc06e2382015-01-28 04:21:4913#include "base/trace_event/trace_event.h"
14#include "base/trace_event/trace_event_argument.h"
caseq@chromium.orgdbe759a2013-12-02 19:23:0215#include "cc/debug/devtools_instrumentation.h"
brianderson@chromium.org224b4522013-08-21 09:58:3016#include "cc/debug/traced_value.h"
brianderson@chromium.org3dc0c772014-04-26 10:06:0517#include "cc/scheduler/delay_based_time_source.h"
jamesr@chromium.org94f206c12012-08-25 00:09:1418
enne@chromium.org9c88e562012-09-14 22:21:3019namespace cc {
brianderson@chromium.org3dc0c772014-04-26 10:06:0520
mithroc34fc0b12014-09-30 09:10:4121BeginFrameSource* SchedulerFrameSourcesConstructor::ConstructPrimaryFrameSource(
22 Scheduler* scheduler) {
bajones274110612015-01-06 20:53:5923 if (scheduler->settings_.use_external_begin_frame_source) {
mithroc34fc0b12014-09-30 09:10:4124 TRACE_EVENT1("cc",
25 "Scheduler::Scheduler()",
26 "PrimaryFrameSource",
simonhonga7e3ac42014-11-11 20:50:2227 "ExternalBeginFrameSource");
28 DCHECK(scheduler->primary_frame_source_internal_)
29 << "Need external BeginFrameSource";
30 return scheduler->primary_frame_source_internal_.get();
mithroc34fc0b12014-09-30 09:10:4131 } else {
32 TRACE_EVENT1("cc",
33 "Scheduler::Scheduler()",
34 "PrimaryFrameSource",
35 "SyntheticBeginFrameSource");
36 scoped_ptr<SyntheticBeginFrameSource> synthetic_source =
37 SyntheticBeginFrameSource::Create(scheduler->task_runner_.get(),
38 scheduler->Now(),
39 BeginFrameArgs::DefaultInterval());
brianderson@chromium.org3dc0c772014-04-26 10:06:0540
mithroc34fc0b12014-09-30 09:10:4141 DCHECK(!scheduler->vsync_observer_);
42 scheduler->vsync_observer_ = synthetic_source.get();
brianderson@chromium.org3dc0c772014-04-26 10:06:0543
mithroc34fc0b12014-09-30 09:10:4144 DCHECK(!scheduler->primary_frame_source_internal_);
45 scheduler->primary_frame_source_internal_ = synthetic_source.Pass();
46 return scheduler->primary_frame_source_internal_.get();
brianderson@chromium.org3dc0c772014-04-26 10:06:0547 }
simonhong@chromium.orgb6de3442014-06-05 16:43:1948}
brianderson@chromium.org3dc0c772014-04-26 10:06:0549
mithroc34fc0b12014-09-30 09:10:4150BeginFrameSource*
bajones274110612015-01-06 20:53:5951SchedulerFrameSourcesConstructor::ConstructUnthrottledFrameSource(
52 Scheduler* scheduler) {
53 TRACE_EVENT1("cc", "Scheduler::Scheduler()", "UnthrottledFrameSource",
54 "BackToBackBeginFrameSource");
55 DCHECK(!scheduler->unthrottled_frame_source_internal_);
56 scheduler->unthrottled_frame_source_internal_ =
57 BackToBackBeginFrameSource::Create(scheduler->task_runner_.get());
58 return scheduler->unthrottled_frame_source_internal_.get();
59}
60
boliu@chromium.org48abf812014-03-20 17:41:5961Scheduler::Scheduler(
62 SchedulerClient* client,
63 const SchedulerSettings& scheduler_settings,
64 int layer_tree_host_id,
mithroc34fc0b12014-09-30 09:10:4165 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
simonhonga7e3ac42014-11-11 20:50:2266 scoped_ptr<BeginFrameSource> external_begin_frame_source,
mithroc34fc0b12014-09-30 09:10:4167 SchedulerFrameSourcesConstructor* frame_sources_constructor)
68 : frame_source_(),
69 primary_frame_source_(NULL),
simonhonga7e3ac42014-11-11 20:50:2270 primary_frame_source_internal_(external_begin_frame_source.Pass()),
mithroc34fc0b12014-09-30 09:10:4171 vsync_observer_(NULL),
simonhong298590fe2015-03-25 06:51:1372 authoritative_vsync_interval_(base::TimeDelta()),
73 last_vsync_timebase_(base::TimeTicks()),
mithro4c7c76902015-04-09 07:05:0174 throttle_frame_production_(false),
mithroc34fc0b12014-09-30 09:10:4175 settings_(scheduler_settings),
enne@chromium.orga8335ac02013-03-16 09:15:1276 client_(client),
caseq@chromium.orgdbe759a2013-12-02 19:23:0277 layer_tree_host_id_(layer_tree_host_id),
enne@chromium.orgaeeedad2014-08-22 18:16:2278 task_runner_(task_runner),
sunnypseab5ac92015-04-02 20:26:1379 begin_impl_frame_deadline_mode_(
80 SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE),
mithro0bdb49d2015-05-27 13:08:0181 begin_impl_frame_tracker_(BEGINFRAMETRACKER_FROM_HERE),
enne@chromium.orga8335ac02013-03-16 09:15:1282 state_machine_(scheduler_settings),
epenner@chromium.orgc48536a52013-09-14 00:02:0883 inside_process_scheduled_actions_(false),
dmichael@chromium.org526bc6c2013-10-08 20:34:3284 inside_action_(SchedulerStateMachine::ACTION_NONE),
85 weak_factory_(this) {
mithro@mithis.comea00bf6a2014-05-11 00:53:2086 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
87 "Scheduler::Scheduler",
88 "settings",
yurys@chromium.orgd12aa932014-08-01 13:10:3889 settings_.AsValue());
enne@chromium.orga8335ac02013-03-16 09:15:1290 DCHECK(client_);
brianderson@chromium.org97e9ccd62014-04-12 01:07:1591 DCHECK(!state_machine_.BeginFrameNeeded());
brianderson@chromium.orgbeed86c2014-04-04 04:34:2892
brianderson@chromium.org97e9ccd62014-04-12 01:07:1593 begin_retro_frame_closure_ =
94 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr());
brianderson@chromium.orgbeed86c2014-04-04 04:34:2895 begin_impl_frame_deadline_closure_ = base::Bind(
96 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr());
brianderson@chromium.orgbeed86c2014-04-04 04:34:2897 advance_commit_state_closure_ = base::Bind(
98 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr());
brianderson@chromium.org3dc0c772014-04-26 10:06:0599
mithroc34fc0b12014-09-30 09:10:41100 frame_source_ = BeginFrameSourceMultiplexer::Create();
101 frame_source_->AddObserver(this);
102
103 // Primary frame source
104 primary_frame_source_ =
105 frame_sources_constructor->ConstructPrimaryFrameSource(this);
106 frame_source_->AddSource(primary_frame_source_);
simonhonga7e3ac42014-11-11 20:50:22107 primary_frame_source_->SetClientReady();
mithroc34fc0b12014-09-30 09:10:41108
bajones274110612015-01-06 20:53:59109 // Unthrottled frame source
110 unthrottled_frame_source_ =
111 frame_sources_constructor->ConstructUnthrottledFrameSource(this);
112 frame_source_->AddSource(unthrottled_frame_source_);
mithro4c7c76902015-04-09 07:05:01113
114 SetThrottleFrameProduction(scheduler_settings.throttle_frame_production);
jamesr@chromium.org94f206c12012-08-25 00:09:14115}
116
brianderson@chromium.org3dc0c772014-04-26 10:06:05117Scheduler::~Scheduler() {
simonhonga7e3ac42014-11-11 20:50:22118 if (frame_source_->NeedsBeginFrames())
119 frame_source_->SetNeedsBeginFrames(false);
sunnypsb2514f2f2015-04-14 22:51:57120 frame_source_->SetActiveSource(nullptr);
mithro0c0ac6a2014-09-10 01:03:36121}
122
123base::TimeTicks Scheduler::Now() const {
abhishek.ka7215854d2015-05-26 06:13:17124 base::TimeTicks now = base::TimeTicks::Now();
mithroc34fc0b12014-09-30 09:10:41125 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now"),
126 "Scheduler::Now",
127 "now",
128 now);
129 return now;
sunnyps340939792014-10-16 21:59:58130}
131
brianderson@chromium.org3dc0c772014-04-26 10:06:05132void Scheduler::CommitVSyncParameters(base::TimeTicks timebase,
133 base::TimeDelta interval) {
simonhong298590fe2015-03-25 06:51:13134 if (authoritative_vsync_interval_ != base::TimeDelta()) {
135 interval = authoritative_vsync_interval_;
136 } else if (interval == base::TimeDelta()) {
137 // TODO(brianderson): We should not be receiving 0 intervals.
brianderson@chromium.org3dc0c772014-04-26 10:06:05138 interval = BeginFrameArgs::DefaultInterval();
simonhong298590fe2015-03-25 06:51:13139 }
140
141 last_vsync_timebase_ = timebase;
mithroc34fc0b12014-09-30 09:10:41142
143 if (vsync_observer_)
144 vsync_observer_->OnUpdateVSyncParameters(timebase, interval);
brianderson@chromium.org3dc0c772014-04-26 10:06:05145}
146
147void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
brianderson@chromium.org1d142de82014-06-11 12:48:23148 DCHECK_GE(draw_time.ToInternalValue(), 0);
brianderson@chromium.org3dc0c772014-04-26 10:06:05149 estimated_parent_draw_time_ = draw_time;
150}
enne@chromium.orga8335ac02013-03-16 09:15:12151
boliu@chromium.org04049fc2013-05-01 03:13:20152void Scheduler::SetCanStart() {
153 state_machine_.SetCanStart();
enne@chromium.orga8335ac02013-03-16 09:15:12154 ProcessScheduledActions();
jamesr@chromium.org94f206c12012-08-25 00:09:14155}
156
bajones274110612015-01-06 20:53:59157void Scheduler::SetVisible(bool visible) {
158 state_machine_.SetVisible(visible);
mithro4c7c76902015-04-09 07:05:01159 ProcessScheduledActions();
jamesr@chromium.org94f206c12012-08-25 00:09:14160}
161
enne@chromium.orga8335ac02013-03-16 09:15:12162void Scheduler::SetCanDraw(bool can_draw) {
163 state_machine_.SetCanDraw(can_draw);
164 ProcessScheduledActions();
jamesr@chromium.org94f206c12012-08-25 00:09:14165}
166
brianderson@chromium.org4f48f6e2013-08-27 06:33:38167void Scheduler::NotifyReadyToActivate() {
168 state_machine_.NotifyReadyToActivate();
enne@chromium.orga8335ac02013-03-16 09:15:12169 ProcessScheduledActions();
brianderson@chromium.org425e5332013-09-21 04:10:03170}
171
ernstmdfac03e2014-11-11 20:18:05172void Scheduler::NotifyReadyToDraw() {
weiliangc8dac5a62015-04-02 06:12:35173 // Future work might still needed for crbug.com/352894.
174 state_machine_.NotifyReadyToDraw();
175 ProcessScheduledActions();
ernstmdfac03e2014-11-11 20:18:05176}
177
bajones274110612015-01-06 20:53:59178void Scheduler::SetThrottleFrameProduction(bool throttle) {
179 throttle_frame_production_ = throttle;
mithro4c7c76902015-04-09 07:05:01180 if (throttle) {
181 frame_source_->SetActiveSource(primary_frame_source_);
182 } else {
183 frame_source_->SetActiveSource(unthrottled_frame_source_);
184 }
185 ProcessScheduledActions();
bajones274110612015-01-06 20:53:59186}
187
enne@chromium.orga8335ac02013-03-16 09:15:12188void Scheduler::SetNeedsCommit() {
189 state_machine_.SetNeedsCommit();
190 ProcessScheduledActions();
enne@chromium.org2e7ca422012-12-20 02:57:27191}
192
enne@chromium.orga8335ac02013-03-16 09:15:12193void Scheduler::SetNeedsRedraw() {
194 state_machine_.SetNeedsRedraw();
epenner@chromium.orgc48536a52013-09-14 00:02:08195 ProcessScheduledActions();
196}
197
skyostil@chromium.org43b8f982014-04-30 21:24:33198void Scheduler::SetNeedsAnimate() {
199 state_machine_.SetNeedsAnimate();
200 ProcessScheduledActions();
201}
202
vmiura59ea9b4042014-12-09 20:50:39203void Scheduler::SetNeedsPrepareTiles() {
204 DCHECK(!IsInsideAction(SchedulerStateMachine::ACTION_PREPARE_TILES));
205 state_machine_.SetNeedsPrepareTiles();
weiliangc8dac5a62015-04-02 06:12:35206 ProcessScheduledActions();
207}
208
209void Scheduler::SetWaitForReadyToDraw() {
210 state_machine_.SetWaitForReadyToDraw();
enne@chromium.orga8335ac02013-03-16 09:15:12211 ProcessScheduledActions();
jamesr@chromium.org94f206c12012-08-25 00:09:14212}
213
brianderson@chromium.orgc14902662014-04-18 05:06:11214void Scheduler::SetMaxSwapsPending(int max) {
215 state_machine_.SetMaxSwapsPending(max);
216}
217
218void Scheduler::DidSwapBuffers() {
219 state_machine_.DidSwapBuffers();
simonhong@chromium.org30d82142014-05-12 04:26:02220
brianderson@chromium.orgc14902662014-04-18 05:06:11221 // There is no need to call ProcessScheduledActions here because
222 // swapping should not trigger any new actions.
223 if (!inside_process_scheduled_actions_) {
224 DCHECK_EQ(state_machine_.NextAction(), SchedulerStateMachine::ACTION_NONE);
225 }
226}
227
brianderson@chromium.orgc14902662014-04-18 05:06:11228void Scheduler::DidSwapBuffersComplete() {
brianderson1545de02015-06-05 22:05:44229 DCHECK_GT(state_machine_.pending_swaps(), 0) << AsValue()->ToString();
brianderson@chromium.orgc14902662014-04-18 05:06:11230 state_machine_.DidSwapBuffersComplete();
enne@chromium.orga8335ac02013-03-16 09:15:12231 ProcessScheduledActions();
brianderson@chromium.org74d9063c2013-01-18 03:14:47232}
233
skyostil733d7ab2014-09-04 23:11:32234void Scheduler::SetImplLatencyTakesPriority(bool impl_latency_takes_priority) {
235 state_machine_.SetImplLatencyTakesPriority(impl_latency_takes_priority);
skyostil@chromium.orgb56e320c2013-10-22 16:17:28236 ProcessScheduledActions();
237}
238
simonhong@chromium.org6f118452014-03-10 07:11:11239void Scheduler::NotifyReadyToCommit() {
240 TRACE_EVENT0("cc", "Scheduler::NotifyReadyToCommit");
241 state_machine_.NotifyReadyToCommit();
enne@chromium.orga8335ac02013-03-16 09:15:12242 ProcessScheduledActions();
jamesr@chromium.org94f206c12012-08-25 00:09:14243}
244
mithrof7a21502014-12-17 03:24:48245void Scheduler::BeginMainFrameAborted(CommitEarlyOutReason reason) {
246 TRACE_EVENT1("cc", "Scheduler::BeginMainFrameAborted", "reason",
247 CommitEarlyOutReasonToString(reason));
248 state_machine_.BeginMainFrameAborted(reason);
enne@chromium.orga8335ac02013-03-16 09:15:12249 ProcessScheduledActions();
jamesr@chromium.org94f206c12012-08-25 00:09:14250}
251
vmiura59ea9b4042014-12-09 20:50:39252void Scheduler::DidPrepareTiles() {
253 state_machine_.DidPrepareTiles();
enne@chromium.orgbac0e552013-11-05 22:38:51254}
255
enne@chromium.orga8335ac02013-03-16 09:15:12256void Scheduler::DidLoseOutputSurface() {
danakj@chromium.orged511b8d2013-03-25 03:29:29257 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface");
sunnyps324cd532014-12-30 21:28:10258 begin_retro_frame_args_.clear();
259 begin_retro_frame_task_.Cancel();
enne@chromium.orga8335ac02013-03-16 09:15:12260 state_machine_.DidLoseOutputSurface();
261 ProcessScheduledActions();
jamesr@chromium.org94f206c12012-08-25 00:09:14262}
263
boliu@chromium.org04049fc2013-05-01 03:13:20264void Scheduler::DidCreateAndInitializeOutputSurface() {
265 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface");
mithroc34fc0b12014-09-30 09:10:41266 DCHECK(!frame_source_->NeedsBeginFrames());
brianderson@chromium.orgbeed86c2014-04-04 04:34:28267 DCHECK(begin_impl_frame_deadline_task_.IsCancelled());
boliu@chromium.org04049fc2013-05-01 03:13:20268 state_machine_.DidCreateAndInitializeOutputSurface();
enne@chromium.orga8335ac02013-03-16 09:15:12269 ProcessScheduledActions();
jamesr@chromium.org94f206c12012-08-25 00:09:14270}
271
simonhong@chromium.orgeb2d2abc2014-03-07 16:19:59272void Scheduler::NotifyBeginMainFrameStarted() {
273 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted");
274 state_machine_.NotifyBeginMainFrameStarted();
275}
276
skyostil@chromium.org5c58f222014-03-07 03:34:09277base::TimeTicks Scheduler::AnticipatedDrawTime() const {
mithroc34fc0b12014-09-30 09:10:41278 if (!frame_source_->NeedsBeginFrames() ||
mithro0bdb49d2015-05-27 13:08:01279 begin_impl_frame_tracker_.DangerousMethodHasFinished())
brianderson@chromium.org049fc7a2013-06-18 12:32:35280 return base::TimeTicks();
281
mithro0c0ac6a2014-09-10 01:03:36282 base::TimeTicks now = Now();
mithro0bdb49d2015-05-27 13:08:01283 BeginFrameArgs args = begin_impl_frame_tracker_.Current();
284 base::TimeTicks timebase = std::max(args.frame_time, args.deadline);
285 int64 intervals =
286 1 + ((now - timebase) / begin_impl_frame_tracker_.Interval());
287 return timebase + (begin_impl_frame_tracker_.Interval() * intervals);
jamesr@chromium.org94f206c12012-08-25 00:09:14288}
289
dominikg@chromium.org87379cde2013-10-21 23:19:52290base::TimeTicks Scheduler::LastBeginImplFrameTime() {
mithro0bdb49d2015-05-27 13:08:01291 return begin_impl_frame_tracker_.Current().frame_time;
reveman@chromium.orge8e410d2012-09-28 01:47:01292}
293
brianderson@chromium.org97e9ccd62014-04-12 01:07:15294void Scheduler::SetupNextBeginFrameIfNeeded() {
sunnyps32f01252015-03-19 03:50:29295 // Never call SetNeedsBeginFrames if the frame source already has the right
296 // value.
297 if (frame_source_->NeedsBeginFrames() != state_machine_.BeginFrameNeeded()) {
298 if (state_machine_.BeginFrameNeeded()) {
299 // Call SetNeedsBeginFrames(true) as soon as possible.
300 frame_source_->SetNeedsBeginFrames(true);
caseqb6a58892015-05-27 13:14:29301 devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_,
302 true);
sunnyps32f01252015-03-19 03:50:29303 } else if (state_machine_.begin_impl_frame_state() ==
304 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) {
305 // Call SetNeedsBeginFrames(false) in between frames only.
306 frame_source_->SetNeedsBeginFrames(false);
rmcilroy0a19362a2015-02-18 12:34:25307 client_->SendBeginMainFrameNotExpectedSoon();
caseqb6a58892015-05-27 13:14:29308 devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_,
309 false);
rmcilroy0a19362a2015-02-18 12:34:25310 }
mithroc34fc0b12014-09-30 09:10:41311 }
312
brianderson@chromium.org3dc0c772014-04-26 10:06:05313 PostBeginRetroFrameIfNeeded();
brianderson@chromium.org3dc0c772014-04-26 10:06:05314}
315
316// We may need to poll when we can't rely on BeginFrame to advance certain
317// state or to avoid deadlock.
sunnypsecc5d202015-01-05 23:46:53318void Scheduler::SetupPollingMechanisms() {
sunnypseab5ac92015-04-02 20:26:13319 // At this point we'd prefer to advance through the commit flow by
320 // drawing a frame, however it's possible that the frame rate controller
321 // will not give us a BeginFrame until the commit completes. See
322 // crbug.com/317430 for an example of a swap ack being held on commit. Thus
323 // we set a repeating timer to poll on ProcessScheduledActions until we
324 // successfully reach BeginFrame. Synchronous compositor does not use
325 // frame rate controller or have the circular wait in the bug.
326 if (IsBeginMainFrameSentOrStarted() &&
327 !settings_.using_synchronous_renderer_compositor) {
brianderson@chromium.orgbeed86c2014-04-04 04:34:28328 if (advance_commit_state_task_.IsCancelled() &&
mithro0bdb49d2015-05-27 13:08:01329 begin_impl_frame_tracker_.DangerousMethodCurrentOrLast().IsValid()) {
boliu@chromium.org48abf812014-03-20 17:41:59330 // Since we'd rather get a BeginImplFrame by the normal mechanism, we
331 // set the interval to twice the interval from the previous frame.
brianderson@chromium.orgbeed86c2014-04-04 04:34:28332 advance_commit_state_task_.Reset(advance_commit_state_closure_);
enne@chromium.orgaeeedad2014-08-22 18:16:22333 task_runner_->PostDelayedTask(FROM_HERE,
334 advance_commit_state_task_.callback(),
mithro0bdb49d2015-05-27 13:08:01335 begin_impl_frame_tracker_.Interval() * 2);
brianderson@chromium.org875fb5bc2013-12-13 11:58:47336 }
brianderson@chromium.org22646b02014-04-03 23:55:32337 } else {
brianderson@chromium.orgbeed86c2014-04-04 04:34:28338 advance_commit_state_task_.Cancel();
brianderson@chromium.org049fc7a2013-06-18 12:32:35339 }
340}
341
brianderson@chromium.org97e9ccd62014-04-12 01:07:15342// BeginFrame is the mechanism that tells us that now is a good time to start
343// making a frame. Usually this means that user input for the frame is complete.
344// If the scheduler is busy, we queue the BeginFrame to be handled later as
345// a BeginRetroFrame.
mithroc34fc0b12014-09-30 09:10:41346bool Scheduler::OnBeginFrameMixInDelegate(const BeginFrameArgs& args) {
miletusfed8c43b2015-01-26 20:04:52347 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginFrame", "args", args.AsValue());
mithro0bdb49d2015-05-27 13:08:01348
349 // Trace this begin frame time through the Chrome stack
350 TRACE_EVENT_FLOW_BEGIN0(
351 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs",
352 args.frame_time.ToInternalValue());
mithroc34fc0b12014-09-30 09:10:41353
brianderson7d4d98d2015-05-05 03:24:17354 // TODO(brianderson): Adjust deadline in the DisplayScheduler.
sunnypsb1e2f5ec2015-03-24 01:39:45355 BeginFrameArgs adjusted_args(args);
356 adjusted_args.deadline -= EstimatedParentDrawTime();
357
brianderson7d4d98d2015-05-05 03:24:17358 // Deliver BeginFrames to children.
359 // TODO(brianderson): Move this responsibility to the DisplayScheduler.
360 if (state_machine_.children_need_begin_frames())
361 client_->SendBeginFramesToChildren(adjusted_args);
362
sunnypseab5ac92015-04-02 20:26:13363 if (settings_.using_synchronous_renderer_compositor) {
364 BeginImplFrameSynchronous(adjusted_args);
365 return true;
366 }
367
mithroc34fc0b12014-09-30 09:10:41368 // We have just called SetNeedsBeginFrame(true) and the BeginFrameSource has
369 // sent us the last BeginFrame we have missed. As we might not be able to
370 // actually make rendering for this call, handle it like a "retro frame".
371 // TODO(brainderson): Add a test for this functionality ASAP!
sunnypsb1e2f5ec2015-03-24 01:39:45372 if (adjusted_args.type == BeginFrameArgs::MISSED) {
373 begin_retro_frame_args_.push_back(adjusted_args);
mithroc34fc0b12014-09-30 09:10:41374 PostBeginRetroFrameIfNeeded();
375 return true;
376 }
mithro@mithis.comb62dcb82014-06-11 13:27:48377
sunnypseab5ac92015-04-02 20:26:13378 bool should_defer_begin_frame =
379 !begin_retro_frame_args_.empty() ||
380 !begin_retro_frame_task_.IsCancelled() ||
381 !frame_source_->NeedsBeginFrames() ||
382 (state_machine_.begin_impl_frame_state() !=
383 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
brianderson@chromium.org97e9ccd62014-04-12 01:07:15384
385 if (should_defer_begin_frame) {
mithro@mithis.comb62dcb82014-06-11 13:27:48386 begin_retro_frame_args_.push_back(adjusted_args);
brianderson@chromium.org97e9ccd62014-04-12 01:07:15387 TRACE_EVENT_INSTANT0(
388 "cc", "Scheduler::BeginFrame deferred", TRACE_EVENT_SCOPE_THREAD);
mithroc34fc0b12014-09-30 09:10:41389 // Queuing the frame counts as "using it", so we need to return true.
390 } else {
sunnypseab5ac92015-04-02 20:26:13391 BeginImplFrameWithDeadline(adjusted_args);
brianderson@chromium.org97e9ccd62014-04-12 01:07:15392 }
mithroc34fc0b12014-09-30 09:10:41393 return true;
brianderson@chromium.org97e9ccd62014-04-12 01:07:15394}
395
simonhongd3d5f7f2014-11-21 16:38:03396void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) {
simonhongd3d5f7f2014-11-21 16:38:03397 state_machine_.SetChildrenNeedBeginFrames(children_need_begin_frames);
simonhong22c5f0f22014-12-16 00:06:37398 ProcessScheduledActions();
sunnypseab5ac92015-04-02 20:26:13399}
400
brianderson2954ab12015-04-14 05:42:35401void Scheduler::SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) {
402 authoritative_vsync_interval_ = interval;
403 if (vsync_observer_)
404 vsync_observer_->OnUpdateVSyncParameters(last_vsync_timebase_, interval);
405}
406
sunnyps7d073dc2015-04-16 23:29:12407void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) {
408 state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames);
409 ProcessScheduledActions();
410}
411
sunnypseab5ac92015-04-02 20:26:13412void Scheduler::OnDrawForOutputSurface() {
413 DCHECK(settings_.using_synchronous_renderer_compositor);
414 DCHECK_EQ(state_machine_.begin_impl_frame_state(),
415 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
416 DCHECK(!BeginImplFrameDeadlinePending());
417
418 state_machine_.OnBeginImplFrameDeadline();
419 ProcessScheduledActions();
420
421 state_machine_.OnBeginImplFrameIdle();
422 ProcessScheduledActions();
simonhong298590fe2015-03-25 06:51:13423}
424
brianderson@chromium.org97e9ccd62014-04-12 01:07:15425// BeginRetroFrame is called for BeginFrames that we've deferred because
426// the scheduler was in the middle of processing a previous BeginFrame.
427void Scheduler::BeginRetroFrame() {
miletusfed8c43b2015-01-26 20:04:52428 TRACE_EVENT0("cc,benchmark", "Scheduler::BeginRetroFrame");
brianderson@chromium.org97e9ccd62014-04-12 01:07:15429 DCHECK(!settings_.using_synchronous_renderer_compositor);
sunnyps324cd532014-12-30 21:28:10430 DCHECK(!begin_retro_frame_args_.empty());
431 DCHECK(!begin_retro_frame_task_.IsCancelled());
brianderson8ecfc9c2014-12-23 02:42:38432 DCHECK_EQ(state_machine_.begin_impl_frame_state(),
433 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
brianderson@chromium.org3dc0c772014-04-26 10:06:05434
sunnyps324cd532014-12-30 21:28:10435 begin_retro_frame_task_.Cancel();
brianderson@chromium.org97e9ccd62014-04-12 01:07:15436
437 // Discard expired BeginRetroFrames
438 // Today, we should always end up with at most one un-expired BeginRetroFrame
439 // because deadlines will not be greater than the next frame time. We don't
440 // DCHECK though because some systems don't always have monotonic timestamps.
441 // TODO(brianderson): In the future, long deadlines could result in us not
442 // draining the queue if we don't catch up. If we consistently can't catch
443 // up, our fallback should be to lower our frame rate.
mithro0c0ac6a2014-09-10 01:03:36444 base::TimeTicks now = Now();
mithro7deb2762014-09-19 01:07:51445
sunnyps977116d2014-11-26 20:33:30446 while (!begin_retro_frame_args_.empty()) {
447 const BeginFrameArgs& args = begin_retro_frame_args_.front();
sunnyps7e4f04592015-05-20 01:43:57448 base::TimeTicks expiration_time = args.deadline;
sunnyps977116d2014-11-26 20:33:30449 if (now <= expiration_time)
450 break;
451 TRACE_EVENT_INSTANT2(
452 "cc", "Scheduler::BeginRetroFrame discarding", TRACE_EVENT_SCOPE_THREAD,
453 "expiration_time - now", (expiration_time - now).InMillisecondsF(),
454 "BeginFrameArgs", begin_retro_frame_args_.front().AsValue());
brianderson@chromium.org97e9ccd62014-04-12 01:07:15455 begin_retro_frame_args_.pop_front();
mithroc34fc0b12014-09-30 09:10:41456 frame_source_->DidFinishFrame(begin_retro_frame_args_.size());
brianderson@chromium.org97e9ccd62014-04-12 01:07:15457 }
458
459 if (begin_retro_frame_args_.empty()) {
mithro@mithis.com1ae2e642014-05-02 05:33:33460 TRACE_EVENT_INSTANT0("cc",
461 "Scheduler::BeginRetroFrames all expired",
462 TRACE_EVENT_SCOPE_THREAD);
brianderson@chromium.org97e9ccd62014-04-12 01:07:15463 } else {
danakj8d1716fb2014-11-14 23:04:49464 BeginFrameArgs front = begin_retro_frame_args_.front();
brianderson@chromium.org97e9ccd62014-04-12 01:07:15465 begin_retro_frame_args_.pop_front();
sunnypseab5ac92015-04-02 20:26:13466 BeginImplFrameWithDeadline(front);
brianderson@chromium.org97e9ccd62014-04-12 01:07:15467 }
brianderson@chromium.org97e9ccd62014-04-12 01:07:15468}
469
470// There could be a race between the posted BeginRetroFrame and a new
471// BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame
472// will check if there is a pending BeginRetroFrame to ensure we handle
473// BeginFrames in FIFO order.
474void Scheduler::PostBeginRetroFrameIfNeeded() {
mithro0c0ac6a2014-09-10 01:03:36475 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
476 "Scheduler::PostBeginRetroFrameIfNeeded",
477 "state",
478 AsValue());
mithroc34fc0b12014-09-30 09:10:41479 if (!frame_source_->NeedsBeginFrames())
brianderson@chromium.org3dc0c772014-04-26 10:06:05480 return;
481
sunnyps324cd532014-12-30 21:28:10482 if (begin_retro_frame_args_.empty() || !begin_retro_frame_task_.IsCancelled())
brianderson@chromium.org97e9ccd62014-04-12 01:07:15483 return;
484
485 // begin_retro_frame_args_ should always be empty for the
486 // synchronous compositor.
487 DCHECK(!settings_.using_synchronous_renderer_compositor);
488
489 if (state_machine_.begin_impl_frame_state() !=
490 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE)
491 return;
492
sunnyps324cd532014-12-30 21:28:10493 begin_retro_frame_task_.Reset(begin_retro_frame_closure_);
494
495 task_runner_->PostTask(FROM_HERE, begin_retro_frame_task_.callback());
brianderson@chromium.org97e9ccd62014-04-12 01:07:15496}
497
sunnypseab5ac92015-04-02 20:26:13498void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) {
sunnyps79f33c32015-04-23 20:56:38499 bool main_thread_is_in_high_latency_mode =
500 state_machine_.MainThreadIsInHighLatencyMode();
501 TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args",
502 args.AsValue(), "main_thread_is_high_latency",
503 main_thread_is_in_high_latency_mode);
504 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
505 "MainThreadLatency", main_thread_is_in_high_latency_mode);
506
507 advance_commit_state_task_.Cancel();
508
mithro0bdb49d2015-05-27 13:08:01509 BeginFrameArgs adjusted_args = args;
510 adjusted_args.deadline -= client_->DrawDurationEstimate();
sunnyps79f33c32015-04-23 20:56:38511
512 if (!state_machine_.impl_latency_takes_priority() &&
513 main_thread_is_in_high_latency_mode &&
514 CanCommitAndActivateBeforeDeadline()) {
515 state_machine_.SetSkipNextBeginMainFrameToReduceLatency();
516 }
517
mithro0bdb49d2015-05-27 13:08:01518 BeginImplFrame(adjusted_args);
sunnypseab5ac92015-04-02 20:26:13519
520 // The deadline will be scheduled in ProcessScheduledActions.
521 state_machine_.OnBeginImplFrameDeadlinePending();
522 ProcessScheduledActions();
523}
524
525void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) {
sunnyps79f33c32015-04-23 20:56:38526 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args",
527 args.AsValue());
mithro0bdb49d2015-05-27 13:08:01528 BeginImplFrame(args);
sunnypseab5ac92015-04-02 20:26:13529 FinishImplFrame();
530}
531
532void Scheduler::FinishImplFrame() {
533 state_machine_.OnBeginImplFrameIdle();
534 ProcessScheduledActions();
535
mithro51693e382015-05-07 23:52:41536 client_->DidFinishImplFrame();
sunnypseab5ac92015-04-02 20:26:13537 frame_source_->DidFinishFrame(begin_retro_frame_args_.size());
mithro0bdb49d2015-05-27 13:08:01538 begin_impl_frame_tracker_.Finish();
sunnypseab5ac92015-04-02 20:26:13539}
540
brianderson@chromium.org97e9ccd62014-04-12 01:07:15541// BeginImplFrame starts a compositor frame that will wait up until a deadline
542// for a BeginMainFrame+activation to complete before it times out and draws
543// any asynchronous animation and scroll/pinch updates.
mithro0bdb49d2015-05-27 13:08:01544void Scheduler::BeginImplFrame(const BeginFrameArgs& args) {
enne@chromium.orgaeeedad2014-08-22 18:16:22545 DCHECK_EQ(state_machine_.begin_impl_frame_state(),
546 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
sunnypseab5ac92015-04-02 20:26:13547 DCHECK(!BeginImplFrameDeadlinePending());
brianderson@chromium.org67bc0992013-09-24 06:24:03548 DCHECK(state_machine_.HasInitializedOutputSurface());
sunnyps79f33c32015-04-23 20:56:38549 DCHECK(advance_commit_state_task_.IsCancelled());
skyostil@chromium.org6d5aa6f2014-03-04 21:42:17550
mithro0bdb49d2015-05-27 13:08:01551 begin_impl_frame_tracker_.Start(args);
sunnypsbd2c89682015-03-20 00:13:12552 state_machine_.OnBeginImplFrame();
caseq@chromium.orgd73094482014-02-13 21:28:28553 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_);
mithro0bdb49d2015-05-27 13:08:01554 client_->WillBeginImplFrame(begin_impl_frame_tracker_.Current());
dominikg@chromium.org56ec7302013-11-08 00:51:45555
enne@chromium.orga8335ac02013-03-16 09:15:12556 ProcessScheduledActions();
skyostil@chromium.org46cc0d62014-03-11 00:35:16557}
558
sunnyps5d8bb1d22014-12-08 20:48:10559void Scheduler::ScheduleBeginImplFrameDeadline() {
sunnyps977116d2014-11-26 20:33:30560 // The synchronous compositor does not post a deadline task.
561 DCHECK(!settings_.using_synchronous_renderer_compositor);
brianderson@chromium.org425e5332013-09-21 04:10:03562
brianderson@chromium.orgbeed86c2014-04-04 04:34:28563 begin_impl_frame_deadline_task_.Cancel();
564 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_);
sunnyps5d8bb1d22014-12-08 20:48:10565
566 begin_impl_frame_deadline_mode_ =
567 state_machine_.CurrentBeginImplFrameDeadlineMode();
568
569 base::TimeTicks deadline;
570 switch (begin_impl_frame_deadline_mode_) {
sunnypseab5ac92015-04-02 20:26:13571 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE:
572 // No deadline.
573 return;
sunnyps5d8bb1d22014-12-08 20:48:10574 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE:
575 // We are ready to draw a new active tree immediately.
576 // We don't use Now() here because it's somewhat expensive to call.
577 deadline = base::TimeTicks();
578 break;
579 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR:
580 // We are animating on the impl thread but we can wait for some time.
mithro0bdb49d2015-05-27 13:08:01581 deadline = begin_impl_frame_tracker_.Current().deadline;
sunnyps5d8bb1d22014-12-08 20:48:10582 break;
583 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE:
584 // We are blocked for one reason or another and we should wait.
585 // TODO(brianderson): Handle long deadlines (that are past the next
586 // frame's frame time) properly instead of using this hack.
mithro0bdb49d2015-05-27 13:08:01587 deadline = begin_impl_frame_tracker_.Current().frame_time +
588 begin_impl_frame_tracker_.Current().interval;
sunnyps5d8bb1d22014-12-08 20:48:10589 break;
weiliangc8dac5a62015-04-02 06:12:35590 case SchedulerStateMachine::
591 BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW:
592 // We are blocked because we are waiting for ReadyToDraw signal. We would
593 // post deadline after we received ReadyToDraw singal.
594 TRACE_EVENT1("cc", "Scheduler::ScheduleBeginImplFrameDeadline",
595 "deadline_mode", "blocked_on_ready_to_draw");
596 return;
sunnyps5d8bb1d22014-12-08 20:48:10597 }
598
sunnypseab5ac92015-04-02 20:26:13599 TRACE_EVENT2("cc", "Scheduler::ScheduleBeginImplFrameDeadline", "mode",
600 SchedulerStateMachine::BeginImplFrameDeadlineModeToString(
601 begin_impl_frame_deadline_mode_),
602 "deadline", deadline);
boliu@chromium.org48abf812014-03-20 17:41:59603
sunnypseab5ac92015-04-02 20:26:13604 base::TimeDelta delta = std::max(deadline - Now(), base::TimeDelta());
enne@chromium.orgaeeedad2014-08-22 18:16:22605 task_runner_->PostDelayedTask(
brianderson@chromium.orgbeed86c2014-04-04 04:34:28606 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta);
sunnyps5d8bb1d22014-12-08 20:48:10607}
608
sunnypseab5ac92015-04-02 20:26:13609void Scheduler::ScheduleBeginImplFrameDeadlineIfNeeded() {
sunnypsb6ee9a212015-04-02 00:51:03610 if (settings_.using_synchronous_renderer_compositor)
611 return;
612
sunnyps5d8bb1d22014-12-08 20:48:10613 if (state_machine_.begin_impl_frame_state() !=
614 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
615 return;
616
sunnypseab5ac92015-04-02 20:26:13617 if (begin_impl_frame_deadline_mode_ ==
618 state_machine_.CurrentBeginImplFrameDeadlineMode() &&
619 BeginImplFrameDeadlinePending())
620 return;
621
622 ScheduleBeginImplFrameDeadline();
brianderson@chromium.org425e5332013-09-21 04:10:03623}
624
dominikg@chromium.org87379cde2013-10-21 23:19:52625void Scheduler::OnBeginImplFrameDeadline() {
miletusfed8c43b2015-01-26 20:04:52626 TRACE_EVENT0("cc,benchmark", "Scheduler::OnBeginImplFrameDeadline");
brianderson@chromium.orgbeed86c2014-04-04 04:34:28627 begin_impl_frame_deadline_task_.Cancel();
brianderson@chromium.org1d8571b52014-02-08 02:33:58628 // We split the deadline actions up into two phases so the state machine
629 // has a chance to trigger actions that should occur durring and after
630 // the deadline separately. For example:
631 // * Sending the BeginMainFrame will not occur after the deadline in
632 // order to wait for more user-input before starting the next commit.
633 // * Creating a new OuputSurface will not occur during the deadline in
634 // order to allow the state machine to "settle" first.
robliaodd25f5b2015-02-27 23:34:02635
636 // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is fixed.
637 tracked_objects::ScopedTracker tracking_profile1(
638 FROM_HERE_WITH_EXPLICIT_FUNCTION(
639 "461509 Scheduler::OnBeginImplFrameDeadline1"));
dominikg@chromium.org7d6685512013-10-19 18:04:38640 state_machine_.OnBeginImplFrameDeadline();
brianderson@chromium.org425e5332013-09-21 04:10:03641 ProcessScheduledActions();
sunnypseab5ac92015-04-02 20:26:13642 FinishImplFrame();
brianderson@chromium.org049fc7a2013-06-18 12:32:35643}
644
brianderson@chromium.org22646b02014-04-03 23:55:32645
646void Scheduler::PollToAdvanceCommitState() {
647 TRACE_EVENT0("cc", "Scheduler::PollToAdvanceCommitState");
brianderson@chromium.orgbeed86c2014-04-04 04:34:28648 advance_commit_state_task_.Cancel();
brianderson@chromium.org22646b02014-04-03 23:55:32649 ProcessScheduledActions();
brianderson@chromium.org02de8f42013-09-12 05:27:52650}
651
brianderson@chromium.org049fc7a2013-06-18 12:32:35652void Scheduler::DrawAndSwapIfPossible() {
simonhong@chromium.org30d82142014-05-12 04:26:02653 DrawResult result = client_->ScheduledActionDrawAndSwapIfPossible();
654 state_machine_.DidDrawIfPossibleCompleted(result);
egraether@chromium.orgf0c2a242013-03-15 19:34:52655}
656
simonhongc6309f792015-01-31 15:47:15657void Scheduler::SetDeferCommits(bool defer_commits) {
658 TRACE_EVENT1("cc", "Scheduler::SetDeferCommits",
659 "defer_commits",
660 defer_commits);
661 state_machine_.SetDeferCommits(defer_commits);
662 ProcessScheduledActions();
663}
664
enne@chromium.orga8335ac02013-03-16 09:15:12665void Scheduler::ProcessScheduledActions() {
666 // We do not allow ProcessScheduledActions to be recursive.
667 // The top-level call will iteratively execute the next action for us anyway.
668 if (inside_process_scheduled_actions_)
669 return;
jamesr@chromium.org94f206c12012-08-25 00:09:14670
enne@chromium.orga8335ac02013-03-16 09:15:12671 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true);
jamesr@chromium.org94f206c12012-08-25 00:09:14672
brianderson@chromium.org224b4522013-08-21 09:58:30673 SchedulerStateMachine::Action action;
674 do {
675 action = state_machine_.NextAction();
676 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
677 "SchedulerStateMachine",
678 "state",
yurys@chromium.orgd12aa932014-08-01 13:10:38679 AsValue());
mithro285b5b982015-05-26 04:57:50680 DVLOG(2) << "Scheduler::ProcessScheduledActions: "
681 << SchedulerStateMachine::ActionToString(action) << " "
682 << state_machine_.GetStatesForDebugging();
enne@chromium.orga8335ac02013-03-16 09:15:12683 state_machine_.UpdateState(action);
epenner@chromium.orgc48536a52013-09-14 00:02:08684 base::AutoReset<SchedulerStateMachine::Action>
685 mark_inside_action(&inside_action_, action);
enne@chromium.orga8335ac02013-03-16 09:15:12686 switch (action) {
687 case SchedulerStateMachine::ACTION_NONE:
skyostil@chromium.orgc2321962014-04-28 19:16:42688 break;
robliao27728e62015-03-21 07:39:34689 case SchedulerStateMachine::ACTION_ANIMATE:
skyostil@chromium.org43b8f982014-04-30 21:24:33690 client_->ScheduledActionAnimate();
691 break;
robliao27728e62015-03-21 07:39:34692 case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME:
dominikg@chromium.org87379cde2013-10-21 23:19:52693 client_->ScheduledActionSendBeginMainFrame();
enne@chromium.orga8335ac02013-03-16 09:15:12694 break;
robliaodd25f5b2015-02-27 23:34:02695 case SchedulerStateMachine::ACTION_COMMIT: {
696 // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is
697 // fixed.
698 tracked_objects::ScopedTracker tracking_profile4(
699 FROM_HERE_WITH_EXPLICIT_FUNCTION(
700 "461509 Scheduler::ProcessScheduledActions4"));
enne@chromium.orga8335ac02013-03-16 09:15:12701 client_->ScheduledActionCommit();
enne@chromium.orga8335ac02013-03-16 09:15:12702 break;
robliaodd25f5b2015-02-27 23:34:02703 }
robliao27728e62015-03-21 07:39:34704 case SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE:
alokp@chromium.orgdea398372014-07-07 19:37:19705 client_->ScheduledActionActivateSyncTree();
enne@chromium.orga8335ac02013-03-16 09:15:12706 break;
robliaodd25f5b2015-02-27 23:34:02707 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE: {
708 // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is
709 // fixed.
710 tracked_objects::ScopedTracker tracking_profile6(
711 FROM_HERE_WITH_EXPLICIT_FUNCTION(
712 "461509 Scheduler::ProcessScheduledActions6"));
brianderson@chromium.org049fc7a2013-06-18 12:32:35713 DrawAndSwapIfPossible();
enne@chromium.orga8335ac02013-03-16 09:15:12714 break;
robliaodd25f5b2015-02-27 23:34:02715 }
robliao27728e62015-03-21 07:39:34716 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED:
simonhong@chromium.org30d82142014-05-12 04:26:02717 client_->ScheduledActionDrawAndSwapForced();
enne@chromium.orga8335ac02013-03-16 09:15:12718 break;
brianderson@chromium.org1ef04b22013-08-23 05:47:16719 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT:
720 // No action is actually performed, but this allows the state machine to
721 // advance out of its waiting to draw state without actually drawing.
brianderson@chromium.org63e61892013-09-07 01:47:29722 break;
robliao27728e62015-03-21 07:39:34723 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
boliu@chromium.org04049fc2013-05-01 03:13:20724 client_->ScheduledActionBeginOutputSurfaceCreation();
enne@chromium.orga8335ac02013-03-16 09:15:12725 break;
robliao27728e62015-03-21 07:39:34726 case SchedulerStateMachine::ACTION_PREPARE_TILES:
vmiura59ea9b4042014-12-09 20:50:39727 client_->ScheduledActionPrepareTiles();
epenner@chromium.orgc48536a52013-09-14 00:02:08728 break;
sunnypseab5ac92015-04-02 20:26:13729 case SchedulerStateMachine::ACTION_INVALIDATE_OUTPUT_SURFACE: {
730 client_->ScheduledActionInvalidateOutputSurface();
731 break;
732 }
brianderson@chromium.orgd7223942012-09-26 22:43:33733 }
brianderson@chromium.org224b4522013-08-21 09:58:30734 } while (action != SchedulerStateMachine::ACTION_NONE);
sunnyps32f01252015-03-19 03:50:29735
736 SetupPollingMechanisms();
737
brianderson@chromium.org049fc7a2013-06-18 12:32:35738 client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime());
sunnyps32f01252015-03-19 03:50:29739
sunnypseab5ac92015-04-02 20:26:13740 ScheduleBeginImplFrameDeadlineIfNeeded();
sunnyps32f01252015-03-19 03:50:29741
742 SetupNextBeginFrameIfNeeded();
jamesr@chromium.org94f206c12012-08-25 00:09:14743}
744
ssid911e40e2015-02-09 17:55:20745scoped_refptr<base::trace_event::ConvertableToTraceFormat> Scheduler::AsValue()
yurys@chromium.orgd12aa932014-08-01 13:10:38746 const {
ssid911e40e2015-02-09 17:55:20747 scoped_refptr<base::trace_event::TracedValue> state =
748 new base::trace_event::TracedValue();
mithrod9168de2014-09-17 10:25:34749 AsValueInto(state.get());
750 return state;
751}
752
ssid911e40e2015-02-09 17:55:20753void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const {
yurys@chromium.orgd12aa932014-08-01 13:10:38754 state->BeginDictionary("state_machine");
sunnypsbd2c89682015-03-20 00:13:12755 state_machine_.AsValueInto(state);
yurys@chromium.orgd12aa932014-08-01 13:10:38756 state->EndDictionary();
mithroc34fc0b12014-09-30 09:10:41757
mithro99262872014-10-09 11:50:14758 // Only trace frame sources when explicitly enabled - http://crbug.com/420607
759 bool frame_tracing_enabled = false;
760 TRACE_EVENT_CATEGORY_GROUP_ENABLED(
761 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
762 &frame_tracing_enabled);
763 if (frame_tracing_enabled) {
764 state->BeginDictionary("frame_source_");
765 frame_source_->AsValueInto(state);
766 state->EndDictionary();
767 }
brianderson@chromium.orga14c6752014-04-03 11:42:47768
yurys@chromium.orgd12aa932014-08-01 13:10:38769 state->BeginDictionary("scheduler_state");
mithro0c0ac6a2014-09-10 01:03:36770 state->SetDouble("time_until_anticipated_draw_time_ms",
771 (AnticipatedDrawTime() - Now()).InMillisecondsF());
yurys@chromium.orgd12aa932014-08-01 13:10:38772 state->SetDouble("estimated_parent_draw_time_ms",
773 estimated_parent_draw_time_.InMillisecondsF());
mithroc34fc0b12014-09-30 09:10:41774 state->SetBoolean("last_set_needs_begin_frame_",
775 frame_source_->NeedsBeginFrames());
brianderson1545de02015-06-05 22:05:44776 state->SetInteger("begin_retro_frame_args",
vmpstr1ba0156d2015-06-04 01:38:51777 static_cast<int>(begin_retro_frame_args_.size()));
brianderson1545de02015-06-05 22:05:44778 state->SetBoolean("begin_retro_frame_task",
sunnyps324cd532014-12-30 21:28:10779 !begin_retro_frame_task_.IsCancelled());
brianderson1545de02015-06-05 22:05:44780 state->SetBoolean("begin_impl_frame_deadline_task",
yurys@chromium.orgd12aa932014-08-01 13:10:38781 !begin_impl_frame_deadline_task_.IsCancelled());
brianderson1545de02015-06-05 22:05:44782 state->SetBoolean("advance_commit_state_task",
yurys@chromium.orgd12aa932014-08-01 13:10:38783 !advance_commit_state_task_.IsCancelled());
brianderson1545de02015-06-05 22:05:44784 state->SetString("inside_action",
785 SchedulerStateMachine::ActionToString(inside_action_));
yurys@chromium.orgd12aa932014-08-01 13:10:38786 state->BeginDictionary("begin_impl_frame_args");
mithro0bdb49d2015-05-27 13:08:01787 begin_impl_frame_tracker_.AsValueInto(Now(), state);
yurys@chromium.orgd12aa932014-08-01 13:10:38788 state->EndDictionary();
yurys@chromium.orgd12aa932014-08-01 13:10:38789 state->EndDictionary();
skyostil@chromium.org5c58f222014-03-07 03:34:09790
yurys@chromium.orgd12aa932014-08-01 13:10:38791 state->BeginDictionary("client_state");
792 state->SetDouble("draw_duration_estimate_ms",
793 client_->DrawDurationEstimate().InMillisecondsF());
794 state->SetDouble(
skyostil@chromium.org5c58f222014-03-07 03:34:09795 "begin_main_frame_to_commit_duration_estimate_ms",
796 client_->BeginMainFrameToCommitDurationEstimate().InMillisecondsF());
yurys@chromium.orgd12aa932014-08-01 13:10:38797 state->SetDouble(
skyostil@chromium.org5c58f222014-03-07 03:34:09798 "commit_to_activate_duration_estimate_ms",
799 client_->CommitToActivateDurationEstimate().InMillisecondsF());
yurys@chromium.orgd12aa932014-08-01 13:10:38800 state->EndDictionary();
skyostil@chromium.org5c58f222014-03-07 03:34:09801}
802
dominikg@chromium.org56ec7302013-11-08 00:51:45803bool Scheduler::CanCommitAndActivateBeforeDeadline() const {
mithro0bdb49d2015-05-27 13:08:01804 BeginFrameArgs args =
805 begin_impl_frame_tracker_.DangerousMethodCurrentOrLast();
806
dominikg@chromium.org56ec7302013-11-08 00:51:45807 // Check if the main thread computation and commit can be finished before the
808 // impl thread's deadline.
809 base::TimeTicks estimated_draw_time =
mithro0bdb49d2015-05-27 13:08:01810 args.frame_time + client_->BeginMainFrameToCommitDurationEstimate() +
dominikg@chromium.org56ec7302013-11-08 00:51:45811 client_->CommitToActivateDurationEstimate();
812
mithro0bdb49d2015-05-27 13:08:01813 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
814 "CanCommitAndActivateBeforeDeadline",
815 "time_left_after_drawing_ms",
816 (args.deadline - estimated_draw_time).InMillisecondsF(), "state",
817 AsValue());
skyostil@chromium.org5c58f222014-03-07 03:34:09818
mithro0bdb49d2015-05-27 13:08:01819 return estimated_draw_time < args.deadline;
dominikg@chromium.org56ec7302013-11-08 00:51:45820}
821
simonhong@chromium.orgeb2d2abc2014-03-07 16:19:59822bool Scheduler::IsBeginMainFrameSentOrStarted() const {
823 return (state_machine_.commit_state() ==
824 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
825 state_machine_.commit_state() ==
826 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED);
827}
828
tfarina@chromium.org0ef67472012-10-11 21:33:39829} // namespace cc