Revert 264226 "Reduce dependency of TiclInvalidationService on P..."
[chromium-blink-merge.git] / cc / scheduler / scheduler_state_machine.cc
blob9a08819081ec08e1aac732abc73f56c41e97a4c3
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_swap_performed_(-1),
26 last_frame_number_begin_main_frame_sent_(-1),
27 last_frame_number_update_visible_tiles_was_called_(-1),
28 manage_tiles_funnel_(0),
29 consecutive_checkerboard_animations_(0),
30 needs_redraw_(false),
31 needs_manage_tiles_(false),
32 swap_used_incomplete_tile_(false),
33 needs_commit_(false),
34 inside_poll_for_anticipated_draw_triggers_(false),
35 visible_(false),
36 can_start_(false),
37 can_draw_(false),
38 has_pending_tree_(false),
39 pending_tree_is_ready_for_activation_(false),
40 active_tree_needs_first_draw_(false),
41 draw_if_possible_failed_(false),
42 did_create_and_initialize_first_output_surface_(false),
43 smoothness_takes_priority_(false),
44 skip_next_begin_main_frame_to_reduce_latency_(false),
45 skip_begin_main_frame_to_reduce_latency_(false),
46 continuous_painting_(false),
47 needs_back_to_back_readback_(false) {}
49 const char* SchedulerStateMachine::OutputSurfaceStateToString(
50 OutputSurfaceState state) {
51 switch (state) {
52 case OUTPUT_SURFACE_ACTIVE:
53 return "OUTPUT_SURFACE_ACTIVE";
54 case OUTPUT_SURFACE_LOST:
55 return "OUTPUT_SURFACE_LOST";
56 case OUTPUT_SURFACE_CREATING:
57 return "OUTPUT_SURFACE_CREATING";
58 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
59 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT";
60 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
61 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION";
63 NOTREACHED();
64 return "???";
67 const char* SchedulerStateMachine::BeginImplFrameStateToString(
68 BeginImplFrameState state) {
69 switch (state) {
70 case BEGIN_IMPL_FRAME_STATE_IDLE:
71 return "BEGIN_IMPL_FRAME_STATE_IDLE";
72 case BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING:
73 return "BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING";
74 case BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME:
75 return "BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME";
76 case BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE:
77 return "BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE";
79 NOTREACHED();
80 return "???";
83 const char* SchedulerStateMachine::CommitStateToString(CommitState state) {
84 switch (state) {
85 case COMMIT_STATE_IDLE:
86 return "COMMIT_STATE_IDLE";
87 case COMMIT_STATE_BEGIN_MAIN_FRAME_SENT:
88 return "COMMIT_STATE_BEGIN_MAIN_FRAME_SENT";
89 case COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED:
90 return "COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED";
91 case COMMIT_STATE_READY_TO_COMMIT:
92 return "COMMIT_STATE_READY_TO_COMMIT";
93 case COMMIT_STATE_WAITING_FOR_ACTIVATION:
94 return "COMMIT_STATE_WAITING_FOR_ACTIVATION";
95 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW:
96 return "COMMIT_STATE_WAITING_FOR_FIRST_DRAW";
98 NOTREACHED();
99 return "???";
102 const char* SchedulerStateMachine::SynchronousReadbackStateToString(
103 SynchronousReadbackState state) {
104 switch (state) {
105 case READBACK_STATE_IDLE:
106 return "READBACK_STATE_IDLE";
107 case READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME:
108 return "READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME";
109 case READBACK_STATE_WAITING_FOR_COMMIT:
110 return "READBACK_STATE_WAITING_FOR_COMMIT";
111 case READBACK_STATE_WAITING_FOR_ACTIVATION:
112 return "READBACK_STATE_WAITING_FOR_ACTIVATION";
113 case READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK:
114 return "READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK";
115 case READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT:
116 return "READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT";
117 case READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION:
118 return "READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION";
120 NOTREACHED();
121 return "???";
124 const char* SchedulerStateMachine::ForcedRedrawOnTimeoutStateToString(
125 ForcedRedrawOnTimeoutState state) {
126 switch (state) {
127 case FORCED_REDRAW_STATE_IDLE:
128 return "FORCED_REDRAW_STATE_IDLE";
129 case FORCED_REDRAW_STATE_WAITING_FOR_COMMIT:
130 return "FORCED_REDRAW_STATE_WAITING_FOR_COMMIT";
131 case FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION:
132 return "FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION";
133 case FORCED_REDRAW_STATE_WAITING_FOR_DRAW:
134 return "FORCED_REDRAW_STATE_WAITING_FOR_DRAW";
136 NOTREACHED();
137 return "???";
140 const char* SchedulerStateMachine::ActionToString(Action action) {
141 switch (action) {
142 case ACTION_NONE:
143 return "ACTION_NONE";
144 case ACTION_SEND_BEGIN_MAIN_FRAME:
145 return "ACTION_SEND_BEGIN_MAIN_FRAME";
146 case ACTION_COMMIT:
147 return "ACTION_COMMIT";
148 case ACTION_UPDATE_VISIBLE_TILES:
149 return "ACTION_UPDATE_VISIBLE_TILES";
150 case ACTION_ACTIVATE_PENDING_TREE:
151 return "ACTION_ACTIVATE_PENDING_TREE";
152 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
153 return "ACTION_DRAW_AND_SWAP_IF_POSSIBLE";
154 case ACTION_DRAW_AND_SWAP_FORCED:
155 return "ACTION_DRAW_AND_SWAP_FORCED";
156 case ACTION_DRAW_AND_SWAP_ABORT:
157 return "ACTION_DRAW_AND_SWAP_ABORT";
158 case ACTION_DRAW_AND_READBACK:
159 return "ACTION_DRAW_AND_READBACK";
160 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
161 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION";
162 case ACTION_MANAGE_TILES:
163 return "ACTION_MANAGE_TILES";
165 NOTREACHED();
166 return "???";
169 scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const {
170 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
172 scoped_ptr<base::DictionaryValue> major_state(new base::DictionaryValue);
173 major_state->SetString("next_action", ActionToString(NextAction()));
174 major_state->SetString("begin_impl_frame_state",
175 BeginImplFrameStateToString(begin_impl_frame_state_));
176 major_state->SetString("commit_state", CommitStateToString(commit_state_));
177 major_state->SetString("output_surface_state_",
178 OutputSurfaceStateToString(output_surface_state_));
179 major_state->SetString(
180 "forced_redraw_state",
181 ForcedRedrawOnTimeoutStateToString(forced_redraw_state_));
182 major_state->SetString("readback_state",
183 SynchronousReadbackStateToString(readback_state_));
184 state->Set("major_state", major_state.release());
186 scoped_ptr<base::DictionaryValue> timestamps_state(new base::DictionaryValue);
187 base::TimeTicks now = gfx::FrameTime::Now();
188 timestamps_state->SetDouble(
189 "0_interval", begin_impl_frame_args_.interval.InMicroseconds() / 1000.0L);
190 timestamps_state->SetDouble(
191 "1_now_to_deadline",
192 (begin_impl_frame_args_.deadline - now).InMicroseconds() / 1000.0L);
193 timestamps_state->SetDouble(
194 "2_frame_time_to_now",
195 (now - begin_impl_frame_args_.frame_time).InMicroseconds() / 1000.0L);
196 timestamps_state->SetDouble(
197 "3_frame_time_to_deadline",
198 (begin_impl_frame_args_.deadline - begin_impl_frame_args_.frame_time)
199 .InMicroseconds() /
200 1000.0L);
201 timestamps_state->SetDouble(
202 "4_now", (now - base::TimeTicks()).InMicroseconds() / 1000.0L);
203 timestamps_state->SetDouble(
204 "5_frame_time",
205 (begin_impl_frame_args_.frame_time - base::TimeTicks()).InMicroseconds() /
206 1000.0L);
207 timestamps_state->SetDouble(
208 "6_deadline",
209 (begin_impl_frame_args_.deadline - base::TimeTicks()).InMicroseconds() /
210 1000.0L);
211 state->Set("major_timestamps_in_ms", timestamps_state.release());
213 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue);
214 minor_state->SetInteger("commit_count", commit_count_);
215 minor_state->SetInteger("current_frame_number", current_frame_number_);
217 minor_state->SetInteger("last_frame_number_swap_performed",
218 last_frame_number_swap_performed_);
219 minor_state->SetInteger(
220 "last_frame_number_begin_main_frame_sent",
221 last_frame_number_begin_main_frame_sent_);
222 minor_state->SetInteger(
223 "last_frame_number_update_visible_tiles_was_called",
224 last_frame_number_update_visible_tiles_was_called_);
226 minor_state->SetInteger("manage_tiles_funnel", manage_tiles_funnel_);
227 minor_state->SetInteger("consecutive_checkerboard_animations",
228 consecutive_checkerboard_animations_);
229 minor_state->SetBoolean("needs_redraw", needs_redraw_);
230 minor_state->SetBoolean("needs_manage_tiles", needs_manage_tiles_);
231 minor_state->SetBoolean("swap_used_incomplete_tile",
232 swap_used_incomplete_tile_);
233 minor_state->SetBoolean("needs_commit", needs_commit_);
234 minor_state->SetBoolean("visible", visible_);
235 minor_state->SetBoolean("can_start", can_start_);
236 minor_state->SetBoolean("can_draw", can_draw_);
237 minor_state->SetBoolean("has_pending_tree", has_pending_tree_);
238 minor_state->SetBoolean("pending_tree_is_ready_for_activation",
239 pending_tree_is_ready_for_activation_);
240 minor_state->SetBoolean("active_tree_needs_first_draw",
241 active_tree_needs_first_draw_);
242 minor_state->SetBoolean("draw_if_possible_failed", draw_if_possible_failed_);
243 minor_state->SetBoolean("did_create_and_initialize_first_output_surface",
244 did_create_and_initialize_first_output_surface_);
245 minor_state->SetBoolean("smoothness_takes_priority",
246 smoothness_takes_priority_);
247 minor_state->SetBoolean("main_thread_is_in_high_latency_mode",
248 MainThreadIsInHighLatencyMode());
249 minor_state->SetBoolean("skip_begin_main_frame_to_reduce_latency",
250 skip_begin_main_frame_to_reduce_latency_);
251 minor_state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency",
252 skip_next_begin_main_frame_to_reduce_latency_);
253 minor_state->SetBoolean("continuous_painting", continuous_painting_);
254 state->Set("minor_state", minor_state.release());
256 return state.PassAs<base::Value>();
259 void SchedulerStateMachine::AdvanceCurrentFrameNumber() {
260 current_frame_number_++;
262 // "Drain" the ManageTiles funnel.
263 if (manage_tiles_funnel_ > 0)
264 manage_tiles_funnel_--;
266 skip_begin_main_frame_to_reduce_latency_ =
267 skip_next_begin_main_frame_to_reduce_latency_;
268 skip_next_begin_main_frame_to_reduce_latency_ = false;
271 bool SchedulerStateMachine::HasSentBeginMainFrameThisFrame() const {
272 return current_frame_number_ ==
273 last_frame_number_begin_main_frame_sent_;
276 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const {
277 return current_frame_number_ ==
278 last_frame_number_update_visible_tiles_was_called_;
281 bool SchedulerStateMachine::HasSwappedThisFrame() const {
282 return current_frame_number_ == last_frame_number_swap_performed_;
285 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const {
286 // These are all the cases where we normally cannot or do not want to draw
287 // but, if needs_redraw_ is true and we do not draw to make forward progress,
288 // we might deadlock with the main thread.
289 // This should be a superset of PendingActivationsShouldBeForced() since
290 // activation of the pending tree is blocked by drawing of the active tree and
291 // the main thread might be blocked on activation of the most recent commit.
292 if (PendingActivationsShouldBeForced())
293 return true;
295 // Additional states where we should abort draws.
296 // Note: We don't force activation in these cases because doing so would
297 // result in checkerboarding on resize, becoming visible, etc.
298 if (!can_draw_)
299 return true;
300 if (!visible_)
301 return true;
302 return false;
305 bool SchedulerStateMachine::PendingActivationsShouldBeForced() const {
306 // These are all the cases where, if we do not force activations to make
307 // forward progress, we might deadlock with the main thread.
309 // There is no output surface to trigger our activations.
310 if (output_surface_state_ == OUTPUT_SURFACE_LOST)
311 return true;
313 return false;
316 bool SchedulerStateMachine::ShouldBeginOutputSurfaceCreation() const {
317 // Don't try to initialize too early.
318 if (!can_start_)
319 return false;
321 // We only want to start output surface initialization after the
322 // previous commit is complete.
323 if (commit_state_ != COMMIT_STATE_IDLE)
324 return false;
326 // Make sure the BeginImplFrame from any previous OutputSurfaces
327 // are complete before creating the new OutputSurface.
328 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_IDLE)
329 return false;
331 // We want to clear the pipline of any pending draws and activations
332 // before starting output surface initialization. This allows us to avoid
333 // weird corner cases where we abort draws or force activation while we
334 // are initializing the output surface and can potentially have a pending
335 // readback.
336 if (active_tree_needs_first_draw_ || has_pending_tree_)
337 return false;
339 // We need to create the output surface if we don't have one and we haven't
340 // started creating one yet.
341 return output_surface_state_ == OUTPUT_SURFACE_LOST;
344 bool SchedulerStateMachine::ShouldDraw() const {
345 // After a readback, make sure not to draw again until we've replaced the
346 // readback commit with a real one.
347 if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT ||
348 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION)
349 return false;
351 // Draw immediately for readbacks to unblock the main thread quickly.
352 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK)
353 return true;
355 // If we need to abort draws, we should do so ASAP since the draw could
356 // be blocking other important actions (like output surface initialization),
357 // from occuring. If we are waiting for the first draw, then perfom the
358 // aborted draw to keep things moving. If we are not waiting for the first
359 // draw however, we don't want to abort for no reason.
360 if (PendingDrawsShouldBeAborted())
361 return active_tree_needs_first_draw_;
363 // After this line, we only want to swap once per frame.
364 if (HasSwappedThisFrame())
365 return false;
367 // Except for the cases above, do not draw outside of the BeginImplFrame
368 // deadline.
369 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
370 return false;
372 // Only handle forced redraws due to timeouts on the regular deadline.
373 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
374 return true;
376 return needs_redraw_;
379 bool SchedulerStateMachine::ShouldActivatePendingTree() const {
380 // There is nothing to activate.
381 if (!has_pending_tree_)
382 return false;
384 // We should not activate a second tree before drawing the first one.
385 // Even if we need to force activation of the pending tree, we should abort
386 // drawing the active tree first.
387 if (active_tree_needs_first_draw_)
388 return false;
390 // If we want to force activation, do so ASAP.
391 if (PendingActivationsShouldBeForced())
392 return true;
394 // At this point, only activate if we are ready to activate.
395 return pending_tree_is_ready_for_activation_;
398 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const {
399 if (!settings_.impl_side_painting)
400 return false;
401 if (HasUpdatedVisibleTilesThisFrame())
402 return false;
404 // There's no reason to check for tiles if we don't have an output surface.
405 if (!HasInitializedOutputSurface())
406 return false;
408 // We should not check for visible tiles until we've entered the deadline so
409 // we check as late as possible and give the tiles more time to initialize.
410 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
411 return false;
413 // If the last swap drew with checkerboard or missing tiles, we should
414 // poll for any new visible tiles so we can be notified to draw again
415 // when there are.
416 if (swap_used_incomplete_tile_)
417 return true;
419 return false;
422 bool SchedulerStateMachine::ShouldSendBeginMainFrame() const {
423 if (!needs_commit_)
424 return false;
426 // Only send BeginMainFrame when there isn't another commit pending already.
427 if (commit_state_ != COMMIT_STATE_IDLE)
428 return false;
430 // Don't send BeginMainFrame early if we are prioritizing the active tree
431 // because of smoothness_takes_priority.
432 if (smoothness_takes_priority_ &&
433 (has_pending_tree_ || active_tree_needs_first_draw_)) {
434 return false;
437 // We want to handle readback commits immediately to unblock the main thread.
438 // Note: This BeginMainFrame will correspond to the replacement commit that
439 // comes after the readback commit itself, so we only send the BeginMainFrame
440 // if a commit isn't already pending behind the readback.
441 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME)
442 return !CommitPending();
444 // We do not need commits if we are not visible, unless there's a
445 // request for a readback.
446 if (!visible_)
447 return false;
449 // We want to start the first commit after we get a new output surface ASAP.
450 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT)
451 return true;
453 // We should not send BeginMainFrame while we are in
454 // BEGIN_IMPL_FRAME_STATE_IDLE since we might have new
455 // user input arriving soon.
456 // TODO(brianderson): Allow sending BeginMainFrame while idle when the main
457 // thread isn't consuming user input.
458 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE &&
459 BeginFrameNeeded())
460 return false;
462 // We need a new commit for the forced redraw. This honors the
463 // single commit per interval because the result will be swapped to screen.
464 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT)
465 return true;
467 // After this point, we only start a commit once per frame.
468 if (HasSentBeginMainFrameThisFrame())
469 return false;
471 // We shouldn't normally accept commits if there isn't an OutputSurface.
472 if (!HasInitializedOutputSurface())
473 return false;
475 if (skip_begin_main_frame_to_reduce_latency_)
476 return false;
478 return true;
481 bool SchedulerStateMachine::ShouldCommit() const {
482 if (commit_state_ != COMMIT_STATE_READY_TO_COMMIT)
483 return false;
485 // We must not finish the commit until the pending tree is free.
486 if (has_pending_tree_) {
487 DCHECK(settings_.main_frame_before_activation_enabled);
488 return false;
491 // Prioritize drawing the previous commit before finishing the next commit.
492 if (active_tree_needs_first_draw_)
493 return false;
495 return true;
498 bool SchedulerStateMachine::ShouldManageTiles() const {
499 // ManageTiles only really needs to be called immediately after commit
500 // and then periodically after that. Use a funnel to make sure we average
501 // one ManageTiles per BeginImplFrame in the long run.
502 if (manage_tiles_funnel_ > 0)
503 return false;
505 // Limiting to once per-frame is not enough, since we only want to
506 // manage tiles _after_ draws. Polling for draw triggers and
507 // begin-frame are mutually exclusive, so we limit to these two cases.
508 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE &&
509 !inside_poll_for_anticipated_draw_triggers_)
510 return false;
511 return needs_manage_tiles_;
514 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
515 if (ShouldUpdateVisibleTiles())
516 return ACTION_UPDATE_VISIBLE_TILES;
517 if (ShouldActivatePendingTree())
518 return ACTION_ACTIVATE_PENDING_TREE;
519 if (ShouldCommit())
520 return ACTION_COMMIT;
521 if (ShouldDraw()) {
522 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK)
523 return ACTION_DRAW_AND_READBACK;
524 else if (PendingDrawsShouldBeAborted())
525 return ACTION_DRAW_AND_SWAP_ABORT;
526 else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
527 return ACTION_DRAW_AND_SWAP_FORCED;
528 else
529 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
531 if (ShouldManageTiles())
532 return ACTION_MANAGE_TILES;
533 if (ShouldSendBeginMainFrame())
534 return ACTION_SEND_BEGIN_MAIN_FRAME;
535 if (ShouldBeginOutputSurfaceCreation())
536 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION;
537 return ACTION_NONE;
540 void SchedulerStateMachine::CheckInvariants() {
541 // We should never try to perform a draw for readback and forced draw due to
542 // timeout simultaneously.
543 DCHECK(!(forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW &&
544 readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK));
547 void SchedulerStateMachine::UpdateState(Action action) {
548 switch (action) {
549 case ACTION_NONE:
550 return;
552 case ACTION_UPDATE_VISIBLE_TILES:
553 last_frame_number_update_visible_tiles_was_called_ =
554 current_frame_number_;
555 return;
557 case ACTION_ACTIVATE_PENDING_TREE:
558 UpdateStateOnActivation();
559 return;
561 case ACTION_SEND_BEGIN_MAIN_FRAME:
562 DCHECK(!has_pending_tree_ ||
563 settings_.main_frame_before_activation_enabled);
564 DCHECK(!active_tree_needs_first_draw_ ||
565 settings_.main_frame_before_draw_enabled);
566 DCHECK(visible_ ||
567 readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME);
568 commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_SENT;
569 needs_commit_ = false;
570 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME)
571 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
572 last_frame_number_begin_main_frame_sent_ =
573 current_frame_number_;
574 return;
576 case ACTION_COMMIT: {
577 bool commit_was_aborted = false;
578 UpdateStateOnCommit(commit_was_aborted);
579 return;
582 case ACTION_DRAW_AND_SWAP_FORCED:
583 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: {
584 bool did_swap = true;
585 UpdateStateOnDraw(did_swap);
586 return;
589 case ACTION_DRAW_AND_SWAP_ABORT:
590 case ACTION_DRAW_AND_READBACK: {
591 bool did_swap = false;
592 UpdateStateOnDraw(did_swap);
593 return;
596 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
597 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST);
598 output_surface_state_ = OUTPUT_SURFACE_CREATING;
600 // The following DCHECKs make sure we are in the proper quiescent state.
601 // The pipeline should be flushed entirely before we start output
602 // surface creation to avoid complicated corner cases.
603 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE);
604 DCHECK(!has_pending_tree_);
605 DCHECK(!active_tree_needs_first_draw_);
606 return;
608 case ACTION_MANAGE_TILES:
609 UpdateStateOnManageTiles();
610 return;
614 void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) {
615 commit_count_++;
617 if (commit_was_aborted || settings_.main_frame_before_activation_enabled) {
618 commit_state_ = COMMIT_STATE_IDLE;
619 } else if (settings_.main_frame_before_draw_enabled) {
620 commit_state_ = settings_.impl_side_painting
621 ? COMMIT_STATE_WAITING_FOR_ACTIVATION
622 : COMMIT_STATE_IDLE;
623 } else {
624 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
627 // If we are impl-side-painting but the commit was aborted, then we behave
628 // mostly as if we are not impl-side-painting since there is no pending tree.
629 has_pending_tree_ = settings_.impl_side_painting && !commit_was_aborted;
631 // Update state related to readbacks.
632 if (readback_state_ == READBACK_STATE_WAITING_FOR_COMMIT) {
633 // Update the state if this is the readback commit.
634 readback_state_ = has_pending_tree_
635 ? READBACK_STATE_WAITING_FOR_ACTIVATION
636 : READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
637 } else if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT) {
638 // Update the state if this is the commit replacing the readback commit.
639 readback_state_ = has_pending_tree_
640 ? READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION
641 : READBACK_STATE_IDLE;
642 } else {
643 DCHECK(readback_state_ == READBACK_STATE_IDLE);
646 // Readbacks can interrupt output surface initialization and forced draws,
647 // so we do not want to advance those states if we are in the middle of a
648 // readback. Note: It is possible for the readback's replacement commit to
649 // be the output surface's first commit and/or the forced redraw's commit.
650 if (readback_state_ == READBACK_STATE_IDLE ||
651 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) {
652 // Update state related to forced draws.
653 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) {
654 forced_redraw_state_ = has_pending_tree_
655 ? FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION
656 : FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
659 // Update the output surface state.
660 DCHECK_NE(output_surface_state_,
661 OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION);
662 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) {
663 if (has_pending_tree_) {
664 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION;
665 } else {
666 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
667 needs_redraw_ = true;
672 // Update state if we have a new active tree to draw, or if the active tree
673 // was unchanged but we need to do a readback or forced draw.
674 if (!has_pending_tree_ &&
675 (!commit_was_aborted ||
676 readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK ||
677 forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)) {
678 needs_redraw_ = true;
679 active_tree_needs_first_draw_ = true;
682 // This post-commit work is common to both completed and aborted commits.
683 pending_tree_is_ready_for_activation_ = false;
685 if (draw_if_possible_failed_)
686 last_frame_number_swap_performed_ = -1;
688 if (continuous_painting_)
689 needs_commit_ = true;
692 void SchedulerStateMachine::UpdateStateOnActivation() {
693 if (commit_state_ == COMMIT_STATE_WAITING_FOR_ACTIVATION)
694 commit_state_ = COMMIT_STATE_IDLE;
696 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
697 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
699 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION)
700 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
702 if (readback_state_ == READBACK_STATE_WAITING_FOR_ACTIVATION) {
703 readback_state_ = READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
704 } else if (readback_state_ ==
705 READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) {
706 if (needs_back_to_back_readback_) {
707 if (commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT) {
708 // If main_frame_before_activation_enabled is true, it is possible that
709 // we will have already sent the BeginMainFrame here.
710 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
711 } else {
712 // Replacement commit for incoming forced commit should be scheduled
713 // after current commit's draw & swap is finished.
714 needs_commit_ = true;
715 readback_state_ = READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME;
717 needs_back_to_back_readback_ = false;
718 } else {
719 readback_state_ = READBACK_STATE_IDLE;
723 has_pending_tree_ = false;
724 pending_tree_is_ready_for_activation_ = false;
725 active_tree_needs_first_draw_ = true;
726 needs_redraw_ = true;
729 void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) {
730 DCHECK(readback_state_ != READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT &&
731 readback_state_ != READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION)
732 << *AsValue();
734 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) {
735 // The draw corresponds to a readback commit.
736 // We are blocking commits from the main thread until after this draw, so
737 // we should not have a pending tree.
738 DCHECK(!has_pending_tree_);
739 // We transition to COMMIT_STATE_BEGIN_MAIN_FRAME_SENT because there is a
740 // pending BeginMainFrame behind the readback request.
741 commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_SENT;
742 readback_state_ = READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT;
743 } else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
744 forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
747 if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW)
748 commit_state_ = COMMIT_STATE_IDLE;
750 needs_redraw_ = false;
751 draw_if_possible_failed_ = false;
752 active_tree_needs_first_draw_ = false;
754 if (did_swap)
755 last_frame_number_swap_performed_ = current_frame_number_;
758 void SchedulerStateMachine::UpdateStateOnManageTiles() {
759 needs_manage_tiles_ = false;
762 void SchedulerStateMachine::SetSkipNextBeginMainFrameToReduceLatency() {
763 skip_next_begin_main_frame_to_reduce_latency_ = true;
766 bool SchedulerStateMachine::BeginFrameNeeded() const {
767 // Proactive BeginFrames are bad for the synchronous compositor because we
768 // have to draw when we get the BeginFrame and could end up drawing many
769 // duplicate frames if our new frame isn't ready in time.
770 // To poll for state with the synchronous compositor without having to draw,
771 // we rely on ShouldPollForAnticipatedDrawTriggers instead.
772 if (!SupportsProactiveBeginFrame())
773 return BeginFrameNeededToDraw();
775 return BeginFrameNeededToDraw() || ProactiveBeginFrameWanted();
778 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const {
779 // ShouldPollForAnticipatedDrawTriggers is what we use in place of
780 // ProactiveBeginFrameWanted when we are using the synchronous
781 // compositor.
782 if (!SupportsProactiveBeginFrame()) {
783 return !BeginFrameNeededToDraw() && ProactiveBeginFrameWanted();
786 // Non synchronous compositors should rely on
787 // ProactiveBeginFrameWanted to poll for state instead.
788 return false;
791 bool SchedulerStateMachine::SupportsProactiveBeginFrame() const {
792 // Both the synchronous compositor and disabled vsync settings
793 // make it undesirable to proactively request BeginImplFrames.
794 // If this is true, the scheduler should poll.
795 return !settings_.using_synchronous_renderer_compositor &&
796 settings_.throttle_frame_production;
799 // These are the cases where we definitely (or almost definitely) have a
800 // new frame to draw and can draw.
801 bool SchedulerStateMachine::BeginFrameNeededToDraw() const {
802 // The output surface is the provider of BeginImplFrames, so we are not going
803 // to get them even if we ask for them.
804 if (!HasInitializedOutputSurface())
805 return false;
807 // If we can't draw, don't tick until we are notified that we can draw again.
808 if (!can_draw_)
809 return false;
811 // The forced draw respects our normal draw scheduling, so we need to
812 // request a BeginImplFrame for it.
813 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
814 return true;
816 // There's no need to produce frames if we are not visible.
817 if (!visible_)
818 return false;
820 // We need to draw a more complete frame than we did the last BeginImplFrame,
821 // so request another BeginImplFrame in anticipation that we will have
822 // additional visible tiles.
823 if (swap_used_incomplete_tile_)
824 return true;
826 return needs_redraw_;
829 // These are cases where we are very likely to draw soon, but might not
830 // actually have a new frame to draw when we receive the next BeginImplFrame.
831 // Proactively requesting the BeginImplFrame helps hide the round trip latency
832 // of the SetNeedsBeginFrame request that has to go to the Browser.
833 bool SchedulerStateMachine::ProactiveBeginFrameWanted() const {
834 // The output surface is the provider of BeginImplFrames,
835 // so we are not going to get them even if we ask for them.
836 if (!HasInitializedOutputSurface())
837 return false;
839 // Do not be proactive when invisible.
840 if (!visible_)
841 return false;
843 // We should proactively request a BeginImplFrame if a commit is pending
844 // because we will want to draw if the commit completes quickly.
845 if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE)
846 return true;
848 // If the pending tree activates quickly, we'll want a BeginImplFrame soon
849 // to draw the new active tree.
850 if (has_pending_tree_)
851 return true;
853 // Changing priorities may allow us to activate (given the new priorities),
854 // which may result in a new frame.
855 if (needs_manage_tiles_)
856 return true;
858 // If we just swapped, it's likely that we are going to produce another
859 // frame soon. This helps avoid negative glitches in our
860 // SetNeedsBeginFrame requests, which may propagate to the BeginImplFrame
861 // provider and get sampled at an inopportune time, delaying the next
862 // BeginImplFrame.
863 if (last_frame_number_swap_performed_ == current_frame_number_)
864 return true;
866 return false;
869 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) {
870 AdvanceCurrentFrameNumber();
871 begin_impl_frame_args_ = args;
872 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) << *AsValue();
873 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING;
876 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() {
877 DCHECK_EQ(begin_impl_frame_state_,
878 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING)
879 << *AsValue();
880 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME;
883 void SchedulerStateMachine::OnBeginImplFrameDeadline() {
884 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
885 << *AsValue();
886 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
889 void SchedulerStateMachine::OnBeginImplFrameIdle() {
890 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
891 << *AsValue();
892 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE;
895 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineEarly() const {
896 // TODO(brianderson): This should take into account multiple commit sources.
898 // If we are in the middle of the readback, we won't swap, so there is
899 // no reason to trigger the deadline early.
900 if (readback_state_ != READBACK_STATE_IDLE)
901 return false;
903 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
904 return false;
906 // If we've lost the output surface, end the current BeginImplFrame ASAP
907 // so we can start creating the next output surface.
908 if (output_surface_state_ == OUTPUT_SURFACE_LOST)
909 return true;
911 if (active_tree_needs_first_draw_)
912 return true;
914 if (!needs_redraw_)
915 return false;
917 // This is used to prioritize impl-thread draws when the main thread isn't
918 // producing anything, e.g., after an aborted commit. We also check that we
919 // don't have a pending tree -- otherwise we should give it a chance to
920 // activate.
921 // TODO(skyostil): Revisit this when we have more accurate deadline estimates.
922 if (commit_state_ == COMMIT_STATE_IDLE && !has_pending_tree_)
923 return true;
925 // Prioritize impl-thread draws in smoothness mode.
926 if (smoothness_takes_priority_)
927 return true;
929 return false;
932 bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const {
933 // If a commit is pending before the previous commit has been drawn, we
934 // are definitely in a high latency mode.
935 if (CommitPending() && (active_tree_needs_first_draw_ || has_pending_tree_))
936 return true;
938 // If we just sent a BeginMainFrame and haven't hit the deadline yet, the main
939 // thread is in a low latency mode.
940 if (last_frame_number_begin_main_frame_sent_ == current_frame_number_ &&
941 (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING ||
942 begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME))
943 return false;
945 // If there's a commit in progress it must either be from the previous frame
946 // or it started after the impl thread's deadline. In either case the main
947 // thread is in high latency mode.
948 if (commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
949 commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED ||
950 commit_state_ == COMMIT_STATE_READY_TO_COMMIT)
951 return true;
953 // Similarly, if there's a pending tree the main thread is in high latency
954 // mode, because either
955 // it's from the previous frame
956 // or
957 // we're currently drawing the active tree and the pending tree will thus
958 // only be drawn in the next frame.
959 if (has_pending_tree_)
960 return true;
962 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) {
963 // Even if there's a new active tree to draw at the deadline or we've just
964 // drawn it, it may have been triggered by a previous BeginImplFrame, in
965 // which case the main thread is in a high latency mode.
966 return (active_tree_needs_first_draw_ ||
967 last_frame_number_swap_performed_ == current_frame_number_) &&
968 last_frame_number_begin_main_frame_sent_ != current_frame_number_;
971 // If the active tree needs its first draw in any other state, we know the
972 // main thread is in a high latency mode.
973 return active_tree_needs_first_draw_;
976 void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() {
977 AdvanceCurrentFrameNumber();
978 inside_poll_for_anticipated_draw_triggers_ = true;
981 void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() {
982 inside_poll_for_anticipated_draw_triggers_ = false;
985 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }
987 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }
989 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }
991 void SchedulerStateMachine::SetNeedsManageTiles() {
992 if (!needs_manage_tiles_) {
993 TRACE_EVENT0("cc",
994 "SchedulerStateMachine::SetNeedsManageTiles");
995 needs_manage_tiles_ = true;
999 void SchedulerStateMachine::SetSwapUsedIncompleteTile(
1000 bool used_incomplete_tile) {
1001 swap_used_incomplete_tile_ = used_incomplete_tile;
1004 void SchedulerStateMachine::SetSmoothnessTakesPriority(
1005 bool smoothness_takes_priority) {
1006 smoothness_takes_priority_ = smoothness_takes_priority;
1009 void SchedulerStateMachine::DidDrawIfPossibleCompleted(
1010 DrawSwapReadbackResult::DrawResult result) {
1011 switch (result) {
1012 case DrawSwapReadbackResult::INVALID_RESULT:
1013 NOTREACHED() << "Uninitialized DrawSwapReadbackResult.";
1014 break;
1015 case DrawSwapReadbackResult::DRAW_ABORTED_CANT_DRAW:
1016 case DrawSwapReadbackResult::DRAW_ABORTED_CANT_READBACK:
1017 case DrawSwapReadbackResult::DRAW_ABORTED_CONTEXT_LOST:
1018 NOTREACHED() << "Invalid return value from DrawAndSwapIfPossible:"
1019 << result;
1020 break;
1021 case DrawSwapReadbackResult::DRAW_SUCCESS:
1022 consecutive_checkerboard_animations_ = 0;
1023 forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
1024 break;
1025 case DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS:
1026 needs_redraw_ = true;
1028 // If we're already in the middle of a redraw, we don't need to
1029 // restart it.
1030 if (forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE)
1031 return;
1033 needs_commit_ = true;
1034 consecutive_checkerboard_animations_++;
1035 if (settings_.timeout_and_draw_when_animation_checkerboards &&
1036 consecutive_checkerboard_animations_ >=
1037 settings_.maximum_number_of_failed_draws_before_draw_is_forced_) {
1038 consecutive_checkerboard_animations_ = 0;
1039 // We need to force a draw, but it doesn't make sense to do this until
1040 // we've committed and have new textures.
1041 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT;
1043 break;
1044 case DrawSwapReadbackResult::DRAW_ABORTED_MISSING_HIGH_RES_CONTENT:
1045 // It's not clear whether this missing content is because of missing
1046 // pictures (which requires a commit) or because of memory pressure
1047 // removing textures (which might not). To be safe, request a commit
1048 // anyway.
1049 needs_commit_ = true;
1050 break;
1054 void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; }
1056 void SchedulerStateMachine::SetNeedsForcedCommitForReadback() {
1057 // If this is called in READBACK_STATE_IDLE, this is a "first" readback
1058 // request.
1059 // If this is called in READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT, this
1060 // is a back-to-back readback request that started before the replacement
1061 // commit had a chance to land.
1062 // If this is called in READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION,
1063 // this is a readback-commit-readback request when replacement commit is in
1064 // impl-side painting.
1065 DCHECK(readback_state_ == READBACK_STATE_IDLE ||
1066 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT ||
1067 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION);
1069 if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) {
1070 // If new forced commit is requested when impl-side painting of replacement
1071 // commit is in progress, it should not interrupt the draw & swap of current
1072 // commit(replacement commit). New commit(incoming forced commit) should be
1073 // started after current commit is finished.
1074 needs_back_to_back_readback_ = true;
1075 } else if (commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT) {
1076 // If there is already a commit in progress when we get the readback request
1077 // then we don't need to send a BeginMainFrame for the replacement commit,
1078 // since there's already a BeginMainFrame behind the readback request. In
1079 // that case, we can skip READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME and go
1080 // directly to READBACK_STATE_WAITING_FOR_COMMIT.
1081 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
1082 } else {
1083 // Set needs_commit_ to true to trigger scheduling BeginMainFrame().
1084 needs_commit_ = true;
1085 readback_state_ = READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME;
1089 void SchedulerStateMachine::NotifyReadyToCommit() {
1090 DCHECK(commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED) << *AsValue();
1091 commit_state_ = COMMIT_STATE_READY_TO_COMMIT;
1094 void SchedulerStateMachine::BeginMainFrameAborted(bool did_handle) {
1095 DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
1096 if (did_handle) {
1097 bool commit_was_aborted = true;
1098 UpdateStateOnCommit(commit_was_aborted);
1099 } else {
1100 DCHECK_NE(readback_state_, READBACK_STATE_WAITING_FOR_COMMIT);
1101 commit_state_ = COMMIT_STATE_IDLE;
1102 SetNeedsCommit();
1106 void SchedulerStateMachine::DidManageTiles() {
1107 needs_manage_tiles_ = false;
1108 // "Fill" the ManageTiles funnel.
1109 manage_tiles_funnel_++;
1112 void SchedulerStateMachine::DidLoseOutputSurface() {
1113 if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
1114 output_surface_state_ == OUTPUT_SURFACE_CREATING)
1115 return;
1116 output_surface_state_ = OUTPUT_SURFACE_LOST;
1117 needs_redraw_ = false;
1120 void SchedulerStateMachine::NotifyReadyToActivate() {
1121 if (has_pending_tree_)
1122 pending_tree_is_ready_for_activation_ = true;
1125 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
1126 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING);
1127 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT;
1129 if (did_create_and_initialize_first_output_surface_) {
1130 // TODO(boliu): See if we can remove this when impl-side painting is always
1131 // on. Does anything on the main thread need to update after recreate?
1132 needs_commit_ = true;
1134 did_create_and_initialize_first_output_surface_ = true;
1137 void SchedulerStateMachine::NotifyBeginMainFrameStarted() {
1138 DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
1140 DCHECK(readback_state_ == READBACK_STATE_IDLE ||
1141 readback_state_ == READBACK_STATE_WAITING_FOR_COMMIT ||
1142 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT);
1144 commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED;
1147 bool SchedulerStateMachine::HasInitializedOutputSurface() const {
1148 switch (output_surface_state_) {
1149 case OUTPUT_SURFACE_LOST:
1150 case OUTPUT_SURFACE_CREATING:
1151 return false;
1153 case OUTPUT_SURFACE_ACTIVE:
1154 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
1155 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
1156 return true;
1158 NOTREACHED();
1159 return false;
1162 } // namespace cc