[go: nahoru, domu]

blob: ee5c3b77c10eae488885f0be65db24a02cf01329 [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"
danakj60bc3bc2016-04-09 00:24:4811#include "base/memory/ptr_util.h"
robliaodd25f5b2015-02-27 23:34:0212#include "base/profiler/scoped_tracker.h"
simonhong@chromium.orgb6de3442014-06-05 16:43:1913#include "base/single_thread_task_runner.h"
primianoc06e2382015-01-28 04:21:4914#include "base/trace_event/trace_event.h"
15#include "base/trace_event/trace_event_argument.h"
chrishtr82b5d9502017-03-20 18:25:3316#include "cc/base/devtools_instrumentation.h"
brianderson@chromium.org224b4522013-08-21 09:58:3017#include "cc/debug/traced_value.h"
briandersonc9f50352015-06-24 03:38:5818#include "cc/scheduler/compositor_timing_history.h"
brianderson@chromium.org3dc0c772014-04-26 10:06:0519#include "cc/scheduler/delay_based_time_source.h"
jamesr@chromium.org94f206c12012-08-25 00:09:1420
enne@chromium.org9c88e562012-09-14 22:21:3021namespace cc {
jamesr@chromium.org94f206c12012-08-25 00:09:1422
brianderson17ec1e92015-09-03 22:16:4923namespace {
24// This is a fudge factor we subtract from the deadline to account
25// for message latency and kernel scheduling variability.
26const base::TimeDelta kDeadlineFudgeFactor =
27 base::TimeDelta::FromMicroseconds(1000);
28}
29
boliu@chromium.org48abf812014-03-20 17:41:5930Scheduler::Scheduler(
31 SchedulerClient* client,
sunnypsf381ede2015-06-23 01:46:5332 const SchedulerSettings& settings,
boliu@chromium.org48abf812014-03-20 17:41:5933 int layer_tree_host_id,
sunnyps86c1dbcd2015-06-24 00:09:5834 base::SingleThreadTaskRunner* task_runner,
danakj60bc3bc2016-04-09 00:24:4835 std::unique_ptr<CompositorTimingHistory> compositor_timing_history)
sunnypsf381ede2015-06-23 01:46:5336 : settings_(settings),
enne@chromium.orga8335ac02013-03-16 09:15:1237 client_(client),
caseq@chromium.orgdbe759a2013-12-02 19:23:0238 layer_tree_host_id_(layer_tree_host_id),
enne@chromium.orgaeeedad2014-08-22 18:16:2239 task_runner_(task_runner),
danakja04855a2015-11-18 20:39:1040 compositor_timing_history_(std::move(compositor_timing_history)),
mithro0bdb49d2015-05-27 13:08:0141 begin_impl_frame_tracker_(BEGINFRAMETRACKER_FROM_HERE),
sunnypsf381ede2015-06-23 01:46:5342 state_machine_(settings),
dmichael@chromium.org526bc6c2013-10-08 20:34:3243 weak_factory_(this) {
sunnypsf381ede2015-06-23 01:46:5344 TRACE_EVENT1("cc", "Scheduler::Scheduler", "settings", settings_.AsValue());
enne@chromium.orga8335ac02013-03-16 09:15:1245 DCHECK(client_);
brianderson@chromium.org97e9ccd62014-04-12 01:07:1546 DCHECK(!state_machine_.BeginFrameNeeded());
Sunny Sachanandani4eab04822017-05-06 01:22:2447
48 begin_impl_frame_deadline_closure_ = base::Bind(
49 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr());
50
enne1e43e0d2016-03-09 00:47:3651 ProcessScheduledActions();
jamesr@chromium.org94f206c12012-08-25 00:09:1452}
53
brianderson@chromium.org3dc0c772014-04-26 10:06:0554Scheduler::~Scheduler() {
enne0ec08052016-03-18 18:22:4355 SetBeginFrameSource(nullptr);
mithro0c0ac6a2014-09-10 01:03:3656}
57
sunnypsda928f0a2016-10-08 00:32:5358void Scheduler::Stop() {
59 stopped_ = true;
60}
61
khushalsagarab73d502017-02-24 02:26:4662void Scheduler::SetNeedsImplSideInvalidation() {
63 state_machine_.SetNeedsImplSideInvalidation();
64 ProcessScheduledActions();
65}
66
mithro0c0ac6a2014-09-10 01:03:3667base::TimeTicks Scheduler::Now() const {
abhishek.ka7215854d2015-05-26 06:13:1768 base::TimeTicks now = base::TimeTicks::Now();
mithroc34fc0b12014-09-30 09:10:4169 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now"),
sunnypsbf106542016-07-14 00:22:3870 "Scheduler::Now", "now", now);
mithroc34fc0b12014-09-30 09:10:4171 return now;
brianderson@chromium.org3dc0c772014-04-26 10:06:0572}
73
bajones274110612015-01-06 20:53:5974void Scheduler::SetVisible(bool visible) {
75 state_machine_.SetVisible(visible);
brianderson68749812015-07-07 22:39:3976 UpdateCompositorTimingHistoryRecordingEnabled();
mithro4c7c76902015-04-09 07:05:0177 ProcessScheduledActions();
bajones274110612015-01-06 20:53:5978}
79
enne@chromium.orga8335ac02013-03-16 09:15:1280void Scheduler::SetCanDraw(bool can_draw) {
81 state_machine_.SetCanDraw(can_draw);
82 ProcessScheduledActions();
jamesr@chromium.org94f206c12012-08-25 00:09:1483}
84
rogerm8aeea932017-04-19 21:26:5785void Scheduler::NotifyReadyToActivate() {
brianderson68749812015-07-07 22:39:3986 compositor_timing_history_->ReadyToActivate();
brianderson@chromium.org4f48f6e2013-08-27 06:33:3887 state_machine_.NotifyReadyToActivate();
enne@chromium.orga8335ac02013-03-16 09:15:1288 ProcessScheduledActions();
jamesr@chromium.org8db2213c2012-09-05 22:08:2189}
90
ernstmdfac03e2014-11-11 20:18:0591void Scheduler::NotifyReadyToDraw() {
weiliangc8dac5a62015-04-02 06:12:3592 // Future work might still needed for crbug.com/352894.
93 state_machine_.NotifyReadyToDraw();
94 ProcessScheduledActions();
ernstmdfac03e2014-11-11 20:18:0595}
96
enne061ea9c82016-03-17 19:50:2697void Scheduler::SetBeginFrameSource(BeginFrameSource* source) {
enne061ea9c82016-03-17 19:50:2698 if (source == begin_frame_source_)
99 return;
100 if (begin_frame_source_ && observing_begin_frame_source_)
101 begin_frame_source_->RemoveObserver(this);
102 begin_frame_source_ = source;
enne0ec08052016-03-18 18:22:43103 if (!begin_frame_source_)
104 return;
enne061ea9c82016-03-17 19:50:26105 if (observing_begin_frame_source_)
106 begin_frame_source_->AddObserver(this);
107}
108
mithroe77254b32015-07-22 09:36:01109void Scheduler::SetNeedsBeginMainFrame() {
110 state_machine_.SetNeedsBeginMainFrame();
enne@chromium.orga8335ac02013-03-16 09:15:12111 ProcessScheduledActions();
enne@chromium.org2e7ca422012-12-20 02:57:27112}
113
danakjf10a6442015-11-03 23:14:25114void Scheduler::SetNeedsOneBeginImplFrame() {
115 state_machine_.SetNeedsOneBeginImplFrame();
116 ProcessScheduledActions();
117}
118
enne@chromium.orga8335ac02013-03-16 09:15:12119void Scheduler::SetNeedsRedraw() {
120 state_machine_.SetNeedsRedraw();
121 ProcessScheduledActions();
jamesr@chromium.org94f206c12012-08-25 00:09:14122}
123
vmiura59ea9b4042014-12-09 20:50:39124void Scheduler::SetNeedsPrepareTiles() {
125 DCHECK(!IsInsideAction(SchedulerStateMachine::ACTION_PREPARE_TILES));
126 state_machine_.SetNeedsPrepareTiles();
epenner@chromium.orgc48536a52013-09-14 00:02:08127 ProcessScheduledActions();
128}
129
danakj9d124422016-10-14 03:15:08130void Scheduler::DidSubmitCompositorFrame() {
131 compositor_timing_history_->DidSubmitCompositorFrame();
132 state_machine_.DidSubmitCompositorFrame();
simonhong@chromium.org30d82142014-05-12 04:26:02133
brianderson@chromium.orgc14902662014-04-18 05:06:11134 // There is no need to call ProcessScheduledActions here because
danakj9d124422016-10-14 03:15:08135 // submitting a CompositorFrame should not trigger any new actions.
brianderson@chromium.orgc14902662014-04-18 05:06:11136 if (!inside_process_scheduled_actions_) {
137 DCHECK_EQ(state_machine_.NextAction(), SchedulerStateMachine::ACTION_NONE);
138 }
139}
140
danakj9d124422016-10-14 03:15:08141void Scheduler::DidReceiveCompositorFrameAck() {
142 DCHECK_GT(state_machine_.pending_submit_frames(), 0) << AsValue()->ToString();
143 compositor_timing_history_->DidReceiveCompositorFrameAck();
144 state_machine_.DidReceiveCompositorFrameAck();
brianderson@chromium.orgc14902662014-04-18 05:06:11145 ProcessScheduledActions();
146}
147
brianderson42ef946a2015-11-19 02:36:40148void Scheduler::SetTreePrioritiesAndScrollState(
149 TreePriority tree_priority,
150 ScrollHandlerState scroll_handler_state) {
151 state_machine_.SetTreePrioritiesAndScrollState(tree_priority,
152 scroll_handler_state);
skyostil@chromium.orgb56e3202013-10-22 16:17:28153 ProcessScheduledActions();
154}
155
simonhong@chromium.org6f118452014-03-10 07:11:11156void Scheduler::NotifyReadyToCommit() {
157 TRACE_EVENT0("cc", "Scheduler::NotifyReadyToCommit");
158 state_machine_.NotifyReadyToCommit();
enne@chromium.orga8335ac02013-03-16 09:15:12159 ProcessScheduledActions();
jamesr@chromium.org94f206c12012-08-25 00:09:14160}
161
brianderson68749812015-07-07 22:39:39162void Scheduler::DidCommit() {
163 compositor_timing_history_->DidCommit();
164}
165
mithrof7a21502014-12-17 03:24:48166void Scheduler::BeginMainFrameAborted(CommitEarlyOutReason reason) {
167 TRACE_EVENT1("cc", "Scheduler::BeginMainFrameAborted", "reason",
168 CommitEarlyOutReasonToString(reason));
brianderson68749812015-07-07 22:39:39169 compositor_timing_history_->BeginMainFrameAborted();
mithrof7a21502014-12-17 03:24:48170 state_machine_.BeginMainFrameAborted(reason);
enne@chromium.orga8335ac02013-03-16 09:15:12171 ProcessScheduledActions();
jamesr@chromium.org94f206c12012-08-25 00:09:14172}
173
brianderson68749812015-07-07 22:39:39174void Scheduler::WillPrepareTiles() {
175 compositor_timing_history_->WillPrepareTiles();
176}
177
vmiura59ea9b4042014-12-09 20:50:39178void Scheduler::DidPrepareTiles() {
brianderson68749812015-07-07 22:39:39179 compositor_timing_history_->DidPrepareTiles();
vmiura59ea9b4042014-12-09 20:50:39180 state_machine_.DidPrepareTiles();
enne@chromium.orgbac0e552013-11-05 22:38:51181}
182
danakjc7afae52017-06-20 21:12:41183void Scheduler::DidLoseLayerTreeFrameSink() {
184 TRACE_EVENT0("cc", "Scheduler::DidLoseLayerTreeFrameSink");
185 state_machine_.DidLoseLayerTreeFrameSink();
brianderson68749812015-07-07 22:39:39186 UpdateCompositorTimingHistoryRecordingEnabled();
enne@chromium.orga8335ac02013-03-16 09:15:12187 ProcessScheduledActions();
jamesr@chromium.org94f206c12012-08-25 00:09:14188}
189
danakjc7afae52017-06-20 21:12:41190void Scheduler::DidCreateAndInitializeLayerTreeFrameSink() {
191 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeLayerTreeFrameSink");
enneb9bf3772016-03-16 21:51:11192 DCHECK(!observing_begin_frame_source_);
brianderson@chromium.orgbeed86c2014-04-04 04:34:28193 DCHECK(begin_impl_frame_deadline_task_.IsCancelled());
danakjc7afae52017-06-20 21:12:41194 state_machine_.DidCreateAndInitializeLayerTreeFrameSink();
195 compositor_timing_history_->DidCreateAndInitializeLayerTreeFrameSink();
brianderson68749812015-07-07 22:39:39196 UpdateCompositorTimingHistoryRecordingEnabled();
enne@chromium.orga8335ac02013-03-16 09:15:12197 ProcessScheduledActions();
jamesr@chromium.org94f206c12012-08-25 00:09:14198}
199
brianderson21aef162015-11-11 05:12:23200void Scheduler::NotifyBeginMainFrameStarted(
201 base::TimeTicks main_thread_start_time) {
simonhong@chromium.orgeb2d2abc2014-03-07 16:19:59202 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted");
203 state_machine_.NotifyBeginMainFrameStarted();
brianderson21aef162015-11-11 05:12:23204 compositor_timing_history_->BeginMainFrameStarted(main_thread_start_time);
simonhong@chromium.orgeb2d2abc2014-03-07 16:19:59205}
206
dominikg@chromium.org87379cde2013-10-21 23:19:52207base::TimeTicks Scheduler::LastBeginImplFrameTime() {
mithro0bdb49d2015-05-27 13:08:01208 return begin_impl_frame_tracker_.Current().frame_time;
reveman@chromium.orge8e410d2012-09-28 01:47:01209}
210
delphick9db74aa2017-05-05 10:20:49211void Scheduler::BeginMainFrameNotExpectedUntil(base::TimeTicks time) {
delphick564084052017-05-15 12:43:44212 TRACE_EVENT1("cc", "Scheduler::BeginMainFrameNotExpectedUntil",
213 "remaining_time", (time - Now()).InMillisecondsF());
delphick9db74aa2017-05-05 10:20:49214 client_->ScheduledActionBeginMainFrameNotExpectedUntil(time);
215}
216
briandersond32468d2015-11-25 22:08:55217void Scheduler::BeginImplFrameNotExpectedSoon() {
218 compositor_timing_history_->BeginImplFrameNotExpectedSoon();
219
220 // Tying this to SendBeginMainFrameNotExpectedSoon will have some
221 // false negatives, but we want to avoid running long idle tasks when
222 // we are actually active.
Dan Elphick99f685d2017-06-15 11:13:51223 if (state_machine_.wants_begin_main_frame_not_expected_messages()) {
224 client_->SendBeginMainFrameNotExpectedSoon();
225 }
briandersond32468d2015-11-25 22:08:55226}
227
brianderson@chromium.org97e9ccd62014-04-12 01:07:15228void Scheduler::SetupNextBeginFrameIfNeeded() {
sunnypsda928f0a2016-10-08 00:32:53229 if (state_machine_.begin_impl_frame_state() !=
230 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) {
231 return;
mithroc34fc0b12014-09-30 09:10:41232 }
sammc95beb472016-09-12 08:35:45233
sunnypsda928f0a2016-10-08 00:32:53234 bool needs_begin_frames = state_machine_.BeginFrameNeeded();
235 if (needs_begin_frames && !observing_begin_frame_source_) {
Sunny Sachanandani4eab04822017-05-06 01:22:24236 observing_begin_frame_source_ = true;
237 if (begin_frame_source_)
238 begin_frame_source_->AddObserver(this);
239 devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_, true);
sunnypsda928f0a2016-10-08 00:32:53240 } else if (!needs_begin_frames && observing_begin_frame_source_) {
Sunny Sachanandani4eab04822017-05-06 01:22:24241 observing_begin_frame_source_ = false;
242 if (begin_frame_source_)
243 begin_frame_source_->RemoveObserver(this);
244 missed_begin_frame_task_.Cancel();
245 BeginImplFrameNotExpectedSoon();
246 devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_,
247 false);
sunnypsda928f0a2016-10-08 00:32:53248 }
brianderson@chromium.org3dc0c772014-04-26 10:06:05249}
250
boliu0c1f91d2016-01-13 19:27:37251void Scheduler::OnBeginFrameSourcePausedChanged(bool paused) {
252 if (state_machine_.begin_frame_source_paused() == paused)
253 return;
254 TRACE_EVENT_INSTANT1("cc", "Scheduler::SetBeginFrameSourcePaused",
255 TRACE_EVENT_SCOPE_THREAD, "paused", paused);
256 state_machine_.SetBeginFrameSourcePaused(paused);
257 ProcessScheduledActions();
258}
259
brianderson@chromium.org97e9ccd62014-04-12 01:07:15260// BeginFrame is the mechanism that tells us that now is a good time to start
261// making a frame. Usually this means that user input for the frame is complete.
262// If the scheduler is busy, we queue the BeginFrame to be handled later as
263// a BeginRetroFrame.
deepak.s796a5ba2015-06-12 19:08:24264bool Scheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) {
miletusfed8c43b2015-01-26 20:04:52265 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginFrame", "args", args.AsValue());
mithroc34fc0b12014-09-30 09:10:41266
sunnypsda928f0a2016-10-08 00:32:53267 if (!state_machine_.BeginFrameNeeded()) {
268 TRACE_EVENT_INSTANT0("cc", "Scheduler::BeginFrameDropped",
269 TRACE_EVENT_SCOPE_THREAD);
eseckler37da9b32017-02-24 23:36:56270 // Since we don't use the BeginFrame, we may later receive the same
271 // BeginFrame again. Thus, we can't confirm it at this point, even though we
272 // don't have any updates right now.
273 SendBeginFrameAck(args, kBeginFrameSkipped);
sunnypsda928f0a2016-10-08 00:32:53274 return false;
275 }
276
mithro0bdb49d2015-05-27 13:08:01277 // Trace this begin frame time through the Chrome stack
278 TRACE_EVENT_FLOW_BEGIN0(
279 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs",
280 args.frame_time.ToInternalValue());
281
sunnypseab5ac92015-04-02 20:26:13282 if (settings_.using_synchronous_renderer_compositor) {
ennebfdea7f2016-09-20 01:09:27283 BeginImplFrameSynchronous(args);
sunnypseab5ac92015-04-02 20:26:13284 return true;
285 }
286
Sunny Sachanandani4eab04822017-05-06 01:22:24287 if (inside_process_scheduled_actions_) {
288 // The BFS can send a missed begin frame inside AddObserver. We can't handle
289 // a begin frame inside ProcessScheduledActions so post a task.
290 DCHECK_EQ(args.type, BeginFrameArgs::MISSED);
291 DCHECK(missed_begin_frame_task_.IsCancelled());
292 missed_begin_frame_task_.Reset(base::Bind(
293 &Scheduler::BeginImplFrameWithDeadline, base::Unretained(this), args));
294 task_runner_->PostTask(FROM_HERE, missed_begin_frame_task_.callback());
mithroc34fc0b12014-09-30 09:10:41295 return true;
296 }
brianderson@chromium.org3dc0c772014-04-26 10:06:05297
sunnypsda928f0a2016-10-08 00:32:53298 BeginImplFrameWithDeadline(args);
mithroc34fc0b12014-09-30 09:10:41299 return true;
brianderson@chromium.org97e9ccd62014-04-12 01:07:15300}
301
sunnyps7d073dc2015-04-16 23:29:12302void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) {
303 state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames);
304 ProcessScheduledActions();
305}
306
danakjc7afae52017-06-20 21:12:41307void Scheduler::OnDrawForLayerTreeFrameSink(bool resourceless_software_draw) {
sunnypseab5ac92015-04-02 20:26:13308 DCHECK(settings_.using_synchronous_renderer_compositor);
309 DCHECK_EQ(state_machine_.begin_impl_frame_state(),
310 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
sunnypsbf106542016-07-14 00:22:38311 DCHECK(begin_impl_frame_deadline_task_.IsCancelled());
sunnypseab5ac92015-04-02 20:26:13312
liushouqune5874ae2016-07-05 10:39:32313 state_machine_.SetResourcelessSoftwareDraw(resourceless_software_draw);
sunnypseab5ac92015-04-02 20:26:13314 state_machine_.OnBeginImplFrameDeadline();
315 ProcessScheduledActions();
316
317 state_machine_.OnBeginImplFrameIdle();
318 ProcessScheduledActions();
liushouqune5874ae2016-07-05 10:39:32319 state_machine_.SetResourcelessSoftwareDraw(false);
sunnypseab5ac92015-04-02 20:26:13320}
321
sunnypsb0fa1213d2017-04-20 20:53:31322void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) {
Sunny Sachanandani4eab04822017-05-06 01:22:24323 // The storage for |args| is owned by the missed begin frame task. Therefore
324 // save |args| before cancelling the task either here or in the deadline.
325 BeginFrameArgs adjusted_args = args;
326 // Cancel the missed begin frame task in case the BFS sends a begin frame
327 // before the missed frame task runs.
328 missed_begin_frame_task_.Cancel();
sunnypsda928f0a2016-10-08 00:32:53329
enneff408182016-10-14 20:15:20330 base::TimeTicks now = Now();
331
sunnypsda928f0a2016-10-08 00:32:53332 // Discard missed begin frames if they are too late.
Sunny Sachanandani4eab04822017-05-06 01:22:24333 if (adjusted_args.type == BeginFrameArgs::MISSED &&
334 now > adjusted_args.deadline) {
sunnyps73f04652017-04-15 01:46:45335 skipped_last_frame_missed_exceeded_deadline_ = true;
Sunny Sachanandani4eab04822017-05-06 01:22:24336 SendBeginFrameAck(adjusted_args, kBeginFrameSkipped);
sunnypsda928f0a2016-10-08 00:32:53337 return;
338 }
339
sunnyps73f04652017-04-15 01:46:45340 skipped_last_frame_missed_exceeded_deadline_ = false;
341
Sunny Sachanandani4eab04822017-05-06 01:22:24342 // Run the previous deadline if any.
343 if (state_machine_.begin_impl_frame_state() ==
344 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) {
345 OnBeginImplFrameDeadline();
346 // We may not need begin frames any longer.
347 if (!observing_begin_frame_source_) {
348 // We need to confirm the ignored BeginFrame, since we don't have updates.
349 // To persist the confirmation for future BeginFrameAcks, we let the state
350 // machine know about the BeginFrame.
351 state_machine_.OnBeginFrameDroppedNotObserving(args.source_id,
352 args.sequence_number);
353 SendBeginFrameAck(adjusted_args, kBeginFrameSkipped);
354 return;
355 }
356 }
357 DCHECK_EQ(state_machine_.begin_impl_frame_state(),
358 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
359
sunnyps79f33c32015-04-23 20:56:38360 bool main_thread_is_in_high_latency_mode =
briandersonfa55c282015-07-21 18:07:26361 state_machine_.main_thread_missed_last_deadline();
sunnyps79f33c32015-04-23 20:56:38362 TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args",
Sunny Sachanandani4eab04822017-05-06 01:22:24363 adjusted_args.AsValue(), "main_thread_missed_last_deadline",
sunnyps79f33c32015-04-23 20:56:38364 main_thread_is_in_high_latency_mode);
365 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
366 "MainThreadLatency", main_thread_is_in_high_latency_mode);
367
Sunny Sachanandani4eab04822017-05-06 01:22:24368 DCHECK_EQ(state_machine_.begin_impl_frame_state(),
369 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
370
briandersonc9f50352015-06-24 03:38:58371 adjusted_args.deadline -= compositor_timing_history_->DrawDurationEstimate();
brianderson17ec1e92015-09-03 22:16:49372 adjusted_args.deadline -= kDeadlineFudgeFactor;
sunnyps79f33c32015-04-23 20:56:38373
brianderson42ef946a2015-11-19 02:36:40374 base::TimeDelta bmf_start_to_activate =
375 compositor_timing_history_
376 ->BeginMainFrameStartToCommitDurationEstimate() +
377 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() +
378 compositor_timing_history_->ActivateDurationEstimate();
379
brianderson185afcd2016-02-06 00:46:21380 base::TimeDelta bmf_to_activate_estimate_critical =
brianderson42ef946a2015-11-19 02:36:40381 bmf_start_to_activate +
382 compositor_timing_history_->BeginMainFrameQueueDurationCriticalEstimate();
383
brianderson42ef946a2015-11-19 02:36:40384 state_machine_.SetCriticalBeginMainFrameToActivateIsFast(
sunnypsda928f0a2016-10-08 00:32:53385 bmf_to_activate_estimate_critical < adjusted_args.interval);
brianderson42ef946a2015-11-19 02:36:40386
387 // Update the BeginMainFrame args now that we know whether the main
388 // thread will be on the critical path or not.
389 begin_main_frame_args_ = adjusted_args;
390 begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority();
391
brianderson185afcd2016-02-06 00:46:21392 base::TimeDelta bmf_to_activate_estimate = bmf_to_activate_estimate_critical;
brianderson42ef946a2015-11-19 02:36:40393 if (!begin_main_frame_args_.on_critical_path) {
brianderson185afcd2016-02-06 00:46:21394 bmf_to_activate_estimate =
brianderson42ef946a2015-11-19 02:36:40395 bmf_start_to_activate +
396 compositor_timing_history_
397 ->BeginMainFrameQueueDurationNotCriticalEstimate();
brianderson42ef946a2015-11-19 02:36:40398 }
399
brianderson185afcd2016-02-06 00:46:21400 bool can_activate_before_deadline =
401 CanBeginMainFrameAndActivateBeforeDeadline(adjusted_args,
enneff408182016-10-14 20:15:20402 bmf_to_activate_estimate, now);
brianderson185afcd2016-02-06 00:46:21403
brianderson42ef946a2015-11-19 02:36:40404 if (ShouldRecoverMainLatency(adjusted_args, can_activate_before_deadline)) {
brianderson6d50e7a2015-07-10 02:29:07405 TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency",
406 TRACE_EVENT_SCOPE_THREAD);
sunnyps79f33c32015-04-23 20:56:38407 state_machine_.SetSkipNextBeginMainFrameToReduceLatency();
brianderson42ef946a2015-11-19 02:36:40408 } else if (ShouldRecoverImplLatency(adjusted_args,
409 can_activate_before_deadline)) {
brianderson6d50e7a2015-07-10 02:29:07410 TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency",
411 TRACE_EVENT_SCOPE_THREAD);
sunnyps73f04652017-04-15 01:46:45412 skipped_last_frame_to_reduce_latency_ = true;
eseckler37da9b32017-02-24 23:36:56413 SendBeginFrameAck(begin_main_frame_args_, kBeginFrameSkipped);
brianderson6d50e7a2015-07-10 02:29:07414 return;
sunnyps79f33c32015-04-23 20:56:38415 }
416
sunnyps73f04652017-04-15 01:46:45417 skipped_last_frame_to_reduce_latency_ = false;
418
stanisc0828f5b2017-03-17 03:38:38419 BeginImplFrame(adjusted_args, now);
sunnypseab5ac92015-04-02 20:26:13420}
421
422void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) {
sunnyps79f33c32015-04-23 20:56:38423 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args",
424 args.AsValue());
brianderson42ef946a2015-11-19 02:36:40425 // The main thread currently can't commit before we draw with the
426 // synchronous compositor, so never consider the BeginMainFrame fast.
427 state_machine_.SetCriticalBeginMainFrameToActivateIsFast(false);
428 begin_main_frame_args_ = args;
429 begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority();
430
stanisc0828f5b2017-03-17 03:38:38431 BeginImplFrame(args, Now());
briandersond32468d2015-11-25 22:08:55432 compositor_timing_history_->WillFinishImplFrame(
433 state_machine_.needs_redraw());
sunnypseab5ac92015-04-02 20:26:13434 FinishImplFrame();
435}
436
437void Scheduler::FinishImplFrame() {
438 state_machine_.OnBeginImplFrameIdle();
439 ProcessScheduledActions();
440
mithro51693e382015-05-07 23:52:41441 client_->DidFinishImplFrame();
Sunny Sachanandani4eab04822017-05-06 01:22:24442 SendBeginFrameAck(begin_main_frame_args_, kBeginFrameFinished);
mithro0bdb49d2015-05-27 13:08:01443 begin_impl_frame_tracker_.Finish();
sunnypseab5ac92015-04-02 20:26:13444}
445
eseckler37da9b32017-02-24 23:36:56446void Scheduler::SendBeginFrameAck(const BeginFrameArgs& args,
447 BeginFrameResult result) {
eseckler37da9b32017-02-24 23:36:56448 bool did_submit = false;
esecklerca6d7cb72017-05-26 11:33:47449 if (result == kBeginFrameFinished)
eseckler37da9b32017-02-24 23:36:56450 did_submit = state_machine_.did_submit_in_last_frame();
esecklerca6d7cb72017-05-26 11:33:47451
452 if (!did_submit) {
453 uint64_t latest_confirmed_sequence_number =
454 BeginFrameArgs::kInvalidFrameNumber;
455 if (args.source_id == state_machine_.begin_frame_source_id()) {
456 latest_confirmed_sequence_number =
457 state_machine_
458 .last_begin_frame_sequence_number_compositor_frame_was_fresh();
459 }
460
461 client_->DidNotProduceFrame(
462 BeginFrameAck(args.source_id, args.sequence_number,
463 latest_confirmed_sequence_number, did_submit));
eseckler37da9b32017-02-24 23:36:56464 }
465
esecklerca6d7cb72017-05-26 11:33:47466 if (begin_frame_source_)
467 begin_frame_source_->DidFinishFrame(this);
eseckler37da9b32017-02-24 23:36:56468}
469
brianderson@chromium.org97e9ccd62014-04-12 01:07:15470// BeginImplFrame starts a compositor frame that will wait up until a deadline
471// for a BeginMainFrame+activation to complete before it times out and draws
472// any asynchronous animation and scroll/pinch updates.
stanisc0828f5b2017-03-17 03:38:38473void Scheduler::BeginImplFrame(const BeginFrameArgs& args,
474 base::TimeTicks now) {
enne@chromium.orgaeeedad2014-08-22 18:16:22475 DCHECK_EQ(state_machine_.begin_impl_frame_state(),
476 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
sunnypsbf106542016-07-14 00:22:38477 DCHECK(begin_impl_frame_deadline_task_.IsCancelled());
danakjc7afae52017-06-20 21:12:41478 DCHECK(state_machine_.HasInitializedLayerTreeFrameSink());
skyostil@chromium.org6d5aa6f2014-03-04 21:42:17479
mithro0bdb49d2015-05-27 13:08:01480 begin_impl_frame_tracker_.Start(args);
eseckler37da9b32017-02-24 23:36:56481 state_machine_.OnBeginImplFrame(args.source_id, args.sequence_number);
caseq@chromium.orgd73094482014-02-13 21:28:28482 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_);
briandersond32468d2015-11-25 22:08:55483 compositor_timing_history_->WillBeginImplFrame(
stanisc0828f5b2017-03-17 03:38:38484 state_machine_.NewActiveTreeLikely(), args.frame_time, args.type, now);
mithro0bdb49d2015-05-27 13:08:01485 client_->WillBeginImplFrame(begin_impl_frame_tracker_.Current());
dominikg@chromium.org56ec7302013-11-08 00:51:45486
enne@chromium.orga8335ac02013-03-16 09:15:12487 ProcessScheduledActions();
skyostil@chromium.org46cc0d62014-03-11 00:35:16488}
489
sunnyps5d8bb1d22014-12-08 20:48:10490void Scheduler::ScheduleBeginImplFrameDeadline() {
sunnyps977116d2014-11-26 20:33:30491 // The synchronous compositor does not post a deadline task.
492 DCHECK(!settings_.using_synchronous_renderer_compositor);
brianderson@chromium.org425e5332013-09-21 04:10:03493
Sunny Sachanandani4eab04822017-05-06 01:22:24494 begin_impl_frame_deadline_task_.Cancel();
495 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_);
boliu@chromium.org48abf812014-03-20 17:41:59496
sunnyps5d8bb1d22014-12-08 20:48:10497 begin_impl_frame_deadline_mode_ =
498 state_machine_.CurrentBeginImplFrameDeadlineMode();
sunnyps5d8bb1d22014-12-08 20:48:10499 switch (begin_impl_frame_deadline_mode_) {
sunnypseab5ac92015-04-02 20:26:13500 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE:
501 // No deadline.
502 return;
sunnyps5d8bb1d22014-12-08 20:48:10503 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE:
504 // We are ready to draw a new active tree immediately.
505 // We don't use Now() here because it's somewhat expensive to call.
Sunny Sachanandanibd1281da2017-04-19 23:01:24506 deadline_ = base::TimeTicks();
sunnyps5d8bb1d22014-12-08 20:48:10507 break;
508 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR:
509 // We are animating on the impl thread but we can wait for some time.
Sunny Sachanandanibd1281da2017-04-19 23:01:24510 deadline_ = begin_impl_frame_tracker_.Current().deadline;
sunnyps5d8bb1d22014-12-08 20:48:10511 break;
512 case SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE:
513 // We are blocked for one reason or another and we should wait.
514 // TODO(brianderson): Handle long deadlines (that are past the next
515 // frame's frame time) properly instead of using this hack.
Sunny Sachanandanibd1281da2017-04-19 23:01:24516 deadline_ = begin_impl_frame_tracker_.Current().frame_time +
517 begin_impl_frame_tracker_.Current().interval;
sunnyps5d8bb1d22014-12-08 20:48:10518 break;
weiliangc8dac5a62015-04-02 06:12:35519 case SchedulerStateMachine::
520 BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW:
521 // We are blocked because we are waiting for ReadyToDraw signal. We would
522 // post deadline after we received ReadyToDraw singal.
523 TRACE_EVENT1("cc", "Scheduler::ScheduleBeginImplFrameDeadline",
524 "deadline_mode", "blocked_on_ready_to_draw");
525 return;
sunnyps5d8bb1d22014-12-08 20:48:10526 }
527
sunnypseab5ac92015-04-02 20:26:13528 TRACE_EVENT2("cc", "Scheduler::ScheduleBeginImplFrameDeadline", "mode",
529 SchedulerStateMachine::BeginImplFrameDeadlineModeToString(
530 begin_impl_frame_deadline_mode_),
Sunny Sachanandanibd1281da2017-04-19 23:01:24531 "deadline", deadline_);
sunnyps5d8bb1d22014-12-08 20:48:10532
Sunny Sachanandanibd1281da2017-04-19 23:01:24533 deadline_scheduled_at_ = Now();
534 base::TimeDelta delta =
535 std::max(deadline_ - deadline_scheduled_at_, base::TimeDelta());
enne@chromium.orgaeeedad2014-08-22 18:16:22536 task_runner_->PostDelayedTask(
brianderson@chromium.orgbeed86c2014-04-04 04:34:28537 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta);
brianderson@chromium.org425e5332013-09-21 04:10:03538}
539
sunnypseab5ac92015-04-02 20:26:13540void Scheduler::ScheduleBeginImplFrameDeadlineIfNeeded() {
sunnypsb6ee9a212015-04-02 00:51:03541 if (settings_.using_synchronous_renderer_compositor)
542 return;
543
sunnyps5d8bb1d22014-12-08 20:48:10544 if (state_machine_.begin_impl_frame_state() !=
545 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
546 return;
547
sunnypseab5ac92015-04-02 20:26:13548 if (begin_impl_frame_deadline_mode_ ==
549 state_machine_.CurrentBeginImplFrameDeadlineMode() &&
sunnypsbf106542016-07-14 00:22:38550 !begin_impl_frame_deadline_task_.IsCancelled()) {
sunnypseab5ac92015-04-02 20:26:13551 return;
sunnypsbf106542016-07-14 00:22:38552 }
sunnypseab5ac92015-04-02 20:26:13553
554 ScheduleBeginImplFrameDeadline();
sunnyps5d8bb1d22014-12-08 20:48:10555}
556
dominikg@chromium.org87379cde2013-10-21 23:19:52557void Scheduler::OnBeginImplFrameDeadline() {
miletusfed8c43b2015-01-26 20:04:52558 TRACE_EVENT0("cc,benchmark", "Scheduler::OnBeginImplFrameDeadline");
brianderson@chromium.orgbeed86c2014-04-04 04:34:28559 begin_impl_frame_deadline_task_.Cancel();
brianderson@chromium.org1d8571b52014-02-08 02:33:58560 // We split the deadline actions up into two phases so the state machine
561 // has a chance to trigger actions that should occur durring and after
562 // the deadline separately. For example:
563 // * Sending the BeginMainFrame will not occur after the deadline in
564 // order to wait for more user-input before starting the next commit.
565 // * Creating a new OuputSurface will not occur during the deadline in
566 // order to allow the state machine to "settle" first.
briandersond32468d2015-11-25 22:08:55567 compositor_timing_history_->WillFinishImplFrame(
568 state_machine_.needs_redraw());
dominikg@chromium.org7d6685512013-10-19 18:04:38569 state_machine_.OnBeginImplFrameDeadline();
brianderson@chromium.org425e5332013-09-21 04:10:03570 ProcessScheduledActions();
sunnypseab5ac92015-04-02 20:26:13571 FinishImplFrame();
brianderson@chromium.org049fc7a2013-06-18 12:32:35572}
573
danakj9d124422016-10-14 03:15:08574void Scheduler::DrawIfPossible() {
briandersond32468d2015-11-25 22:08:55575 bool drawing_with_new_active_tree =
khushalsagarab73d502017-02-24 02:26:46576 state_machine_.active_tree_needs_first_draw() &&
577 !state_machine_.previous_pending_tree_was_impl_side();
briandersonbb917dd2016-02-20 05:21:14578 bool main_thread_missed_last_deadline =
579 state_machine_.main_thread_missed_last_deadline();
brianderson68749812015-07-07 22:39:39580 compositor_timing_history_->WillDraw();
briandersond32468d2015-11-25 22:08:55581 state_machine_.WillDraw();
danakj9d124422016-10-14 03:15:08582 DrawResult result = client_->ScheduledActionDrawIfPossible();
briandersonf677d492015-11-25 03:48:19583 state_machine_.DidDraw(result);
briandersonbb917dd2016-02-20 05:21:14584 compositor_timing_history_->DidDraw(
585 drawing_with_new_active_tree, main_thread_missed_last_deadline,
586 begin_impl_frame_tracker_.DangerousMethodCurrentOrLast().frame_time);
briandersonc9f50352015-06-24 03:38:58587}
588
danakj9d124422016-10-14 03:15:08589void Scheduler::DrawForced() {
briandersond32468d2015-11-25 22:08:55590 bool drawing_with_new_active_tree =
khushalsagarab73d502017-02-24 02:26:46591 state_machine_.active_tree_needs_first_draw() &&
592 !state_machine_.previous_pending_tree_was_impl_side();
briandersonbb917dd2016-02-20 05:21:14593 bool main_thread_missed_last_deadline =
594 state_machine_.main_thread_missed_last_deadline();
brianderson68749812015-07-07 22:39:39595 compositor_timing_history_->WillDraw();
briandersond32468d2015-11-25 22:08:55596 state_machine_.WillDraw();
danakj9d124422016-10-14 03:15:08597 DrawResult result = client_->ScheduledActionDrawForced();
briandersonf677d492015-11-25 03:48:19598 state_machine_.DidDraw(result);
briandersonbb917dd2016-02-20 05:21:14599 compositor_timing_history_->DidDraw(
600 drawing_with_new_active_tree, main_thread_missed_last_deadline,
601 begin_impl_frame_tracker_.DangerousMethodCurrentOrLast().frame_time);
brianderson@chromium.org63e61892013-09-07 01:47:29602}
603
simonhongc6309f792015-01-31 15:47:15604void Scheduler::SetDeferCommits(bool defer_commits) {
sunnypsbf106542016-07-14 00:22:38605 TRACE_EVENT1("cc", "Scheduler::SetDeferCommits", "defer_commits",
606 defer_commits);
simonhongc6309f792015-01-31 15:47:15607 state_machine_.SetDeferCommits(defer_commits);
608 ProcessScheduledActions();
609}
610
Dan Elphick95929fd2017-06-13 09:15:07611void Scheduler::SetMainThreadWantsBeginMainFrameNotExpected(bool new_state) {
612 state_machine_.SetMainThreadWantsBeginMainFrameNotExpectedMessages(new_state);
613 ProcessScheduledActions();
614}
615
enne@chromium.orga8335ac02013-03-16 09:15:12616void Scheduler::ProcessScheduledActions() {
sunnypsda928f0a2016-10-08 00:32:53617 // Do not perform actions during compositor shutdown.
618 if (stopped_)
619 return;
620
enne@chromium.orga8335ac02013-03-16 09:15:12621 // We do not allow ProcessScheduledActions to be recursive.
622 // The top-level call will iteratively execute the next action for us anyway.
623 if (inside_process_scheduled_actions_)
624 return;
rogerm8aeea932017-04-19 21:26:57625
enne@chromium.orga8335ac02013-03-16 09:15:12626 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true);
jamesr@chromium.org94f206c12012-08-25 00:09:14627
brianderson@chromium.org224b4522013-08-21 09:58:30628 SchedulerStateMachine::Action action;
629 do {
630 action = state_machine_.NextAction();
631 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
sunnypsbf106542016-07-14 00:22:38632 "SchedulerStateMachine", "state", AsValue());
633 base::AutoReset<SchedulerStateMachine::Action> mark_inside_action(
634 &inside_action_, action);
enne@chromium.orga8335ac02013-03-16 09:15:12635 switch (action) {
636 case SchedulerStateMachine::ACTION_NONE:
637 break;
robliao27728e62015-03-21 07:39:34638 case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME:
brianderson21aef162015-11-11 05:12:23639 compositor_timing_history_->WillBeginMainFrame(
briandersonbb917dd2016-02-20 05:21:14640 begin_main_frame_args_.on_critical_path,
stanisc0828f5b2017-03-17 03:38:38641 begin_main_frame_args_.frame_time);
brianderson1f154ea2015-08-13 22:55:48642 state_machine_.WillSendBeginMainFrame();
brianderson21aef162015-11-11 05:12:23643 // TODO(brianderson): Pass begin_main_frame_args_ directly to client.
brianderson266dc3a2015-11-12 03:16:40644 client_->ScheduledActionSendBeginMainFrame(begin_main_frame_args_);
enne@chromium.orga8335ac02013-03-16 09:15:12645 break;
delphick9db74aa2017-05-05 10:20:49646 case SchedulerStateMachine::ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_SENT:
647 state_machine_.WillNotifyBeginMainFrameNotSent();
Dan Elphick99f685d2017-06-15 11:13:51648 // If SendBeginMainFrameNotExpectedSoon was not previously sent by
649 // BeginImplFrameNotExpectedSoon (because the messages were not required
650 // at that time), then send it now.
651 if (!observing_begin_frame_source_) {
652 client_->SendBeginMainFrameNotExpectedSoon();
653 } else {
654 BeginMainFrameNotExpectedUntil(begin_main_frame_args_.frame_time +
655 begin_main_frame_args_.interval);
656 }
delphick9db74aa2017-05-05 10:20:49657 break;
robliaodd25f5b2015-02-27 23:34:02658 case SchedulerStateMachine::ACTION_COMMIT: {
brianderson1f154ea2015-08-13 22:55:48659 bool commit_has_no_updates = false;
660 state_machine_.WillCommit(commit_has_no_updates);
enne@chromium.orga8335ac02013-03-16 09:15:12661 client_->ScheduledActionCommit();
662 break;
robliaodd25f5b2015-02-27 23:34:02663 }
robliao27728e62015-03-21 07:39:34664 case SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE:
brianderson68749812015-07-07 22:39:39665 compositor_timing_history_->WillActivate();
brianderson1f154ea2015-08-13 22:55:48666 state_machine_.WillActivate();
alokp@chromium.orgdea398372014-07-07 19:37:19667 client_->ScheduledActionActivateSyncTree();
brianderson68749812015-07-07 22:39:39668 compositor_timing_history_->DidActivate();
enne@chromium.orga8335ac02013-03-16 09:15:12669 break;
khushalsagarab73d502017-02-24 02:26:46670 case SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION:
671 state_machine_.WillPerformImplSideInvalidation();
672 client_->ScheduledActionPerformImplSideInvalidation();
673 break;
danakj9d124422016-10-14 03:15:08674 case SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE:
675 DrawIfPossible();
enne@chromium.orga8335ac02013-03-16 09:15:12676 break;
danakj9d124422016-10-14 03:15:08677 case SchedulerStateMachine::ACTION_DRAW_FORCED:
678 DrawForced();
enne@chromium.orga8335ac02013-03-16 09:15:12679 break;
danakj9d124422016-10-14 03:15:08680 case SchedulerStateMachine::ACTION_DRAW_ABORT: {
brianderson@chromium.org1ef04b22013-08-23 05:47:16681 // No action is actually performed, but this allows the state machine to
briandersonf677d492015-11-25 03:48:19682 // drain the pipeline without actually drawing.
danakj9d124422016-10-14 03:15:08683 state_machine_.AbortDraw();
briandersonbb917dd2016-02-20 05:21:14684 compositor_timing_history_->DrawAborted();
brianderson@chromium.org1ef04b22013-08-23 05:47:16685 break;
brianderson1f154ea2015-08-13 22:55:48686 }
danakjc7afae52017-06-20 21:12:41687 case SchedulerStateMachine::ACTION_BEGIN_LAYER_TREE_FRAME_SINK_CREATION:
688 state_machine_.WillBeginLayerTreeFrameSinkCreation();
689 client_->ScheduledActionBeginLayerTreeFrameSinkCreation();
enne@chromium.orga8335ac02013-03-16 09:15:12690 break;
robliao27728e62015-03-21 07:39:34691 case SchedulerStateMachine::ACTION_PREPARE_TILES:
brianderson1f154ea2015-08-13 22:55:48692 state_machine_.WillPrepareTiles();
vmiura59ea9b4042014-12-09 20:50:39693 client_->ScheduledActionPrepareTiles();
epenner@chromium.orgc48536a52013-09-14 00:02:08694 break;
danakjc7afae52017-06-20 21:12:41695 case SchedulerStateMachine::ACTION_INVALIDATE_LAYER_TREE_FRAME_SINK: {
696 state_machine_.WillInvalidateLayerTreeFrameSink();
697 client_->ScheduledActionInvalidateLayerTreeFrameSink();
sunnypseab5ac92015-04-02 20:26:13698 break;
699 }
brianderson@chromium.orgd7223942012-09-26 22:43:33700 }
brianderson@chromium.org224b4522013-08-21 09:58:30701 } while (action != SchedulerStateMachine::ACTION_NONE);
jamesr@chromium.org94f206c12012-08-25 00:09:14702
sunnypseab5ac92015-04-02 20:26:13703 ScheduleBeginImplFrameDeadlineIfNeeded();
sunnyps32f01252015-03-19 03:50:29704 SetupNextBeginFrameIfNeeded();
jamesr@chromium.org94f206c12012-08-25 00:09:14705}
706
danakj60bc3bc2016-04-09 00:24:48707std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
708Scheduler::AsValue() const {
sunnyps73f04652017-04-15 01:46:45709 auto state = base::MakeUnique<base::trace_event::TracedValue>();
710 AsValueInto(state.get());
711 return std::move(state);
712}
713
714void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const {
Sunny Sachanandani4eab04822017-05-06 01:22:24715 base::TimeTicks now = Now();
716
yurys@chromium.orgd12aa932014-08-01 13:10:38717 state->BeginDictionary("state_machine");
sunnyps73f04652017-04-15 01:46:45718 state_machine_.AsValueInto(state);
yurys@chromium.orgd12aa932014-08-01 13:10:38719 state->EndDictionary();
mithroc34fc0b12014-09-30 09:10:41720
enneb9bf3772016-03-16 21:51:11721 state->SetBoolean("observing_begin_frame_source",
722 observing_begin_frame_source_);
brianderson1545de02015-06-05 22:05:44723 state->SetBoolean("begin_impl_frame_deadline_task",
yurys@chromium.orgd12aa932014-08-01 13:10:38724 !begin_impl_frame_deadline_task_.IsCancelled());
sunnypsda928f0a2016-10-08 00:32:53725 state->SetBoolean("missed_begin_frame_task",
726 !missed_begin_frame_task_.IsCancelled());
sunnyps73f04652017-04-15 01:46:45727 state->SetBoolean("skipped_last_frame_missed_exceeded_deadline",
728 skipped_last_frame_missed_exceeded_deadline_);
729 state->SetBoolean("skipped_last_frame_to_reduce_latency",
730 skipped_last_frame_to_reduce_latency_);
brianderson1545de02015-06-05 22:05:44731 state->SetString("inside_action",
732 SchedulerStateMachine::ActionToString(inside_action_));
sunnyps73f04652017-04-15 01:46:45733 state->SetString("begin_impl_frame_deadline_mode",
brianderson6d50e7a2015-07-10 02:29:07734 SchedulerStateMachine::BeginImplFrameDeadlineModeToString(
735 begin_impl_frame_deadline_mode_));
sunnyps73f04652017-04-15 01:46:45736
Sunny Sachanandanibd1281da2017-04-19 23:01:24737 state->SetDouble("deadline_ms",
738 (deadline_ - base::TimeTicks()).InMillisecondsF());
739 state->SetDouble(
740 "deadline_scheduled_at_ms",
741 (deadline_scheduled_at_ - base::TimeTicks()).InMillisecondsF());
742
743 state->SetDouble("now_ms", (Now() - base::TimeTicks()).InMillisecondsF());
744 state->SetDouble("now_to_deadline_ms", (deadline_ - Now()).InMillisecondsF());
745 state->SetDouble("now_to_deadline_scheduled_at_ms",
746 (deadline_scheduled_at_ - Now()).InMillisecondsF());
747
Sunny Sachanandani4eab04822017-05-06 01:22:24748 state->BeginDictionary("begin_impl_frame_args");
749 begin_impl_frame_tracker_.AsValueInto(now, state);
yurys@chromium.orgd12aa932014-08-01 13:10:38750 state->EndDictionary();
skyostil@chromium.org5c58f222014-03-07 03:34:09751
sunnyps73f04652017-04-15 01:46:45752 state->BeginDictionary("begin_frame_observer_state");
753 BeginFrameObserverBase::AsValueInto(state);
754 state->EndDictionary();
755
756 if (begin_frame_source_) {
757 state->BeginDictionary("begin_frame_source_state");
758 begin_frame_source_->AsValueInto(state);
759 state->EndDictionary();
760 }
761
briandersonc9f50352015-06-24 03:38:58762 state->BeginDictionary("compositor_timing_history");
sunnyps73f04652017-04-15 01:46:45763 compositor_timing_history_->AsValueInto(state);
yurys@chromium.orgd12aa932014-08-01 13:10:38764 state->EndDictionary();
skyostil@chromium.org5c58f222014-03-07 03:34:09765}
766
brianderson68749812015-07-07 22:39:39767void Scheduler::UpdateCompositorTimingHistoryRecordingEnabled() {
768 compositor_timing_history_->SetRecordingEnabled(
danakjc7afae52017-06-20 21:12:41769 state_machine_.HasInitializedLayerTreeFrameSink() &&
danakj1120f4c2016-09-15 02:05:32770 state_machine_.visible());
brianderson68749812015-07-07 22:39:39771}
772
brianderson42ef946a2015-11-19 02:36:40773bool Scheduler::ShouldRecoverMainLatency(
774 const BeginFrameArgs& args,
775 bool can_activate_before_deadline) const {
brianderson6d50e7a2015-07-10 02:29:07776 DCHECK(!settings_.using_synchronous_renderer_compositor);
mithro0bdb49d2015-05-27 13:08:01777
enneeb16f562016-09-19 21:46:51778 if (!settings_.enable_latency_recovery)
779 return false;
780
brianderson185afcd2016-02-06 00:46:21781 // The main thread is in a low latency mode and there's no need to recover.
briandersonfa55c282015-07-21 18:07:26782 if (!state_machine_.main_thread_missed_last_deadline())
brianderson6d50e7a2015-07-10 02:29:07783 return false;
784
785 // When prioritizing impl thread latency, we currently put the
786 // main thread in a high latency mode. Don't try to fight it.
brianderson42ef946a2015-11-19 02:36:40787 if (state_machine_.ImplLatencyTakesPriority())
brianderson6d50e7a2015-07-10 02:29:07788 return false;
789
brianderson42ef946a2015-11-19 02:36:40790 return can_activate_before_deadline;
brianderson6d50e7a2015-07-10 02:29:07791}
792
brianderson42ef946a2015-11-19 02:36:40793bool Scheduler::ShouldRecoverImplLatency(
794 const BeginFrameArgs& args,
795 bool can_activate_before_deadline) const {
brianderson6d50e7a2015-07-10 02:29:07796 DCHECK(!settings_.using_synchronous_renderer_compositor);
797
enneeb16f562016-09-19 21:46:51798 if (!settings_.enable_latency_recovery)
799 return false;
800
brianderson16a5cb22015-07-11 00:39:20801 // Disable impl thread latency recovery when using the unthrottled
802 // begin frame source since we will always get a BeginFrame before
803 // the swap ack and our heuristics below will not work.
ennee292bdc2016-09-15 19:57:15804 if (begin_frame_source_ && !begin_frame_source_->IsThrottled())
brianderson16a5cb22015-07-11 00:39:20805 return false;
806
brianderson6d50e7a2015-07-10 02:29:07807 // If we are swap throttled at the BeginFrame, that means the impl thread is
808 // very likely in a high latency mode.
danakj9d124422016-10-14 03:15:08809 bool impl_thread_is_likely_high_latency = state_machine_.IsDrawThrottled();
brianderson6d50e7a2015-07-10 02:29:07810 if (!impl_thread_is_likely_high_latency)
811 return false;
812
813 // The deadline may be in the past if our draw time is too long.
814 bool can_draw_before_deadline = args.frame_time < args.deadline;
815
816 // When prioritizing impl thread latency, the deadline doesn't wait
817 // for the main thread.
brianderson42ef946a2015-11-19 02:36:40818 if (state_machine_.ImplLatencyTakesPriority())
brianderson6d50e7a2015-07-10 02:29:07819 return can_draw_before_deadline;
820
821 // If we only have impl-side updates, the deadline doesn't wait for
822 // the main thread.
823 if (state_machine_.OnlyImplSideUpdatesExpected())
824 return can_draw_before_deadline;
825
826 // If we get here, we know the main thread is in a low-latency mode relative
827 // to the impl thread. In this case, only try to also recover impl thread
828 // latency if both the main and impl threads can run serially before the
829 // deadline.
brianderson42ef946a2015-11-19 02:36:40830 return can_activate_before_deadline;
brianderson6d50e7a2015-07-10 02:29:07831}
832
brianderson42ef946a2015-11-19 02:36:40833bool Scheduler::CanBeginMainFrameAndActivateBeforeDeadline(
834 const BeginFrameArgs& args,
enneff408182016-10-14 20:15:20835 base::TimeDelta bmf_to_activate_estimate,
836 base::TimeTicks now) const {
dominikg@chromium.org56ec7302013-11-08 00:51:45837 // Check if the main thread computation and commit can be finished before the
838 // impl thread's deadline.
enneff408182016-10-14 20:15:20839 base::TimeTicks estimated_draw_time = now + bmf_to_activate_estimate;
dominikg@chromium.org56ec7302013-11-08 00:51:45840
mithro0bdb49d2015-05-27 13:08:01841 return estimated_draw_time < args.deadline;
dominikg@chromium.org56ec7302013-11-08 00:51:45842}
843
simonhong@chromium.orgeb2d2abc2014-03-07 16:19:59844bool Scheduler::IsBeginMainFrameSentOrStarted() const {
mithroe77254b32015-07-22 09:36:01845 return (state_machine_.begin_main_frame_state() ==
846 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT ||
847 state_machine_.begin_main_frame_state() ==
848 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_STARTED);
simonhong@chromium.orgeb2d2abc2014-03-07 16:19:59849}
850
esecklerdde665f2017-03-07 20:19:27851BeginFrameAck Scheduler::CurrentBeginFrameAckForActiveTree() const {
852 return BeginFrameAck(
853 begin_main_frame_args_.source_id, begin_main_frame_args_.sequence_number,
854 state_machine_.last_begin_frame_sequence_number_active_tree_was_fresh(),
esecklerdcb90782017-03-28 09:17:56855 true);
esecklerdde665f2017-03-07 20:19:27856}
857
tfarina@chromium.org0ef67472012-10-11 21:33:39858} // namespace cc