Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / cc / scheduler / scheduler_state_machine.cc
blob44ab643e84d0e71f37dd5b9411e3eb7ec54e306e
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.
5 #include "cc/scheduler/scheduler_state_machine.h"
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"
14 namespace cc {
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 forced_redraw_state_(FORCED_REDRAW_STATE_IDLE),
22 readback_state_(READBACK_STATE_IDLE),
23 commit_count_(0),
24 current_frame_number_(0),
25 last_frame_number_animate_performed_(-1),
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 manage_tiles_funnel_(0),
30 consecutive_checkerboard_animations_(0),
31 max_pending_swaps_(1),
32 pending_swaps_(0),
33 needs_redraw_(false),
34 needs_animate_(false),
35 needs_manage_tiles_(false),
36 swap_used_incomplete_tile_(false),
37 needs_commit_(false),
38 inside_poll_for_anticipated_draw_triggers_(false),
39 visible_(false),
40 can_start_(false),
41 can_draw_(false),
42 has_pending_tree_(false),
43 pending_tree_is_ready_for_activation_(false),
44 active_tree_needs_first_draw_(false),
45 did_create_and_initialize_first_output_surface_(false),
46 smoothness_takes_priority_(false),
47 skip_next_begin_main_frame_to_reduce_latency_(false),
48 skip_begin_main_frame_to_reduce_latency_(false),
49 continuous_painting_(false),
50 needs_back_to_back_readback_(false) {
53 const char* SchedulerStateMachine::OutputSurfaceStateToString(
54 OutputSurfaceState state) {
55 switch (state) {
56 case OUTPUT_SURFACE_ACTIVE:
57 return "OUTPUT_SURFACE_ACTIVE";
58 case OUTPUT_SURFACE_LOST:
59 return "OUTPUT_SURFACE_LOST";
60 case OUTPUT_SURFACE_CREATING:
61 return "OUTPUT_SURFACE_CREATING";
62 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
63 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT";
64 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
65 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION";
67 NOTREACHED();
68 return "???";
71 const char* SchedulerStateMachine::BeginImplFrameStateToString(
72 BeginImplFrameState state) {
73 switch (state) {
74 case BEGIN_IMPL_FRAME_STATE_IDLE:
75 return "BEGIN_IMPL_FRAME_STATE_IDLE";
76 case BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING:
77 return "BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING";
78 case BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME:
79 return "BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME";
80 case BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE:
81 return "BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE";
83 NOTREACHED();
84 return "???";
87 const char* SchedulerStateMachine::CommitStateToString(CommitState state) {
88 switch (state) {
89 case COMMIT_STATE_IDLE:
90 return "COMMIT_STATE_IDLE";
91 case COMMIT_STATE_BEGIN_MAIN_FRAME_SENT:
92 return "COMMIT_STATE_BEGIN_MAIN_FRAME_SENT";
93 case COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED:
94 return "COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED";
95 case COMMIT_STATE_READY_TO_COMMIT:
96 return "COMMIT_STATE_READY_TO_COMMIT";
97 case COMMIT_STATE_WAITING_FOR_ACTIVATION:
98 return "COMMIT_STATE_WAITING_FOR_ACTIVATION";
99 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW:
100 return "COMMIT_STATE_WAITING_FOR_FIRST_DRAW";
102 NOTREACHED();
103 return "???";
106 const char* SchedulerStateMachine::SynchronousReadbackStateToString(
107 SynchronousReadbackState state) {
108 switch (state) {
109 case READBACK_STATE_IDLE:
110 return "READBACK_STATE_IDLE";
111 case READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME:
112 return "READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME";
113 case READBACK_STATE_WAITING_FOR_COMMIT:
114 return "READBACK_STATE_WAITING_FOR_COMMIT";
115 case READBACK_STATE_WAITING_FOR_ACTIVATION:
116 return "READBACK_STATE_WAITING_FOR_ACTIVATION";
117 case READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK:
118 return "READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK";
119 case READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT:
120 return "READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT";
121 case READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION:
122 return "READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION";
124 NOTREACHED();
125 return "???";
128 const char* SchedulerStateMachine::ForcedRedrawOnTimeoutStateToString(
129 ForcedRedrawOnTimeoutState state) {
130 switch (state) {
131 case FORCED_REDRAW_STATE_IDLE:
132 return "FORCED_REDRAW_STATE_IDLE";
133 case FORCED_REDRAW_STATE_WAITING_FOR_COMMIT:
134 return "FORCED_REDRAW_STATE_WAITING_FOR_COMMIT";
135 case FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION:
136 return "FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION";
137 case FORCED_REDRAW_STATE_WAITING_FOR_DRAW:
138 return "FORCED_REDRAW_STATE_WAITING_FOR_DRAW";
140 NOTREACHED();
141 return "???";
144 const char* SchedulerStateMachine::ActionToString(Action action) {
145 switch (action) {
146 case ACTION_NONE:
147 return "ACTION_NONE";
148 case ACTION_ANIMATE:
149 return "ACTION_ANIMATE";
150 case ACTION_SEND_BEGIN_MAIN_FRAME:
151 return "ACTION_SEND_BEGIN_MAIN_FRAME";
152 case ACTION_COMMIT:
153 return "ACTION_COMMIT";
154 case ACTION_UPDATE_VISIBLE_TILES:
155 return "ACTION_UPDATE_VISIBLE_TILES";
156 case ACTION_ACTIVATE_PENDING_TREE:
157 return "ACTION_ACTIVATE_PENDING_TREE";
158 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
159 return "ACTION_DRAW_AND_SWAP_IF_POSSIBLE";
160 case ACTION_DRAW_AND_SWAP_FORCED:
161 return "ACTION_DRAW_AND_SWAP_FORCED";
162 case ACTION_DRAW_AND_SWAP_ABORT:
163 return "ACTION_DRAW_AND_SWAP_ABORT";
164 case ACTION_DRAW_AND_READBACK:
165 return "ACTION_DRAW_AND_READBACK";
166 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
167 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION";
168 case ACTION_MANAGE_TILES:
169 return "ACTION_MANAGE_TILES";
171 NOTREACHED();
172 return "???";
175 scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const {
176 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
178 scoped_ptr<base::DictionaryValue> major_state(new base::DictionaryValue);
179 major_state->SetString("next_action", ActionToString(NextAction()));
180 major_state->SetString("begin_impl_frame_state",
181 BeginImplFrameStateToString(begin_impl_frame_state_));
182 major_state->SetString("commit_state", CommitStateToString(commit_state_));
183 major_state->SetString("output_surface_state_",
184 OutputSurfaceStateToString(output_surface_state_));
185 major_state->SetString(
186 "forced_redraw_state",
187 ForcedRedrawOnTimeoutStateToString(forced_redraw_state_));
188 major_state->SetString("readback_state",
189 SynchronousReadbackStateToString(readback_state_));
190 state->Set("major_state", major_state.release());
192 scoped_ptr<base::DictionaryValue> timestamps_state(new base::DictionaryValue);
193 base::TimeTicks now = gfx::FrameTime::Now();
194 timestamps_state->SetDouble(
195 "0_interval", begin_impl_frame_args_.interval.InMicroseconds() / 1000.0L);
196 timestamps_state->SetDouble(
197 "1_now_to_deadline",
198 (begin_impl_frame_args_.deadline - now).InMicroseconds() / 1000.0L);
199 timestamps_state->SetDouble(
200 "2_frame_time_to_now",
201 (now - begin_impl_frame_args_.frame_time).InMicroseconds() / 1000.0L);
202 timestamps_state->SetDouble(
203 "3_frame_time_to_deadline",
204 (begin_impl_frame_args_.deadline - begin_impl_frame_args_.frame_time)
205 .InMicroseconds() /
206 1000.0L);
207 timestamps_state->SetDouble(
208 "4_now", (now - base::TimeTicks()).InMicroseconds() / 1000.0L);
209 timestamps_state->SetDouble(
210 "5_frame_time",
211 (begin_impl_frame_args_.frame_time - base::TimeTicks()).InMicroseconds() /
212 1000.0L);
213 timestamps_state->SetDouble(
214 "6_deadline",
215 (begin_impl_frame_args_.deadline - base::TimeTicks()).InMicroseconds() /
216 1000.0L);
217 state->Set("major_timestamps_in_ms", timestamps_state.release());
219 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue);
220 minor_state->SetInteger("commit_count", commit_count_);
221 minor_state->SetInteger("current_frame_number", current_frame_number_);
223 minor_state->SetInteger("last_frame_number_animate_performed",
224 last_frame_number_animate_performed_);
225 minor_state->SetInteger("last_frame_number_swap_performed",
226 last_frame_number_swap_performed_);
227 minor_state->SetInteger(
228 "last_frame_number_begin_main_frame_sent",
229 last_frame_number_begin_main_frame_sent_);
230 minor_state->SetInteger(
231 "last_frame_number_update_visible_tiles_was_called",
232 last_frame_number_update_visible_tiles_was_called_);
234 minor_state->SetInteger("manage_tiles_funnel", manage_tiles_funnel_);
235 minor_state->SetInteger("consecutive_checkerboard_animations",
236 consecutive_checkerboard_animations_);
237 minor_state->SetInteger("max_pending_swaps_", max_pending_swaps_);
238 minor_state->SetInteger("pending_swaps_", pending_swaps_);
239 minor_state->SetBoolean("needs_redraw", needs_redraw_);
240 minor_state->SetBoolean("needs_animate_", needs_animate_);
241 minor_state->SetBoolean("needs_manage_tiles", needs_manage_tiles_);
242 minor_state->SetBoolean("swap_used_incomplete_tile",
243 swap_used_incomplete_tile_);
244 minor_state->SetBoolean("needs_commit", needs_commit_);
245 minor_state->SetBoolean("visible", visible_);
246 minor_state->SetBoolean("can_start", can_start_);
247 minor_state->SetBoolean("can_draw", can_draw_);
248 minor_state->SetBoolean("has_pending_tree", has_pending_tree_);
249 minor_state->SetBoolean("pending_tree_is_ready_for_activation",
250 pending_tree_is_ready_for_activation_);
251 minor_state->SetBoolean("active_tree_needs_first_draw",
252 active_tree_needs_first_draw_);
253 minor_state->SetBoolean("did_create_and_initialize_first_output_surface",
254 did_create_and_initialize_first_output_surface_);
255 minor_state->SetBoolean("smoothness_takes_priority",
256 smoothness_takes_priority_);
257 minor_state->SetBoolean("main_thread_is_in_high_latency_mode",
258 MainThreadIsInHighLatencyMode());
259 minor_state->SetBoolean("skip_begin_main_frame_to_reduce_latency",
260 skip_begin_main_frame_to_reduce_latency_);
261 minor_state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency",
262 skip_next_begin_main_frame_to_reduce_latency_);
263 minor_state->SetBoolean("continuous_painting", continuous_painting_);
264 state->Set("minor_state", minor_state.release());
266 return state.PassAs<base::Value>();
269 void SchedulerStateMachine::AdvanceCurrentFrameNumber() {
270 current_frame_number_++;
272 // "Drain" the ManageTiles funnel.
273 if (manage_tiles_funnel_ > 0)
274 manage_tiles_funnel_--;
276 skip_begin_main_frame_to_reduce_latency_ =
277 skip_next_begin_main_frame_to_reduce_latency_;
278 skip_next_begin_main_frame_to_reduce_latency_ = false;
281 bool SchedulerStateMachine::HasSentBeginMainFrameThisFrame() const {
282 return current_frame_number_ ==
283 last_frame_number_begin_main_frame_sent_;
286 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const {
287 return current_frame_number_ ==
288 last_frame_number_update_visible_tiles_was_called_;
291 bool SchedulerStateMachine::HasSwappedThisFrame() const {
292 return current_frame_number_ == last_frame_number_swap_performed_;
295 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const {
296 // These are all the cases where we normally cannot or do not want to draw
297 // but, if needs_redraw_ is true and we do not draw to make forward progress,
298 // we might deadlock with the main thread.
299 // This should be a superset of PendingActivationsShouldBeForced() since
300 // activation of the pending tree is blocked by drawing of the active tree and
301 // the main thread might be blocked on activation of the most recent commit.
302 if (PendingActivationsShouldBeForced())
303 return true;
305 // Additional states where we should abort draws.
306 // Note: We don't force activation in these cases because doing so would
307 // result in checkerboarding on resize, becoming visible, etc.
308 if (!can_draw_)
309 return true;
310 if (!visible_)
311 return true;
312 return false;
315 bool SchedulerStateMachine::PendingActivationsShouldBeForced() const {
316 // These are all the cases where, if we do not force activations to make
317 // forward progress, we might deadlock with the main thread.
319 // There is no output surface to trigger our activations.
320 if (output_surface_state_ == OUTPUT_SURFACE_LOST)
321 return true;
323 return false;
326 bool SchedulerStateMachine::ShouldBeginOutputSurfaceCreation() const {
327 // Don't try to initialize too early.
328 if (!can_start_)
329 return false;
331 // We only want to start output surface initialization after the
332 // previous commit is complete.
333 if (commit_state_ != COMMIT_STATE_IDLE)
334 return false;
336 // Make sure the BeginImplFrame from any previous OutputSurfaces
337 // are complete before creating the new OutputSurface.
338 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_IDLE)
339 return false;
341 // We want to clear the pipline of any pending draws and activations
342 // before starting output surface initialization. This allows us to avoid
343 // weird corner cases where we abort draws or force activation while we
344 // are initializing the output surface and can potentially have a pending
345 // readback.
346 if (active_tree_needs_first_draw_ || has_pending_tree_)
347 return false;
349 // We need to create the output surface if we don't have one and we haven't
350 // started creating one yet.
351 return output_surface_state_ == OUTPUT_SURFACE_LOST;
354 bool SchedulerStateMachine::ShouldDraw() const {
355 // After a readback, make sure not to draw again until we've replaced the
356 // readback commit with a real one.
357 if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT ||
358 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION)
359 return false;
361 // Draw immediately for readbacks to unblock the main thread quickly.
362 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK)
363 return true;
365 // If we need to abort draws, we should do so ASAP since the draw could
366 // be blocking other important actions (like output surface initialization),
367 // from occuring. If we are waiting for the first draw, then perfom the
368 // aborted draw to keep things moving. If we are not waiting for the first
369 // draw however, we don't want to abort for no reason.
370 if (PendingDrawsShouldBeAborted())
371 return active_tree_needs_first_draw_;
373 // After this line, we only want to swap once per frame.
374 if (HasSwappedThisFrame())
375 return false;
377 // Do not queue too many swaps.
378 if (pending_swaps_ >= max_pending_swaps_)
379 return false;
381 // Except for the cases above, do not draw outside of the BeginImplFrame
382 // deadline.
383 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
384 return false;
386 // Only handle forced redraws due to timeouts on the regular deadline.
387 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
388 return true;
390 return needs_redraw_;
393 bool SchedulerStateMachine::ShouldActivatePendingTree() const {
394 // There is nothing to activate.
395 if (!has_pending_tree_)
396 return false;
398 // We should not activate a second tree before drawing the first one.
399 // Even if we need to force activation of the pending tree, we should abort
400 // drawing the active tree first.
401 if (active_tree_needs_first_draw_)
402 return false;
404 // If we want to force activation, do so ASAP.
405 if (PendingActivationsShouldBeForced())
406 return true;
408 // At this point, only activate if we are ready to activate.
409 return pending_tree_is_ready_for_activation_;
412 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const {
413 if (!settings_.impl_side_painting)
414 return false;
415 if (HasUpdatedVisibleTilesThisFrame())
416 return false;
418 // There's no reason to check for tiles if we don't have an output surface.
419 if (!HasInitializedOutputSurface())
420 return false;
422 // We should not check for visible tiles until we've entered the deadline so
423 // we check as late as possible and give the tiles more time to initialize.
424 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
425 return false;
427 // If the last swap drew with checkerboard or missing tiles, we should
428 // poll for any new visible tiles so we can be notified to draw again
429 // when there are.
430 if (swap_used_incomplete_tile_)
431 return true;
433 return false;
436 bool SchedulerStateMachine::ShouldAnimate() const {
437 if (!can_draw_)
438 return false;
440 if (last_frame_number_animate_performed_ == current_frame_number_)
441 return false;
443 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING &&
444 begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
445 return false;
447 return needs_redraw_ || needs_animate_;
450 bool SchedulerStateMachine::ShouldSendBeginMainFrame() const {
451 if (!needs_commit_)
452 return false;
454 // Only send BeginMainFrame when there isn't another commit pending already.
455 if (commit_state_ != COMMIT_STATE_IDLE)
456 return false;
458 // Don't send BeginMainFrame early if we are prioritizing the active tree
459 // because of smoothness_takes_priority.
460 if (smoothness_takes_priority_ &&
461 (has_pending_tree_ || active_tree_needs_first_draw_)) {
462 return false;
465 // We want to handle readback commits immediately to unblock the main thread.
466 // Note: This BeginMainFrame will correspond to the replacement commit that
467 // comes after the readback commit itself, so we only send the BeginMainFrame
468 // if a commit isn't already pending behind the readback.
469 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME)
470 return !CommitPending();
472 // We do not need commits if we are not visible, unless there's a
473 // request for a readback.
474 if (!visible_)
475 return false;
477 // We want to start the first commit after we get a new output surface ASAP.
478 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT)
479 return true;
481 // We should not send BeginMainFrame while we are in
482 // BEGIN_IMPL_FRAME_STATE_IDLE since we might have new
483 // user input arriving soon.
484 // TODO(brianderson): Allow sending BeginMainFrame while idle when the main
485 // thread isn't consuming user input.
486 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE &&
487 BeginFrameNeeded())
488 return false;
490 // We need a new commit for the forced redraw. This honors the
491 // single commit per interval because the result will be swapped to screen.
492 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT)
493 return true;
495 // After this point, we only start a commit once per frame.
496 if (HasSentBeginMainFrameThisFrame())
497 return false;
499 // We shouldn't normally accept commits if there isn't an OutputSurface.
500 if (!HasInitializedOutputSurface())
501 return false;
503 // SwapAck throttle the BeginMainFrames
504 // TODO(brianderson): Remove this restriction to improve throughput.
505 if (pending_swaps_ >= max_pending_swaps_)
506 return false;
508 if (skip_begin_main_frame_to_reduce_latency_)
509 return false;
511 return true;
514 bool SchedulerStateMachine::ShouldCommit() const {
515 if (commit_state_ != COMMIT_STATE_READY_TO_COMMIT)
516 return false;
518 // We must not finish the commit until the pending tree is free.
519 if (has_pending_tree_) {
520 DCHECK(settings_.main_frame_before_activation_enabled);
521 return false;
524 // Prioritize drawing the previous commit before finishing the next commit.
525 if (active_tree_needs_first_draw_)
526 return false;
528 return true;
531 bool SchedulerStateMachine::ShouldManageTiles() const {
532 // ManageTiles only really needs to be called immediately after commit
533 // and then periodically after that. Use a funnel to make sure we average
534 // one ManageTiles per BeginImplFrame in the long run.
535 if (manage_tiles_funnel_ > 0)
536 return false;
538 // Limiting to once per-frame is not enough, since we only want to
539 // manage tiles _after_ draws. Polling for draw triggers and
540 // begin-frame are mutually exclusive, so we limit to these two cases.
541 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE &&
542 !inside_poll_for_anticipated_draw_triggers_)
543 return false;
544 return needs_manage_tiles_;
547 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
548 if (ShouldUpdateVisibleTiles())
549 return ACTION_UPDATE_VISIBLE_TILES;
550 if (ShouldActivatePendingTree())
551 return ACTION_ACTIVATE_PENDING_TREE;
552 if (ShouldCommit())
553 return ACTION_COMMIT;
554 if (ShouldAnimate())
555 return ACTION_ANIMATE;
556 if (ShouldDraw()) {
557 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK)
558 return ACTION_DRAW_AND_READBACK;
559 else if (PendingDrawsShouldBeAborted())
560 return ACTION_DRAW_AND_SWAP_ABORT;
561 else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
562 return ACTION_DRAW_AND_SWAP_FORCED;
563 else
564 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
566 if (ShouldManageTiles())
567 return ACTION_MANAGE_TILES;
568 if (ShouldSendBeginMainFrame())
569 return ACTION_SEND_BEGIN_MAIN_FRAME;
570 if (ShouldBeginOutputSurfaceCreation())
571 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION;
572 return ACTION_NONE;
575 void SchedulerStateMachine::CheckInvariants() {
576 // We should never try to perform a draw for readback and forced draw due to
577 // timeout simultaneously.
578 DCHECK(!(forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW &&
579 readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK));
582 void SchedulerStateMachine::UpdateState(Action action) {
583 switch (action) {
584 case ACTION_NONE:
585 return;
587 case ACTION_UPDATE_VISIBLE_TILES:
588 last_frame_number_update_visible_tiles_was_called_ =
589 current_frame_number_;
590 return;
592 case ACTION_ACTIVATE_PENDING_TREE:
593 UpdateStateOnActivation();
594 return;
596 case ACTION_ANIMATE:
597 last_frame_number_animate_performed_ = current_frame_number_;
598 needs_animate_ = false;
599 // TODO(skyostil): Instead of assuming this, require the client to tell
600 // us.
601 SetNeedsRedraw();
602 return;
604 case ACTION_SEND_BEGIN_MAIN_FRAME:
605 DCHECK(!has_pending_tree_ ||
606 settings_.main_frame_before_activation_enabled);
607 DCHECK(!active_tree_needs_first_draw_ ||
608 settings_.main_frame_before_draw_enabled);
609 DCHECK(visible_ ||
610 readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME);
611 commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_SENT;
612 needs_commit_ = false;
613 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME)
614 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
615 last_frame_number_begin_main_frame_sent_ =
616 current_frame_number_;
617 return;
619 case ACTION_COMMIT: {
620 bool commit_was_aborted = false;
621 UpdateStateOnCommit(commit_was_aborted);
622 return;
625 case ACTION_DRAW_AND_SWAP_FORCED:
626 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: {
627 bool did_request_swap = true;
628 UpdateStateOnDraw(did_request_swap);
629 return;
632 case ACTION_DRAW_AND_SWAP_ABORT:
633 case ACTION_DRAW_AND_READBACK: {
634 bool did_request_swap = false;
635 UpdateStateOnDraw(did_request_swap);
636 return;
639 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
640 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST);
641 output_surface_state_ = OUTPUT_SURFACE_CREATING;
643 // The following DCHECKs make sure we are in the proper quiescent state.
644 // The pipeline should be flushed entirely before we start output
645 // surface creation to avoid complicated corner cases.
646 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE);
647 DCHECK(!has_pending_tree_);
648 DCHECK(!active_tree_needs_first_draw_);
649 return;
651 case ACTION_MANAGE_TILES:
652 UpdateStateOnManageTiles();
653 return;
657 void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) {
658 commit_count_++;
660 if (commit_was_aborted || settings_.main_frame_before_activation_enabled) {
661 commit_state_ = COMMIT_STATE_IDLE;
662 } else if (settings_.main_frame_before_draw_enabled) {
663 commit_state_ = settings_.impl_side_painting
664 ? COMMIT_STATE_WAITING_FOR_ACTIVATION
665 : COMMIT_STATE_IDLE;
666 } else {
667 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
670 // If we are impl-side-painting but the commit was aborted, then we behave
671 // mostly as if we are not impl-side-painting since there is no pending tree.
672 has_pending_tree_ = settings_.impl_side_painting && !commit_was_aborted;
674 // Update state related to readbacks.
675 if (readback_state_ == READBACK_STATE_WAITING_FOR_COMMIT) {
676 // Update the state if this is the readback commit.
677 readback_state_ = has_pending_tree_
678 ? READBACK_STATE_WAITING_FOR_ACTIVATION
679 : READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
680 } else if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT) {
681 // Update the state if this is the commit replacing the readback commit.
682 readback_state_ = has_pending_tree_
683 ? READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION
684 : READBACK_STATE_IDLE;
685 } else {
686 DCHECK(readback_state_ == READBACK_STATE_IDLE);
689 // Readbacks can interrupt output surface initialization and forced draws,
690 // so we do not want to advance those states if we are in the middle of a
691 // readback. Note: It is possible for the readback's replacement commit to
692 // be the output surface's first commit and/or the forced redraw's commit.
693 if (readback_state_ == READBACK_STATE_IDLE ||
694 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) {
695 // Update state related to forced draws.
696 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) {
697 forced_redraw_state_ = has_pending_tree_
698 ? FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION
699 : FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
702 // Update the output surface state.
703 DCHECK_NE(output_surface_state_,
704 OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION);
705 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) {
706 if (has_pending_tree_) {
707 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION;
708 } else {
709 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
710 needs_redraw_ = true;
715 // Update state if we have a new active tree to draw, or if the active tree
716 // was unchanged but we need to do a readback or forced draw.
717 if (!has_pending_tree_ &&
718 (!commit_was_aborted ||
719 readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK ||
720 forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)) {
721 needs_redraw_ = true;
722 active_tree_needs_first_draw_ = true;
725 // This post-commit work is common to both completed and aborted commits.
726 pending_tree_is_ready_for_activation_ = false;
728 if (continuous_painting_)
729 needs_commit_ = true;
732 void SchedulerStateMachine::UpdateStateOnActivation() {
733 if (commit_state_ == COMMIT_STATE_WAITING_FOR_ACTIVATION)
734 commit_state_ = COMMIT_STATE_IDLE;
736 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
737 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
739 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION)
740 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
742 if (readback_state_ == READBACK_STATE_WAITING_FOR_ACTIVATION) {
743 readback_state_ = READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
744 } else if (readback_state_ ==
745 READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) {
746 if (needs_back_to_back_readback_) {
747 if (commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT) {
748 // If main_frame_before_activation_enabled is true, it is possible that
749 // we will have already sent the BeginMainFrame here.
750 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
751 } else {
752 // Replacement commit for incoming forced commit should be scheduled
753 // after current commit's draw & swap is finished.
754 needs_commit_ = true;
755 readback_state_ = READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME;
757 needs_back_to_back_readback_ = false;
758 } else {
759 readback_state_ = READBACK_STATE_IDLE;
763 has_pending_tree_ = false;
764 pending_tree_is_ready_for_activation_ = false;
765 active_tree_needs_first_draw_ = true;
766 needs_redraw_ = true;
769 void SchedulerStateMachine::UpdateStateOnDraw(bool did_request_swap) {
770 DCHECK(readback_state_ != READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT &&
771 readback_state_ != READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION)
772 << *AsValue();
774 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) {
775 // The draw corresponds to a readback commit.
776 // We are blocking commits from the main thread until after this draw, so
777 // we should not have a pending tree.
778 DCHECK(!has_pending_tree_);
779 // We transition to COMMIT_STATE_BEGIN_MAIN_FRAME_SENT because there is a
780 // pending BeginMainFrame behind the readback request.
781 commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_SENT;
782 readback_state_ = READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT;
783 } else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
784 forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
787 if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW)
788 commit_state_ = COMMIT_STATE_IDLE;
790 needs_redraw_ = false;
791 active_tree_needs_first_draw_ = false;
793 if (did_request_swap)
794 last_frame_number_swap_performed_ = current_frame_number_;
797 void SchedulerStateMachine::UpdateStateOnManageTiles() {
798 needs_manage_tiles_ = false;
801 void SchedulerStateMachine::SetSkipNextBeginMainFrameToReduceLatency() {
802 skip_next_begin_main_frame_to_reduce_latency_ = true;
805 bool SchedulerStateMachine::BeginFrameNeeded() const {
806 // Proactive BeginFrames are bad for the synchronous compositor because we
807 // have to draw when we get the BeginFrame and could end up drawing many
808 // duplicate frames if our new frame isn't ready in time.
809 // To poll for state with the synchronous compositor without having to draw,
810 // we rely on ShouldPollForAnticipatedDrawTriggers instead.
811 if (!SupportsProactiveBeginFrame())
812 return BeginFrameNeededToAnimateOrDraw();
814 return BeginFrameNeededToAnimateOrDraw() || ProactiveBeginFrameWanted();
817 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const {
818 // ShouldPollForAnticipatedDrawTriggers is what we use in place of
819 // ProactiveBeginFrameWanted when we are using the synchronous
820 // compositor.
821 if (!SupportsProactiveBeginFrame()) {
822 return !BeginFrameNeededToAnimateOrDraw() && ProactiveBeginFrameWanted();
825 // Non synchronous compositors should rely on
826 // ProactiveBeginFrameWanted to poll for state instead.
827 return false;
830 // Note: If SupportsProactiveBeginFrame is false, the scheduler should poll
831 // for changes in it's draw state so it can request a BeginFrame when it's
832 // actually ready.
833 bool SchedulerStateMachine::SupportsProactiveBeginFrame() const {
834 // It is undesirable to proactively request BeginFrames if we are
835 // using a synchronous compositor because we *must* draw for every
836 // BeginFrame, which could cause duplicate draws.
837 return !settings_.using_synchronous_renderer_compositor;
840 // These are the cases where we definitely (or almost definitely) have a
841 // new frame to animate and/or draw and can draw.
842 bool SchedulerStateMachine::BeginFrameNeededToAnimateOrDraw() const {
843 // The output surface is the provider of BeginImplFrames, so we are not going
844 // to get them even if we ask for them.
845 if (!HasInitializedOutputSurface())
846 return false;
848 // If we can't draw, don't tick until we are notified that we can draw again.
849 if (!can_draw_)
850 return false;
852 // The forced draw respects our normal draw scheduling, so we need to
853 // request a BeginImplFrame for it.
854 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
855 return true;
857 // There's no need to produce frames if we are not visible.
858 if (!visible_)
859 return false;
861 // We need to draw a more complete frame than we did the last BeginImplFrame,
862 // so request another BeginImplFrame in anticipation that we will have
863 // additional visible tiles.
864 if (swap_used_incomplete_tile_)
865 return true;
867 if (needs_animate_)
868 return true;
870 return needs_redraw_;
873 // These are cases where we are very likely to draw soon, but might not
874 // actually have a new frame to draw when we receive the next BeginImplFrame.
875 // Proactively requesting the BeginImplFrame helps hide the round trip latency
876 // of the SetNeedsBeginFrame request that has to go to the Browser.
877 bool SchedulerStateMachine::ProactiveBeginFrameWanted() const {
878 // The output surface is the provider of BeginImplFrames,
879 // so we are not going to get them even if we ask for them.
880 if (!HasInitializedOutputSurface())
881 return false;
883 // Do not be proactive when invisible.
884 if (!visible_)
885 return false;
887 // We should proactively request a BeginImplFrame if a commit is pending
888 // because we will want to draw if the commit completes quickly.
889 if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE)
890 return true;
892 // If the pending tree activates quickly, we'll want a BeginImplFrame soon
893 // to draw the new active tree.
894 if (has_pending_tree_)
895 return true;
897 // Changing priorities may allow us to activate (given the new priorities),
898 // which may result in a new frame.
899 if (needs_manage_tiles_)
900 return true;
902 // If we just swapped, it's likely that we are going to produce another
903 // frame soon. This helps avoid negative glitches in our
904 // SetNeedsBeginFrame requests, which may propagate to the BeginImplFrame
905 // provider and get sampled at an inopportune time, delaying the next
906 // BeginImplFrame.
907 if (last_frame_number_swap_performed_ == current_frame_number_)
908 return true;
910 return false;
913 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) {
914 AdvanceCurrentFrameNumber();
915 begin_impl_frame_args_ = args;
916 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) << *AsValue();
917 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING;
920 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() {
921 DCHECK_EQ(begin_impl_frame_state_,
922 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING)
923 << *AsValue();
924 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME;
927 void SchedulerStateMachine::OnBeginImplFrameDeadline() {
928 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
929 << *AsValue();
930 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
933 void SchedulerStateMachine::OnBeginImplFrameIdle() {
934 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
935 << *AsValue();
936 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE;
939 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineEarly() const {
940 // TODO(brianderson): This should take into account multiple commit sources.
942 // If we are in the middle of the readback, we won't swap, so there is
943 // no reason to trigger the deadline early.
944 if (readback_state_ != READBACK_STATE_IDLE)
945 return false;
947 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
948 return false;
950 // If we've lost the output surface, end the current BeginImplFrame ASAP
951 // so we can start creating the next output surface.
952 if (output_surface_state_ == OUTPUT_SURFACE_LOST)
953 return true;
955 // SwapAck throttle the deadline since we wont draw and swap anyway.
956 if (pending_swaps_ >= max_pending_swaps_)
957 return false;
959 if (active_tree_needs_first_draw_)
960 return true;
962 if (!needs_redraw_)
963 return false;
965 // This is used to prioritize impl-thread draws when the main thread isn't
966 // producing anything, e.g., after an aborted commit. We also check that we
967 // don't have a pending tree -- otherwise we should give it a chance to
968 // activate.
969 // TODO(skyostil): Revisit this when we have more accurate deadline estimates.
970 if (commit_state_ == COMMIT_STATE_IDLE && !has_pending_tree_)
971 return true;
973 // Prioritize impl-thread draws in smoothness mode.
974 if (smoothness_takes_priority_)
975 return true;
977 return false;
980 bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const {
981 // If a commit is pending before the previous commit has been drawn, we
982 // are definitely in a high latency mode.
983 if (CommitPending() && (active_tree_needs_first_draw_ || has_pending_tree_))
984 return true;
986 // If we just sent a BeginMainFrame and haven't hit the deadline yet, the main
987 // thread is in a low latency mode.
988 if (last_frame_number_begin_main_frame_sent_ == current_frame_number_ &&
989 (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING ||
990 begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME))
991 return false;
993 // If there's a commit in progress it must either be from the previous frame
994 // or it started after the impl thread's deadline. In either case the main
995 // thread is in high latency mode.
996 if (commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
997 commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED ||
998 commit_state_ == COMMIT_STATE_READY_TO_COMMIT)
999 return true;
1001 // Similarly, if there's a pending tree the main thread is in high latency
1002 // mode, because either
1003 // it's from the previous frame
1004 // or
1005 // we're currently drawing the active tree and the pending tree will thus
1006 // only be drawn in the next frame.
1007 if (has_pending_tree_)
1008 return true;
1010 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) {
1011 // Even if there's a new active tree to draw at the deadline or we've just
1012 // drawn it, it may have been triggered by a previous BeginImplFrame, in
1013 // which case the main thread is in a high latency mode.
1014 return (active_tree_needs_first_draw_ ||
1015 last_frame_number_swap_performed_ == current_frame_number_) &&
1016 last_frame_number_begin_main_frame_sent_ != current_frame_number_;
1019 // If the active tree needs its first draw in any other state, we know the
1020 // main thread is in a high latency mode.
1021 return active_tree_needs_first_draw_;
1024 void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() {
1025 AdvanceCurrentFrameNumber();
1026 inside_poll_for_anticipated_draw_triggers_ = true;
1029 void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() {
1030 inside_poll_for_anticipated_draw_triggers_ = false;
1033 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }
1035 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }
1037 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }
1039 void SchedulerStateMachine::SetNeedsAnimate() {
1040 needs_animate_ = true;
1043 void SchedulerStateMachine::SetNeedsManageTiles() {
1044 if (!needs_manage_tiles_) {
1045 TRACE_EVENT0("cc",
1046 "SchedulerStateMachine::SetNeedsManageTiles");
1047 needs_manage_tiles_ = true;
1051 void SchedulerStateMachine::SetMaxSwapsPending(int max) {
1052 max_pending_swaps_ = max;
1055 void SchedulerStateMachine::DidSwapBuffers() {
1056 pending_swaps_++;
1057 DCHECK_LE(pending_swaps_, max_pending_swaps_);
1060 void SchedulerStateMachine::SetSwapUsedIncompleteTile(
1061 bool used_incomplete_tile) {
1062 swap_used_incomplete_tile_ = used_incomplete_tile;
1065 void SchedulerStateMachine::DidSwapBuffersComplete() {
1066 DCHECK_GT(pending_swaps_, 0);
1067 pending_swaps_--;
1070 void SchedulerStateMachine::SetSmoothnessTakesPriority(
1071 bool smoothness_takes_priority) {
1072 smoothness_takes_priority_ = smoothness_takes_priority;
1075 void SchedulerStateMachine::DidDrawIfPossibleCompleted(
1076 DrawSwapReadbackResult::DrawResult result) {
1077 switch (result) {
1078 case DrawSwapReadbackResult::INVALID_RESULT:
1079 NOTREACHED() << "Uninitialized DrawSwapReadbackResult.";
1080 break;
1081 case DrawSwapReadbackResult::DRAW_ABORTED_CANT_DRAW:
1082 case DrawSwapReadbackResult::DRAW_ABORTED_CANT_READBACK:
1083 case DrawSwapReadbackResult::DRAW_ABORTED_CONTEXT_LOST:
1084 NOTREACHED() << "Invalid return value from DrawAndSwapIfPossible:"
1085 << result;
1086 break;
1087 case DrawSwapReadbackResult::DRAW_SUCCESS:
1088 consecutive_checkerboard_animations_ = 0;
1089 forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
1090 break;
1091 case DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS:
1092 needs_redraw_ = true;
1094 // If we're already in the middle of a redraw, we don't need to
1095 // restart it.
1096 if (forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE)
1097 return;
1099 needs_commit_ = true;
1100 consecutive_checkerboard_animations_++;
1101 if (settings_.timeout_and_draw_when_animation_checkerboards &&
1102 consecutive_checkerboard_animations_ >=
1103 settings_.maximum_number_of_failed_draws_before_draw_is_forced_) {
1104 consecutive_checkerboard_animations_ = 0;
1105 // We need to force a draw, but it doesn't make sense to do this until
1106 // we've committed and have new textures.
1107 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT;
1109 break;
1110 case DrawSwapReadbackResult::DRAW_ABORTED_MISSING_HIGH_RES_CONTENT:
1111 // It's not clear whether this missing content is because of missing
1112 // pictures (which requires a commit) or because of memory pressure
1113 // removing textures (which might not). To be safe, request a commit
1114 // anyway.
1115 needs_commit_ = true;
1116 break;
1120 void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; }
1122 void SchedulerStateMachine::SetNeedsForcedCommitForReadback() {
1123 // If this is called in READBACK_STATE_IDLE, this is a "first" readback
1124 // request.
1125 // If this is called in READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT, this
1126 // is a back-to-back readback request that started before the replacement
1127 // commit had a chance to land.
1128 // If this is called in READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION,
1129 // this is a readback-commit-readback request when replacement commit is in
1130 // impl-side painting.
1131 DCHECK(readback_state_ == READBACK_STATE_IDLE ||
1132 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT ||
1133 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION);
1135 if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) {
1136 // If new forced commit is requested when impl-side painting of replacement
1137 // commit is in progress, it should not interrupt the draw & swap of current
1138 // commit(replacement commit). New commit(incoming forced commit) should be
1139 // started after current commit is finished.
1140 needs_back_to_back_readback_ = true;
1141 } else if (commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT) {
1142 // If there is already a commit in progress when we get the readback request
1143 // then we don't need to send a BeginMainFrame for the replacement commit,
1144 // since there's already a BeginMainFrame behind the readback request. In
1145 // that case, we can skip READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME and go
1146 // directly to READBACK_STATE_WAITING_FOR_COMMIT.
1147 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
1148 } else {
1149 // Set needs_commit_ to true to trigger scheduling BeginMainFrame().
1150 needs_commit_ = true;
1151 readback_state_ = READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME;
1155 void SchedulerStateMachine::NotifyReadyToCommit() {
1156 DCHECK(commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED) << *AsValue();
1157 commit_state_ = COMMIT_STATE_READY_TO_COMMIT;
1160 void SchedulerStateMachine::BeginMainFrameAborted(bool did_handle) {
1161 DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
1162 if (did_handle) {
1163 bool commit_was_aborted = true;
1164 UpdateStateOnCommit(commit_was_aborted);
1165 } else {
1166 DCHECK_NE(readback_state_, READBACK_STATE_WAITING_FOR_COMMIT);
1167 commit_state_ = COMMIT_STATE_IDLE;
1168 SetNeedsCommit();
1172 void SchedulerStateMachine::DidManageTiles() {
1173 needs_manage_tiles_ = false;
1174 // "Fill" the ManageTiles funnel.
1175 manage_tiles_funnel_++;
1178 void SchedulerStateMachine::DidLoseOutputSurface() {
1179 if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
1180 output_surface_state_ == OUTPUT_SURFACE_CREATING)
1181 return;
1182 output_surface_state_ = OUTPUT_SURFACE_LOST;
1183 needs_redraw_ = false;
1186 void SchedulerStateMachine::NotifyReadyToActivate() {
1187 if (has_pending_tree_)
1188 pending_tree_is_ready_for_activation_ = true;
1191 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
1192 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING);
1193 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT;
1195 if (did_create_and_initialize_first_output_surface_) {
1196 // TODO(boliu): See if we can remove this when impl-side painting is always
1197 // on. Does anything on the main thread need to update after recreate?
1198 needs_commit_ = true;
1200 did_create_and_initialize_first_output_surface_ = true;
1201 pending_swaps_ = 0;
1204 void SchedulerStateMachine::NotifyBeginMainFrameStarted() {
1205 DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
1207 DCHECK(readback_state_ == READBACK_STATE_IDLE ||
1208 readback_state_ == READBACK_STATE_WAITING_FOR_COMMIT ||
1209 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT);
1211 commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED;
1214 bool SchedulerStateMachine::HasInitializedOutputSurface() const {
1215 switch (output_surface_state_) {
1216 case OUTPUT_SURFACE_LOST:
1217 case OUTPUT_SURFACE_CREATING:
1218 return false;
1220 case OUTPUT_SURFACE_ACTIVE:
1221 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
1222 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
1223 return true;
1225 NOTREACHED();
1226 return false;
1229 } // namespace cc