1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cc/scheduler/scheduler_state_machine.h"
6
7 #include "base/debug/trace_event.h"
8 #include "base/format_macros.h"
9 #include "base/logging.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/values.h"
12 #include "ui/gfx/frame_time.h"
13
14 namespace cc {
15
SchedulerStateMachine(const SchedulerSettings & settings)16 SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
17 : settings_(settings),
18 output_surface_state_(OUTPUT_SURFACE_LOST),
19 begin_impl_frame_state_(BEGIN_IMPL_FRAME_STATE_IDLE),
20 commit_state_(COMMIT_STATE_IDLE),
21 texture_state_(LAYER_TEXTURE_STATE_UNLOCKED),
22 forced_redraw_state_(FORCED_REDRAW_STATE_IDLE),
23 readback_state_(READBACK_STATE_IDLE),
24 commit_count_(0),
25 current_frame_number_(0),
26 last_frame_number_swap_performed_(-1),
27 last_frame_number_begin_main_frame_sent_(-1),
28 last_frame_number_update_visible_tiles_was_called_(-1),
29 last_frame_number_manage_tiles_called_(-1),
30 consecutive_failed_draws_(0),
31 needs_redraw_(false),
32 needs_manage_tiles_(false),
33 swap_used_incomplete_tile_(false),
34 needs_commit_(false),
35 main_thread_needs_layer_textures_(false),
36 inside_poll_for_anticipated_draw_triggers_(false),
37 visible_(false),
38 can_start_(false),
39 can_draw_(false),
40 has_pending_tree_(false),
41 pending_tree_is_ready_for_activation_(false),
42 active_tree_needs_first_draw_(false),
43 draw_if_possible_failed_(false),
44 did_create_and_initialize_first_output_surface_(false),
45 smoothness_takes_priority_(false),
46 skip_begin_main_frame_to_reduce_latency_(false) {}
47
OutputSurfaceStateToString(OutputSurfaceState state)48 const char* SchedulerStateMachine::OutputSurfaceStateToString(
49 OutputSurfaceState state) {
50 switch (state) {
51 case OUTPUT_SURFACE_ACTIVE:
52 return "OUTPUT_SURFACE_ACTIVE";
53 case OUTPUT_SURFACE_LOST:
54 return "OUTPUT_SURFACE_LOST";
55 case OUTPUT_SURFACE_CREATING:
56 return "OUTPUT_SURFACE_CREATING";
57 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
58 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT";
59 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
60 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION";
61 }
62 NOTREACHED();
63 return "???";
64 }
65
BeginImplFrameStateToString(BeginImplFrameState state)66 const char* SchedulerStateMachine::BeginImplFrameStateToString(
67 BeginImplFrameState state) {
68 switch (state) {
69 case BEGIN_IMPL_FRAME_STATE_IDLE:
70 return "BEGIN_IMPL_FRAME_STATE_IDLE";
71 case BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING:
72 return "BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING";
73 case BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME:
74 return "BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME";
75 case BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE:
76 return "BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE";
77 }
78 NOTREACHED();
79 return "???";
80 }
81
CommitStateToString(CommitState state)82 const char* SchedulerStateMachine::CommitStateToString(CommitState state) {
83 switch (state) {
84 case COMMIT_STATE_IDLE:
85 return "COMMIT_STATE_IDLE";
86 case COMMIT_STATE_FRAME_IN_PROGRESS:
87 return "COMMIT_STATE_FRAME_IN_PROGRESS";
88 case COMMIT_STATE_READY_TO_COMMIT:
89 return "COMMIT_STATE_READY_TO_COMMIT";
90 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW:
91 return "COMMIT_STATE_WAITING_FOR_FIRST_DRAW";
92 }
93 NOTREACHED();
94 return "???";
95 }
96
TextureStateToString(TextureState state)97 const char* SchedulerStateMachine::TextureStateToString(TextureState state) {
98 switch (state) {
99 case LAYER_TEXTURE_STATE_UNLOCKED:
100 return "LAYER_TEXTURE_STATE_UNLOCKED";
101 case LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD:
102 return "LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD";
103 case LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD:
104 return "LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD";
105 }
106 NOTREACHED();
107 return "???";
108 }
109
SynchronousReadbackStateToString(SynchronousReadbackState state)110 const char* SchedulerStateMachine::SynchronousReadbackStateToString(
111 SynchronousReadbackState state) {
112 switch (state) {
113 case READBACK_STATE_IDLE:
114 return "READBACK_STATE_IDLE";
115 case READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME:
116 return "READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME";
117 case READBACK_STATE_WAITING_FOR_COMMIT:
118 return "READBACK_STATE_WAITING_FOR_COMMIT";
119 case READBACK_STATE_WAITING_FOR_ACTIVATION:
120 return "READBACK_STATE_WAITING_FOR_ACTIVATION";
121 case READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK:
122 return "READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK";
123 case READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT:
124 return "READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT";
125 case READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION:
126 return "READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION";
127 }
128 NOTREACHED();
129 return "???";
130 }
131
ForcedRedrawOnTimeoutStateToString(ForcedRedrawOnTimeoutState state)132 const char* SchedulerStateMachine::ForcedRedrawOnTimeoutStateToString(
133 ForcedRedrawOnTimeoutState state) {
134 switch (state) {
135 case FORCED_REDRAW_STATE_IDLE:
136 return "FORCED_REDRAW_STATE_IDLE";
137 case FORCED_REDRAW_STATE_WAITING_FOR_COMMIT:
138 return "FORCED_REDRAW_STATE_WAITING_FOR_COMMIT";
139 case FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION:
140 return "FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION";
141 case FORCED_REDRAW_STATE_WAITING_FOR_DRAW:
142 return "FORCED_REDRAW_STATE_WAITING_FOR_DRAW";
143 }
144 NOTREACHED();
145 return "???";
146 }
147
ActionToString(Action action)148 const char* SchedulerStateMachine::ActionToString(Action action) {
149 switch (action) {
150 case ACTION_NONE:
151 return "ACTION_NONE";
152 case ACTION_SEND_BEGIN_MAIN_FRAME:
153 return "ACTION_SEND_BEGIN_MAIN_FRAME";
154 case ACTION_COMMIT:
155 return "ACTION_COMMIT";
156 case ACTION_UPDATE_VISIBLE_TILES:
157 return "ACTION_UPDATE_VISIBLE_TILES";
158 case ACTION_ACTIVATE_PENDING_TREE:
159 return "ACTION_ACTIVATE_PENDING_TREE";
160 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
161 return "ACTION_DRAW_AND_SWAP_IF_POSSIBLE";
162 case ACTION_DRAW_AND_SWAP_FORCED:
163 return "ACTION_DRAW_AND_SWAP_FORCED";
164 case ACTION_DRAW_AND_SWAP_ABORT:
165 return "ACTION_DRAW_AND_SWAP_ABORT";
166 case ACTION_DRAW_AND_READBACK:
167 return "ACTION_DRAW_AND_READBACK";
168 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
169 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION";
170 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
171 return "ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD";
172 case ACTION_MANAGE_TILES:
173 return "ACTION_MANAGE_TILES";
174 }
175 NOTREACHED();
176 return "???";
177 }
178
AsValue() const179 scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const {
180 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
181
182 scoped_ptr<base::DictionaryValue> major_state(new base::DictionaryValue);
183 major_state->SetString("next_action", ActionToString(NextAction()));
184 major_state->SetString("begin_impl_frame_state",
185 BeginImplFrameStateToString(begin_impl_frame_state_));
186 major_state->SetString("commit_state", CommitStateToString(commit_state_));
187 major_state->SetString("texture_state_",
188 TextureStateToString(texture_state_));
189 major_state->SetString("output_surface_state_",
190 OutputSurfaceStateToString(output_surface_state_));
191 major_state->SetString(
192 "forced_redraw_state",
193 ForcedRedrawOnTimeoutStateToString(forced_redraw_state_));
194 major_state->SetString("readback_state",
195 SynchronousReadbackStateToString(readback_state_));
196 state->Set("major_state", major_state.release());
197
198 scoped_ptr<base::DictionaryValue> timestamps_state(new base::DictionaryValue);
199 base::TimeTicks now = gfx::FrameTime::Now();
200 timestamps_state->SetDouble(
201 "0_interval",
202 last_begin_impl_frame_args_.interval.InMicroseconds() / 1000.0L);
203 timestamps_state->SetDouble(
204 "1_now_to_deadline",
205 (last_begin_impl_frame_args_.deadline - now).InMicroseconds() / 1000.0L);
206 timestamps_state->SetDouble(
207 "2_frame_time_to_now",
208 (now - last_begin_impl_frame_args_.frame_time).InMicroseconds() /
209 1000.0L);
210 timestamps_state->SetDouble(
211 "3_frame_time_to_deadline",
212 (last_begin_impl_frame_args_.deadline -
213 last_begin_impl_frame_args_.frame_time).InMicroseconds() /
214 1000.0L);
215 timestamps_state->SetDouble(
216 "4_now", (now - base::TimeTicks()).InMicroseconds() / 1000.0L);
217 timestamps_state->SetDouble(
218 "5_frame_time",
219 (last_begin_impl_frame_args_.frame_time - base::TimeTicks())
220 .InMicroseconds() /
221 1000.0L);
222 timestamps_state->SetDouble(
223 "6_deadline",
224 (last_begin_impl_frame_args_.deadline - base::TimeTicks())
225 .InMicroseconds() /
226 1000.0L);
227 state->Set("major_timestamps_in_ms", timestamps_state.release());
228
229 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue);
230 minor_state->SetInteger("commit_count", commit_count_);
231 minor_state->SetInteger("current_frame_number", current_frame_number_);
232
233 minor_state->SetInteger("last_frame_number_swap_performed",
234 last_frame_number_swap_performed_);
235 minor_state->SetInteger(
236 "last_frame_number_begin_main_frame_sent",
237 last_frame_number_begin_main_frame_sent_);
238 minor_state->SetInteger(
239 "last_frame_number_update_visible_tiles_was_called",
240 last_frame_number_update_visible_tiles_was_called_);
241
242 minor_state->SetInteger("consecutive_failed_draws",
243 consecutive_failed_draws_);
244 minor_state->SetBoolean("needs_redraw", needs_redraw_);
245 minor_state->SetBoolean("needs_manage_tiles", needs_manage_tiles_);
246 minor_state->SetBoolean("swap_used_incomplete_tile",
247 swap_used_incomplete_tile_);
248 minor_state->SetBoolean("needs_commit", needs_commit_);
249 minor_state->SetBoolean("main_thread_needs_layer_textures",
250 main_thread_needs_layer_textures_);
251 minor_state->SetBoolean("visible", visible_);
252 minor_state->SetBoolean("can_start", can_start_);
253 minor_state->SetBoolean("can_draw", can_draw_);
254 minor_state->SetBoolean("has_pending_tree", has_pending_tree_);
255 minor_state->SetBoolean("pending_tree_is_ready_for_activation",
256 pending_tree_is_ready_for_activation_);
257 minor_state->SetBoolean("active_tree_needs_first_draw",
258 active_tree_needs_first_draw_);
259 minor_state->SetBoolean("draw_if_possible_failed", draw_if_possible_failed_);
260 minor_state->SetBoolean("did_create_and_initialize_first_output_surface",
261 did_create_and_initialize_first_output_surface_);
262 minor_state->SetBoolean("smoothness_takes_priority",
263 smoothness_takes_priority_);
264 minor_state->SetBoolean("main_thread_is_in_high_latency_mode",
265 MainThreadIsInHighLatencyMode());
266 minor_state->SetBoolean("skip_begin_main_frame_to_reduce_latency",
267 skip_begin_main_frame_to_reduce_latency_);
268 state->Set("minor_state", minor_state.release());
269
270 return state.PassAs<base::Value>();
271 }
272
HasSentBeginMainFrameThisFrame() const273 bool SchedulerStateMachine::HasSentBeginMainFrameThisFrame() const {
274 return current_frame_number_ ==
275 last_frame_number_begin_main_frame_sent_;
276 }
277
HasUpdatedVisibleTilesThisFrame() const278 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const {
279 return current_frame_number_ ==
280 last_frame_number_update_visible_tiles_was_called_;
281 }
282
HasSwappedThisFrame() const283 bool SchedulerStateMachine::HasSwappedThisFrame() const {
284 return current_frame_number_ == last_frame_number_swap_performed_;
285 }
286
PendingDrawsShouldBeAborted() const287 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const {
288 // These are all the cases where we normally cannot or do not want to draw
289 // but, if needs_redraw_ is true and we do not draw to make forward progress,
290 // we might deadlock with the main thread.
291 // This should be a superset of PendingActivationsShouldBeForced() since
292 // activation of the pending tree is blocked by drawing of the active tree and
293 // the main thread might be blocked on activation of the most recent commit.
294 if (PendingActivationsShouldBeForced())
295 return true;
296
297 // Additional states where we should abort draws.
298 // Note: We don't force activation in these cases because doing so would
299 // result in checkerboarding on resize, becoming visible, etc.
300 if (!can_draw_)
301 return true;
302 if (!visible_)
303 return true;
304 return false;
305 }
306
PendingActivationsShouldBeForced() const307 bool SchedulerStateMachine::PendingActivationsShouldBeForced() const {
308 // These are all the cases where, if we do not force activations to make
309 // forward progress, we might deadlock with the main thread.
310
311 // The impl thread cannot lock layer textures unless the pending
312 // tree can be activated to unblock the commit.
313 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD)
314 return true;
315
316 // There is no output surface to trigger our activations.
317 if (output_surface_state_ == OUTPUT_SURFACE_LOST)
318 return true;
319
320 return false;
321 }
322
ShouldBeginOutputSurfaceCreation() const323 bool SchedulerStateMachine::ShouldBeginOutputSurfaceCreation() const {
324 // Don't try to initialize too early.
325 if (!can_start_)
326 return false;
327
328 // We only want to start output surface initialization after the
329 // previous commit is complete.
330 if (commit_state_ != COMMIT_STATE_IDLE)
331 return false;
332
333 // We want to clear the pipline of any pending draws and activations
334 // before starting output surface initialization. This allows us to avoid
335 // weird corner cases where we abort draws or force activation while we
336 // are initializing the output surface and can potentially have a pending
337 // readback.
338 if (active_tree_needs_first_draw_ || has_pending_tree_)
339 return false;
340
341 // We need to create the output surface if we don't have one and we haven't
342 // started creating one yet.
343 return output_surface_state_ == OUTPUT_SURFACE_LOST;
344 }
345
ShouldDraw() const346 bool SchedulerStateMachine::ShouldDraw() const {
347 // After a readback, make sure not to draw again until we've replaced the
348 // readback commit with a real one.
349 if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT ||
350 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION)
351 return false;
352
353 // Draw immediately for readbacks to unblock the main thread quickly.
354 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) {
355 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
356 return true;
357 }
358
359 // If we need to abort draws, we should do so ASAP since the draw could
360 // be blocking other important actions (like output surface initialization),
361 // from occuring. If we are waiting for the first draw, then perfom the
362 // aborted draw to keep things moving. If we are not waiting for the first
363 // draw however, we don't want to abort for no reason.
364 if (PendingDrawsShouldBeAborted())
365 return active_tree_needs_first_draw_;
366
367 // After this line, we only want to swap once per frame.
368 if (HasSwappedThisFrame())
369 return false;
370
371 // Except for the cases above, do not draw outside of the BeginImplFrame
372 // deadline.
373 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
374 return false;
375
376 // Only handle forced redraws due to timeouts on the regular deadline.
377 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
378 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
379 return true;
380 }
381
382 return needs_redraw_;
383 }
384
ShouldAcquireLayerTexturesForMainThread() const385 bool SchedulerStateMachine::ShouldAcquireLayerTexturesForMainThread() const {
386 if (!main_thread_needs_layer_textures_)
387 return false;
388 if (texture_state_ == LAYER_TEXTURE_STATE_UNLOCKED)
389 return true;
390 DCHECK_EQ(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD);
391 return false;
392 }
393
ShouldActivatePendingTree() const394 bool SchedulerStateMachine::ShouldActivatePendingTree() const {
395 // There is nothing to activate.
396 if (!has_pending_tree_)
397 return false;
398
399 // We should not activate a second tree before drawing the first one.
400 // Even if we need to force activation of the pending tree, we should abort
401 // drawing the active tree first.
402 if (active_tree_needs_first_draw_)
403 return false;
404
405 // If we want to force activation, do so ASAP.
406 if (PendingActivationsShouldBeForced())
407 return true;
408
409 // At this point, only activate if we are ready to activate.
410 return pending_tree_is_ready_for_activation_;
411 }
412
ShouldUpdateVisibleTiles() const413 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const {
414 if (!settings_.impl_side_painting)
415 return false;
416 if (HasUpdatedVisibleTilesThisFrame())
417 return false;
418
419 // There's no reason to check for tiles if we don't have an output surface.
420 if (!HasInitializedOutputSurface())
421 return false;
422
423 // We should not check for visible tiles until we've entered the deadline so
424 // we check as late as possible and give the tiles more time to initialize.
425 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
426 return false;
427
428 // If the last swap drew with checkerboard or missing tiles, we should
429 // poll for any new visible tiles so we can be notified to draw again
430 // when there are.
431 if (swap_used_incomplete_tile_)
432 return true;
433
434 return false;
435 }
436
ShouldSendBeginMainFrame() const437 bool SchedulerStateMachine::ShouldSendBeginMainFrame() const {
438 if (!needs_commit_)
439 return false;
440
441 // Only send BeginMainFrame when there isn't another commit pending already.
442 if (commit_state_ != COMMIT_STATE_IDLE)
443 return false;
444
445 // We can't accept a commit if we have a pending tree.
446 if (has_pending_tree_)
447 return false;
448
449 // We want to handle readback commits immediately to unblock the main thread.
450 // Note: This BeginMainFrame will correspond to the replacement commit that
451 // comes after the readback commit itself, so we only send the BeginMainFrame
452 // if a commit isn't already pending behind the readback.
453 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME)
454 return !CommitPending();
455
456 // We do not need commits if we are not visible, unless there's a
457 // request for a readback.
458 if (!visible_)
459 return false;
460
461 // We want to start the first commit after we get a new output surface ASAP.
462 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT)
463 return true;
464
465 // With deadline scheduling enabled, we should not send BeginMainFrame while
466 // we are in BEGIN_IMPL_FRAME_STATE_IDLE, since we might have new user input
467 // coming in soon.
468 // However, if we are not expecting a BeginImplFrame to take us out of idle,
469 // we should not early out here to avoid blocking commits forever.
470 // This only works well when deadline scheduling is enabled because there is
471 // an interval over which to accept the commit and draw. Without deadline
472 // scheduling, delaying the commit could prevent us from having something
473 // to draw on the next BeginImplFrame.
474 // TODO(brianderson): Allow sending BeginMainFrame while idle when the main
475 // thread isn't consuming user input.
476 if (settings_.deadline_scheduling_enabled &&
477 begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE &&
478 BeginImplFrameNeeded())
479 return false;
480
481 // We need a new commit for the forced redraw. This honors the
482 // single commit per interval because the result will be swapped to screen.
483 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT)
484 return true;
485
486 // After this point, we only start a commit once per frame.
487 if (HasSentBeginMainFrameThisFrame())
488 return false;
489
490 // We shouldn't normally accept commits if there isn't an OutputSurface.
491 if (!HasInitializedOutputSurface())
492 return false;
493
494 if (skip_begin_main_frame_to_reduce_latency_)
495 return false;
496
497 return true;
498 }
499
ShouldCommit() const500 bool SchedulerStateMachine::ShouldCommit() const {
501 return commit_state_ == COMMIT_STATE_READY_TO_COMMIT;
502 }
503
IsCommitStateWaiting() const504 bool SchedulerStateMachine::IsCommitStateWaiting() const {
505 return commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS;
506 }
507
ShouldManageTiles() const508 bool SchedulerStateMachine::ShouldManageTiles() const {
509 // ManageTiles only really needs to be called immediately after commit
510 // and then periodically after that. Limiting to once per frame prevents
511 // post-commit and post-draw ManageTiles on the same frame.
512 if (last_frame_number_manage_tiles_called_ == current_frame_number_)
513 return false;
514
515 // Limiting to once per-frame is not enough, since we only want to
516 // manage tiles _after_ draws. Polling for draw triggers and
517 // begin-frame are mutually exclusive, so we limit to these two cases.
518 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE &&
519 !inside_poll_for_anticipated_draw_triggers_)
520 return false;
521 return needs_manage_tiles_;
522 }
523
NextAction() const524 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
525 if (ShouldAcquireLayerTexturesForMainThread())
526 return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD;
527 if (ShouldUpdateVisibleTiles())
528 return ACTION_UPDATE_VISIBLE_TILES;
529 if (ShouldActivatePendingTree())
530 return ACTION_ACTIVATE_PENDING_TREE;
531 if (ShouldCommit())
532 return ACTION_COMMIT;
533 if (ShouldDraw()) {
534 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK)
535 return ACTION_DRAW_AND_READBACK;
536 else if (PendingDrawsShouldBeAborted())
537 return ACTION_DRAW_AND_SWAP_ABORT;
538 else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
539 return ACTION_DRAW_AND_SWAP_FORCED;
540 else
541 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
542 }
543 if (ShouldManageTiles())
544 return ACTION_MANAGE_TILES;
545 if (ShouldSendBeginMainFrame())
546 return ACTION_SEND_BEGIN_MAIN_FRAME;
547 if (ShouldBeginOutputSurfaceCreation())
548 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION;
549 return ACTION_NONE;
550 }
551
CheckInvariants()552 void SchedulerStateMachine::CheckInvariants() {
553 // We should never try to perform a draw for readback and forced draw due to
554 // timeout simultaneously.
555 DCHECK(!(forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW &&
556 readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK));
557 }
558
UpdateState(Action action)559 void SchedulerStateMachine::UpdateState(Action action) {
560 switch (action) {
561 case ACTION_NONE:
562 return;
563
564 case ACTION_UPDATE_VISIBLE_TILES:
565 last_frame_number_update_visible_tiles_was_called_ =
566 current_frame_number_;
567 return;
568
569 case ACTION_ACTIVATE_PENDING_TREE:
570 UpdateStateOnActivation();
571 return;
572
573 case ACTION_SEND_BEGIN_MAIN_FRAME:
574 DCHECK(!has_pending_tree_);
575 DCHECK(visible_ ||
576 readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME);
577 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
578 needs_commit_ = false;
579 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME)
580 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
581 last_frame_number_begin_main_frame_sent_ =
582 current_frame_number_;
583 return;
584
585 case ACTION_COMMIT: {
586 bool commit_was_aborted = false;
587 UpdateStateOnCommit(commit_was_aborted);
588 return;
589 }
590
591 case ACTION_DRAW_AND_SWAP_FORCED:
592 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: {
593 bool did_swap = true;
594 UpdateStateOnDraw(did_swap);
595 return;
596 }
597
598 case ACTION_DRAW_AND_SWAP_ABORT:
599 case ACTION_DRAW_AND_READBACK: {
600 bool did_swap = false;
601 UpdateStateOnDraw(did_swap);
602 return;
603 }
604
605 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
606 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST);
607 output_surface_state_ = OUTPUT_SURFACE_CREATING;
608
609 // The following DCHECKs make sure we are in the proper quiescent state.
610 // The pipeline should be flushed entirely before we start output
611 // surface creation to avoid complicated corner cases.
612 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE);
613 DCHECK(!has_pending_tree_);
614 DCHECK(!active_tree_needs_first_draw_);
615 return;
616
617 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
618 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD;
619 main_thread_needs_layer_textures_ = false;
620 return;
621
622 case ACTION_MANAGE_TILES:
623 UpdateStateOnManageTiles();
624 return;
625 }
626 }
627
UpdateStateOnCommit(bool commit_was_aborted)628 void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) {
629 commit_count_++;
630
631 // If we are impl-side-painting but the commit was aborted, then we behave
632 // mostly as if we are not impl-side-painting since there is no pending tree.
633 has_pending_tree_ = settings_.impl_side_painting && !commit_was_aborted;
634
635 // Update state related to readbacks.
636 if (readback_state_ == READBACK_STATE_WAITING_FOR_COMMIT) {
637 // Update the state if this is the readback commit.
638 readback_state_ = has_pending_tree_
639 ? READBACK_STATE_WAITING_FOR_ACTIVATION
640 : READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
641 } else if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT) {
642 // Update the state if this is the commit replacing the readback commit.
643 readback_state_ = has_pending_tree_
644 ? READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION
645 : READBACK_STATE_IDLE;
646 } else {
647 DCHECK(readback_state_ == READBACK_STATE_IDLE);
648 }
649
650 // Readbacks can interrupt output surface initialization and forced draws,
651 // so we do not want to advance those states if we are in the middle of a
652 // readback. Note: It is possible for the readback's replacement commit to
653 // be the output surface's first commit and/or the forced redraw's commit.
654 if (readback_state_ == READBACK_STATE_IDLE ||
655 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) {
656 // Update state related to forced draws.
657 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) {
658 forced_redraw_state_ = has_pending_tree_
659 ? FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION
660 : FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
661 }
662
663 // Update the output surface state.
664 DCHECK_NE(output_surface_state_,
665 OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION);
666 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) {
667 if (has_pending_tree_) {
668 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION;
669 } else {
670 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
671 needs_redraw_ = true;
672 }
673 }
674 }
675
676 // Update the commit state. We expect and wait for a draw if the commit
677 // was not aborted or if we are in a readback or forced draw.
678 if (!commit_was_aborted) {
679 DCHECK(commit_state_ == COMMIT_STATE_READY_TO_COMMIT);
680 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
681 } else if (readback_state_ != READBACK_STATE_IDLE ||
682 forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE) {
683 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
684 } else {
685 commit_state_ = COMMIT_STATE_IDLE;
686 }
687
688 // Update state if we have a new active tree to draw, or if the active tree
689 // was unchanged but we need to do a readback or forced draw.
690 if (!has_pending_tree_ &&
691 (!commit_was_aborted ||
692 readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK ||
693 forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)) {
694 needs_redraw_ = true;
695 active_tree_needs_first_draw_ = true;
696 }
697
698 // This post-commit work is common to both completed and aborted commits.
699 pending_tree_is_ready_for_activation_ = false;
700
701 if (draw_if_possible_failed_)
702 last_frame_number_swap_performed_ = -1;
703
704 // If we are planing to draw with the new commit, lock the layer textures for
705 // use on the impl thread. Otherwise, leave them unlocked.
706 if (has_pending_tree_ || needs_redraw_)
707 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD;
708 else
709 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED;
710 }
711
UpdateStateOnActivation()712 void SchedulerStateMachine::UpdateStateOnActivation() {
713 // Update output surface state.
714 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
715 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
716
717 // Update readback state
718 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION)
719 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
720
721 // Update forced redraw state
722 if (readback_state_ == READBACK_STATE_WAITING_FOR_ACTIVATION)
723 readback_state_ = READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
724 else if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION)
725 readback_state_ = READBACK_STATE_IDLE;
726
727 has_pending_tree_ = false;
728 pending_tree_is_ready_for_activation_ = false;
729 active_tree_needs_first_draw_ = true;
730 needs_redraw_ = true;
731 }
732
UpdateStateOnDraw(bool did_swap)733 void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) {
734 DCHECK(readback_state_ != READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT &&
735 readback_state_ != READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION)
736 << *AsValue();
737
738 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) {
739 // The draw correspons to a readback commit.
740 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
741 // We are blocking commits from the main thread until after this draw, so
742 // we should not have a pending tree.
743 DCHECK(!has_pending_tree_);
744 // We transition to COMMIT_STATE_FRAME_IN_PROGRESS because there is a
745 // pending BeginMainFrame behind the readback request.
746 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
747 readback_state_ = READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT;
748 } else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
749 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
750 commit_state_ = COMMIT_STATE_IDLE;
751 forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
752 } else if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW &&
753 !has_pending_tree_) {
754 commit_state_ = COMMIT_STATE_IDLE;
755 }
756
757 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD)
758 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED;
759
760 needs_redraw_ = false;
761 draw_if_possible_failed_ = false;
762 active_tree_needs_first_draw_ = false;
763
764 if (did_swap)
765 last_frame_number_swap_performed_ = current_frame_number_;
766 }
767
UpdateStateOnManageTiles()768 void SchedulerStateMachine::UpdateStateOnManageTiles() {
769 needs_manage_tiles_ = false;
770 }
771
SetMainThreadNeedsLayerTextures()772 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() {
773 DCHECK(!main_thread_needs_layer_textures_);
774 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD);
775 main_thread_needs_layer_textures_ = true;
776 }
777
SetSkipBeginMainFrameToReduceLatency(bool skip)778 void SchedulerStateMachine::SetSkipBeginMainFrameToReduceLatency(bool skip) {
779 skip_begin_main_frame_to_reduce_latency_ = skip;
780 }
781
BeginImplFrameNeeded() const782 bool SchedulerStateMachine::BeginImplFrameNeeded() const {
783 // Proactive BeginImplFrames are bad for the synchronous compositor because we
784 // have to draw when we get the BeginImplFrame and could end up drawing many
785 // duplicate frames if our new frame isn't ready in time.
786 // To poll for state with the synchronous compositor without having to draw,
787 // we rely on ShouldPollForAnticipatedDrawTriggers instead.
788 if (!SupportsProactiveBeginImplFrame())
789 return BeginImplFrameNeededToDraw();
790
791 return BeginImplFrameNeededToDraw() ||
792 ProactiveBeginImplFrameWanted();
793 }
794
ShouldPollForAnticipatedDrawTriggers() const795 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const {
796 // ShouldPollForAnticipatedDrawTriggers is what we use in place of
797 // ProactiveBeginImplFrameWanted when we are using the synchronous
798 // compositor.
799 if (!SupportsProactiveBeginImplFrame()) {
800 return !BeginImplFrameNeededToDraw() &&
801 ProactiveBeginImplFrameWanted();
802 }
803
804 // Non synchronous compositors should rely on
805 // ProactiveBeginImplFrameWanted to poll for state instead.
806 return false;
807 }
808
SupportsProactiveBeginImplFrame() const809 bool SchedulerStateMachine::SupportsProactiveBeginImplFrame() const {
810 // Both the synchronous compositor and disabled vsync settings
811 // make it undesirable to proactively request BeginImplFrames.
812 // If this is true, the scheduler should poll.
813 return !settings_.using_synchronous_renderer_compositor &&
814 settings_.throttle_frame_production;
815 }
816
817 // These are the cases where we definitely (or almost definitely) have a
818 // new frame to draw and can draw.
BeginImplFrameNeededToDraw() const819 bool SchedulerStateMachine::BeginImplFrameNeededToDraw() const {
820 // The output surface is the provider of BeginImplFrames, so we are not going
821 // to get them even if we ask for them.
822 if (!HasInitializedOutputSurface())
823 return false;
824
825 // If we can't draw, don't tick until we are notified that we can draw again.
826 if (!can_draw_)
827 return false;
828
829 // The forced draw respects our normal draw scheduling, so we need to
830 // request a BeginImplFrame for it.
831 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
832 return true;
833
834 // There's no need to produce frames if we are not visible.
835 if (!visible_)
836 return false;
837
838 // We need to draw a more complete frame than we did the last BeginImplFrame,
839 // so request another BeginImplFrame in anticipation that we will have
840 // additional visible tiles.
841 if (swap_used_incomplete_tile_)
842 return true;
843
844 return needs_redraw_;
845 }
846
847 // These are cases where we are very likely to draw soon, but might not
848 // actually have a new frame to draw when we receive the next BeginImplFrame.
849 // Proactively requesting the BeginImplFrame helps hide the round trip latency
850 // of the SetNeedsBeginImplFrame request that has to go to the Browser.
ProactiveBeginImplFrameWanted() const851 bool SchedulerStateMachine::ProactiveBeginImplFrameWanted() const {
852 // The output surface is the provider of BeginImplFrames,
853 // so we are not going to get them even if we ask for them.
854 if (!HasInitializedOutputSurface())
855 return false;
856
857 // Do not be proactive when invisible.
858 if (!visible_)
859 return false;
860
861 // We should proactively request a BeginImplFrame if a commit is pending
862 // because we will want to draw if the commit completes quickly.
863 if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE)
864 return true;
865
866 // If the pending tree activates quickly, we'll want a BeginImplFrame soon
867 // to draw the new active tree.
868 if (has_pending_tree_)
869 return true;
870
871 // Changing priorities may allow us to activate (given the new priorities),
872 // which may result in a new frame.
873 if (needs_manage_tiles_)
874 return true;
875
876 // If we just swapped, it's likely that we are going to produce another
877 // frame soon. This helps avoid negative glitches in our
878 // SetNeedsBeginImplFrame requests, which may propagate to the BeginImplFrame
879 // provider and get sampled at an inopportune time, delaying the next
880 // BeginImplFrame.
881 if (last_frame_number_swap_performed_ == current_frame_number_)
882 return true;
883
884 return false;
885 }
886
OnBeginImplFrame(const BeginFrameArgs & args)887 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) {
888 current_frame_number_++;
889 last_begin_impl_frame_args_ = args;
890 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) << *AsValue();
891 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING;
892 }
893
OnBeginImplFrameDeadlinePending()894 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() {
895 DCHECK_EQ(begin_impl_frame_state_,
896 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING)
897 << *AsValue();
898 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME;
899 }
900
OnBeginImplFrameDeadline()901 void SchedulerStateMachine::OnBeginImplFrameDeadline() {
902 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
903 << *AsValue();
904 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
905 }
906
OnBeginImplFrameIdle()907 void SchedulerStateMachine::OnBeginImplFrameIdle() {
908 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
909 << *AsValue();
910 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE;
911 }
912
ShouldTriggerBeginImplFrameDeadlineEarly() const913 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineEarly() const {
914 // TODO(brianderson): This should take into account multiple commit sources.
915
916 // If we are in the middle of the readback, we won't swap, so there is
917 // no reason to trigger the deadline early.
918 if (readback_state_ != READBACK_STATE_IDLE)
919 return false;
920
921 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
922 return false;
923
924 if (active_tree_needs_first_draw_)
925 return true;
926
927 if (!needs_redraw_)
928 return false;
929
930 // This is used to prioritize impl-thread draws when the main thread isn't
931 // producing anything, e.g., after an aborted commit. We also check that we
932 // don't have a pending tree -- otherwise we should give it a chance to
933 // activate.
934 // TODO(skyostil): Revisit this when we have more accurate deadline estimates.
935 if (commit_state_ == COMMIT_STATE_IDLE && !has_pending_tree_)
936 return true;
937
938 // Prioritize impl-thread draws in smoothness mode.
939 if (smoothness_takes_priority_)
940 return true;
941
942 return false;
943 }
944
MainThreadIsInHighLatencyMode() const945 bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const {
946 // If we just sent a BeginMainFrame and haven't hit the deadline yet, the main
947 // thread is in a low latency mode.
948 if (last_frame_number_begin_main_frame_sent_ == current_frame_number_ &&
949 (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING ||
950 begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME))
951 return false;
952
953 // If there's a commit in progress it must either be from the previous frame
954 // or it started after the impl thread's deadline. In either case the main
955 // thread is in high latency mode.
956 if (commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS ||
957 commit_state_ == COMMIT_STATE_READY_TO_COMMIT)
958 return true;
959
960 // Similarly, if there's a pending tree the main thread is in high latency
961 // mode, because either
962 // it's from the previous frame
963 // or
964 // we're currently drawing the active tree and the pending tree will thus
965 // only be drawn in the next frame.
966 if (has_pending_tree_)
967 return true;
968
969 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) {
970 // Even if there's a new active tree to draw at the deadline or we've just
971 // drawn it, it may have been triggered by a previous BeginImplFrame, in
972 // which case the main thread is in a high latency mode.
973 return (active_tree_needs_first_draw_ ||
974 last_frame_number_swap_performed_ == current_frame_number_) &&
975 last_frame_number_begin_main_frame_sent_ != current_frame_number_;
976 }
977
978 // If the active tree needs its first draw in any other state, we know the
979 // main thread is in a high latency mode.
980 return active_tree_needs_first_draw_;
981 }
982
DidEnterPollForAnticipatedDrawTriggers()983 void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() {
984 current_frame_number_++;
985 inside_poll_for_anticipated_draw_triggers_ = true;
986 }
987
DidLeavePollForAnticipatedDrawTriggers()988 void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() {
989 inside_poll_for_anticipated_draw_triggers_ = false;
990 }
991
SetVisible(bool visible)992 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }
993
SetCanDraw(bool can_draw)994 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }
995
SetNeedsRedraw()996 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }
997
SetNeedsManageTiles()998 void SchedulerStateMachine::SetNeedsManageTiles() {
999 if (!needs_manage_tiles_) {
1000 TRACE_EVENT0("cc",
1001 "SchedulerStateMachine::SetNeedsManageTiles");
1002 needs_manage_tiles_ = true;
1003 }
1004 }
1005
SetSwapUsedIncompleteTile(bool used_incomplete_tile)1006 void SchedulerStateMachine::SetSwapUsedIncompleteTile(
1007 bool used_incomplete_tile) {
1008 swap_used_incomplete_tile_ = used_incomplete_tile;
1009 }
1010
SetSmoothnessTakesPriority(bool smoothness_takes_priority)1011 void SchedulerStateMachine::SetSmoothnessTakesPriority(
1012 bool smoothness_takes_priority) {
1013 smoothness_takes_priority_ = smoothness_takes_priority;
1014 }
1015
DidDrawIfPossibleCompleted(bool success)1016 void SchedulerStateMachine::DidDrawIfPossibleCompleted(bool success) {
1017 draw_if_possible_failed_ = !success;
1018 if (draw_if_possible_failed_) {
1019 needs_redraw_ = true;
1020
1021 // If we're already in the middle of a redraw, we don't need to
1022 // restart it.
1023 if (forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE)
1024 return;
1025
1026 needs_commit_ = true;
1027 consecutive_failed_draws_++;
1028 if (settings_.timeout_and_draw_when_animation_checkerboards &&
1029 consecutive_failed_draws_ >=
1030 settings_.maximum_number_of_failed_draws_before_draw_is_forced_) {
1031 consecutive_failed_draws_ = 0;
1032 // We need to force a draw, but it doesn't make sense to do this until
1033 // we've committed and have new textures.
1034 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT;
1035 }
1036 } else {
1037 consecutive_failed_draws_ = 0;
1038 forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
1039 }
1040 }
1041
SetNeedsCommit()1042 void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; }
1043
SetNeedsForcedCommitForReadback()1044 void SchedulerStateMachine::SetNeedsForcedCommitForReadback() {
1045 // If this is called in READBACK_STATE_IDLE, this is a "first" readback
1046 // request.
1047 // If this is called in READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT, this
1048 // is a back-to-back readback request that started before the replacement
1049 // commit had a chance to land.
1050 DCHECK(readback_state_ == READBACK_STATE_IDLE ||
1051 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT);
1052
1053 // If there is already a commit in progress when we get the readback request
1054 // (we are in COMMIT_STATE_FRAME_IN_PROGRESS), then we don't need to send a
1055 // BeginMainFrame for the replacement commit, since there's already a
1056 // BeginMainFrame behind the readback request. In that case, we can skip
1057 // READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME and go directly to
1058 // READBACK_STATE_WAITING_FOR_COMMIT
1059 if (commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS)
1060 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
1061 else
1062 readback_state_ = READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME;
1063 }
1064
FinishCommit()1065 void SchedulerStateMachine::FinishCommit() {
1066 DCHECK(commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS) << *AsValue();
1067 commit_state_ = COMMIT_STATE_READY_TO_COMMIT;
1068 }
1069
BeginMainFrameAborted(bool did_handle)1070 void SchedulerStateMachine::BeginMainFrameAborted(bool did_handle) {
1071 DCHECK_EQ(commit_state_, COMMIT_STATE_FRAME_IN_PROGRESS);
1072 if (did_handle) {
1073 bool commit_was_aborted = true;
1074 UpdateStateOnCommit(commit_was_aborted);
1075 } else {
1076 DCHECK_NE(readback_state_, READBACK_STATE_WAITING_FOR_COMMIT);
1077 commit_state_ = COMMIT_STATE_IDLE;
1078 SetNeedsCommit();
1079 }
1080 }
1081
DidManageTiles()1082 void SchedulerStateMachine::DidManageTiles() {
1083 needs_manage_tiles_ = false;
1084 last_frame_number_manage_tiles_called_ = current_frame_number_;
1085 }
1086
DidLoseOutputSurface()1087 void SchedulerStateMachine::DidLoseOutputSurface() {
1088 if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
1089 output_surface_state_ == OUTPUT_SURFACE_CREATING)
1090 return;
1091 output_surface_state_ = OUTPUT_SURFACE_LOST;
1092 needs_redraw_ = false;
1093 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE;
1094 }
1095
NotifyReadyToActivate()1096 void SchedulerStateMachine::NotifyReadyToActivate() {
1097 if (has_pending_tree_)
1098 pending_tree_is_ready_for_activation_ = true;
1099 }
1100
DidCreateAndInitializeOutputSurface()1101 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
1102 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING);
1103 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT;
1104
1105 if (did_create_and_initialize_first_output_surface_) {
1106 // TODO(boliu): See if we can remove this when impl-side painting is always
1107 // on. Does anything on the main thread need to update after recreate?
1108 needs_commit_ = true;
1109 }
1110 did_create_and_initialize_first_output_surface_ = true;
1111 }
1112
HasInitializedOutputSurface() const1113 bool SchedulerStateMachine::HasInitializedOutputSurface() const {
1114 switch (output_surface_state_) {
1115 case OUTPUT_SURFACE_LOST:
1116 case OUTPUT_SURFACE_CREATING:
1117 return false;
1118
1119 case OUTPUT_SURFACE_ACTIVE:
1120 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
1121 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
1122 return true;
1123 }
1124 NOTREACHED();
1125 return false;
1126 }
1127
1128 } // namespace cc
1129