Remove PlatformFile from ZipFileCreator
[chromium-blink-merge.git] / cc / scheduler / scheduler_state_machine.cc
blob0a30ab747b0f6e36d14139602bef1115eb7d168c
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 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 manage_tiles_funnel_(0),
30 consecutive_checkerboard_animations_(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_next_begin_main_frame_to_reduce_latency_(false),
47 skip_begin_main_frame_to_reduce_latency_(false),
48 continuous_painting_(false),
49 needs_back_to_back_readback_(false) {}
51 const char* SchedulerStateMachine::OutputSurfaceStateToString(
52 OutputSurfaceState state) {
53 switch (state) {
54 case OUTPUT_SURFACE_ACTIVE:
55 return "OUTPUT_SURFACE_ACTIVE";
56 case OUTPUT_SURFACE_LOST:
57 return "OUTPUT_SURFACE_LOST";
58 case OUTPUT_SURFACE_CREATING:
59 return "OUTPUT_SURFACE_CREATING";
60 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
61 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT";
62 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
63 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION";
65 NOTREACHED();
66 return "???";
69 const char* SchedulerStateMachine::BeginImplFrameStateToString(
70 BeginImplFrameState state) {
71 switch (state) {
72 case BEGIN_IMPL_FRAME_STATE_IDLE:
73 return "BEGIN_IMPL_FRAME_STATE_IDLE";
74 case BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING:
75 return "BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING";
76 case BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME:
77 return "BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME";
78 case BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE:
79 return "BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE";
81 NOTREACHED();
82 return "???";
85 const char* SchedulerStateMachine::CommitStateToString(CommitState state) {
86 switch (state) {
87 case COMMIT_STATE_IDLE:
88 return "COMMIT_STATE_IDLE";
89 case COMMIT_STATE_BEGIN_MAIN_FRAME_SENT:
90 return "COMMIT_STATE_BEGIN_MAIN_FRAME_SENT";
91 case COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED:
92 return "COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED";
93 case COMMIT_STATE_READY_TO_COMMIT:
94 return "COMMIT_STATE_READY_TO_COMMIT";
95 case COMMIT_STATE_WAITING_FOR_ACTIVATION:
96 return "COMMIT_STATE_WAITING_FOR_ACTIVATION";
97 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW:
98 return "COMMIT_STATE_WAITING_FOR_FIRST_DRAW";
100 NOTREACHED();
101 return "???";
104 const char* SchedulerStateMachine::TextureStateToString(TextureState state) {
105 switch (state) {
106 case LAYER_TEXTURE_STATE_UNLOCKED:
107 return "LAYER_TEXTURE_STATE_UNLOCKED";
108 case LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD:
109 return "LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD";
110 case LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD:
111 return "LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD";
113 NOTREACHED();
114 return "???";
117 const char* SchedulerStateMachine::SynchronousReadbackStateToString(
118 SynchronousReadbackState state) {
119 switch (state) {
120 case READBACK_STATE_IDLE:
121 return "READBACK_STATE_IDLE";
122 case READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME:
123 return "READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME";
124 case READBACK_STATE_WAITING_FOR_COMMIT:
125 return "READBACK_STATE_WAITING_FOR_COMMIT";
126 case READBACK_STATE_WAITING_FOR_ACTIVATION:
127 return "READBACK_STATE_WAITING_FOR_ACTIVATION";
128 case READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK:
129 return "READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK";
130 case READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT:
131 return "READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT";
132 case READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION:
133 return "READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION";
135 NOTREACHED();
136 return "???";
139 const char* SchedulerStateMachine::ForcedRedrawOnTimeoutStateToString(
140 ForcedRedrawOnTimeoutState state) {
141 switch (state) {
142 case FORCED_REDRAW_STATE_IDLE:
143 return "FORCED_REDRAW_STATE_IDLE";
144 case FORCED_REDRAW_STATE_WAITING_FOR_COMMIT:
145 return "FORCED_REDRAW_STATE_WAITING_FOR_COMMIT";
146 case FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION:
147 return "FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION";
148 case FORCED_REDRAW_STATE_WAITING_FOR_DRAW:
149 return "FORCED_REDRAW_STATE_WAITING_FOR_DRAW";
151 NOTREACHED();
152 return "???";
155 const char* SchedulerStateMachine::ActionToString(Action action) {
156 switch (action) {
157 case ACTION_NONE:
158 return "ACTION_NONE";
159 case ACTION_SEND_BEGIN_MAIN_FRAME:
160 return "ACTION_SEND_BEGIN_MAIN_FRAME";
161 case ACTION_COMMIT:
162 return "ACTION_COMMIT";
163 case ACTION_UPDATE_VISIBLE_TILES:
164 return "ACTION_UPDATE_VISIBLE_TILES";
165 case ACTION_ACTIVATE_PENDING_TREE:
166 return "ACTION_ACTIVATE_PENDING_TREE";
167 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
168 return "ACTION_DRAW_AND_SWAP_IF_POSSIBLE";
169 case ACTION_DRAW_AND_SWAP_FORCED:
170 return "ACTION_DRAW_AND_SWAP_FORCED";
171 case ACTION_DRAW_AND_SWAP_ABORT:
172 return "ACTION_DRAW_AND_SWAP_ABORT";
173 case ACTION_DRAW_AND_READBACK:
174 return "ACTION_DRAW_AND_READBACK";
175 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
176 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION";
177 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
178 return "ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD";
179 case ACTION_MANAGE_TILES:
180 return "ACTION_MANAGE_TILES";
182 NOTREACHED();
183 return "???";
186 scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const {
187 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
189 scoped_ptr<base::DictionaryValue> major_state(new base::DictionaryValue);
190 major_state->SetString("next_action", ActionToString(NextAction()));
191 major_state->SetString("begin_impl_frame_state",
192 BeginImplFrameStateToString(begin_impl_frame_state_));
193 major_state->SetString("commit_state", CommitStateToString(commit_state_));
194 major_state->SetString("texture_state_",
195 TextureStateToString(texture_state_));
196 major_state->SetString("output_surface_state_",
197 OutputSurfaceStateToString(output_surface_state_));
198 major_state->SetString(
199 "forced_redraw_state",
200 ForcedRedrawOnTimeoutStateToString(forced_redraw_state_));
201 major_state->SetString("readback_state",
202 SynchronousReadbackStateToString(readback_state_));
203 state->Set("major_state", major_state.release());
205 scoped_ptr<base::DictionaryValue> timestamps_state(new base::DictionaryValue);
206 base::TimeTicks now = gfx::FrameTime::Now();
207 timestamps_state->SetDouble(
208 "0_interval",
209 last_begin_impl_frame_args_.interval.InMicroseconds() / 1000.0L);
210 timestamps_state->SetDouble(
211 "1_now_to_deadline",
212 (last_begin_impl_frame_args_.deadline - now).InMicroseconds() / 1000.0L);
213 timestamps_state->SetDouble(
214 "2_frame_time_to_now",
215 (now - last_begin_impl_frame_args_.frame_time).InMicroseconds() /
216 1000.0L);
217 timestamps_state->SetDouble(
218 "3_frame_time_to_deadline",
219 (last_begin_impl_frame_args_.deadline -
220 last_begin_impl_frame_args_.frame_time).InMicroseconds() /
221 1000.0L);
222 timestamps_state->SetDouble(
223 "4_now", (now - base::TimeTicks()).InMicroseconds() / 1000.0L);
224 timestamps_state->SetDouble(
225 "5_frame_time",
226 (last_begin_impl_frame_args_.frame_time - base::TimeTicks())
227 .InMicroseconds() /
228 1000.0L);
229 timestamps_state->SetDouble(
230 "6_deadline",
231 (last_begin_impl_frame_args_.deadline - base::TimeTicks())
232 .InMicroseconds() /
233 1000.0L);
234 state->Set("major_timestamps_in_ms", timestamps_state.release());
236 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue);
237 minor_state->SetInteger("commit_count", commit_count_);
238 minor_state->SetInteger("current_frame_number", current_frame_number_);
240 minor_state->SetInteger("last_frame_number_swap_performed",
241 last_frame_number_swap_performed_);
242 minor_state->SetInteger(
243 "last_frame_number_begin_main_frame_sent",
244 last_frame_number_begin_main_frame_sent_);
245 minor_state->SetInteger(
246 "last_frame_number_update_visible_tiles_was_called",
247 last_frame_number_update_visible_tiles_was_called_);
249 minor_state->SetInteger("manage_tiles_funnel", manage_tiles_funnel_);
250 minor_state->SetInteger("consecutive_checkerboard_animations",
251 consecutive_checkerboard_animations_);
252 minor_state->SetBoolean("needs_redraw", needs_redraw_);
253 minor_state->SetBoolean("needs_manage_tiles", needs_manage_tiles_);
254 minor_state->SetBoolean("swap_used_incomplete_tile",
255 swap_used_incomplete_tile_);
256 minor_state->SetBoolean("needs_commit", needs_commit_);
257 minor_state->SetBoolean("main_thread_needs_layer_textures",
258 main_thread_needs_layer_textures_);
259 minor_state->SetBoolean("visible", visible_);
260 minor_state->SetBoolean("can_start", can_start_);
261 minor_state->SetBoolean("can_draw", can_draw_);
262 minor_state->SetBoolean("has_pending_tree", has_pending_tree_);
263 minor_state->SetBoolean("pending_tree_is_ready_for_activation",
264 pending_tree_is_ready_for_activation_);
265 minor_state->SetBoolean("active_tree_needs_first_draw",
266 active_tree_needs_first_draw_);
267 minor_state->SetBoolean("draw_if_possible_failed", draw_if_possible_failed_);
268 minor_state->SetBoolean("did_create_and_initialize_first_output_surface",
269 did_create_and_initialize_first_output_surface_);
270 minor_state->SetBoolean("smoothness_takes_priority",
271 smoothness_takes_priority_);
272 minor_state->SetBoolean("main_thread_is_in_high_latency_mode",
273 MainThreadIsInHighLatencyMode());
274 minor_state->SetBoolean("skip_begin_main_frame_to_reduce_latency",
275 skip_begin_main_frame_to_reduce_latency_);
276 minor_state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency",
277 skip_next_begin_main_frame_to_reduce_latency_);
278 minor_state->SetBoolean("continuous_painting", continuous_painting_);
279 state->Set("minor_state", minor_state.release());
281 return state.PassAs<base::Value>();
284 void SchedulerStateMachine::AdvanceCurrentFrameNumber() {
285 current_frame_number_++;
287 // "Drain" the ManageTiles funnel.
288 if (manage_tiles_funnel_ > 0)
289 manage_tiles_funnel_--;
291 skip_begin_main_frame_to_reduce_latency_ =
292 skip_next_begin_main_frame_to_reduce_latency_;
293 skip_next_begin_main_frame_to_reduce_latency_ = false;
296 bool SchedulerStateMachine::HasSentBeginMainFrameThisFrame() const {
297 return current_frame_number_ ==
298 last_frame_number_begin_main_frame_sent_;
301 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const {
302 return current_frame_number_ ==
303 last_frame_number_update_visible_tiles_was_called_;
306 bool SchedulerStateMachine::HasSwappedThisFrame() const {
307 return current_frame_number_ == last_frame_number_swap_performed_;
310 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const {
311 // These are all the cases where we normally cannot or do not want to draw
312 // but, if needs_redraw_ is true and we do not draw to make forward progress,
313 // we might deadlock with the main thread.
314 // This should be a superset of PendingActivationsShouldBeForced() since
315 // activation of the pending tree is blocked by drawing of the active tree and
316 // the main thread might be blocked on activation of the most recent commit.
317 if (PendingActivationsShouldBeForced())
318 return true;
320 // Impl thread should not draw anymore when texture is acquired by main thread
321 // because texture is controlled under main thread.
322 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD)
323 return true;
325 // Additional states where we should abort draws.
326 // Note: We don't force activation in these cases because doing so would
327 // result in checkerboarding on resize, becoming visible, etc.
328 if (!can_draw_)
329 return true;
330 if (!visible_)
331 return true;
332 return false;
335 bool SchedulerStateMachine::PendingActivationsShouldBeForced() const {
336 // These are all the cases where, if we do not force activations to make
337 // forward progress, we might deadlock with the main thread.
339 // There is no output surface to trigger our activations.
340 if (output_surface_state_ == OUTPUT_SURFACE_LOST)
341 return true;
343 return false;
346 bool SchedulerStateMachine::ShouldBeginOutputSurfaceCreation() const {
347 // Don't try to initialize too early.
348 if (!can_start_)
349 return false;
351 // We only want to start output surface initialization after the
352 // previous commit is complete.
353 if (commit_state_ != COMMIT_STATE_IDLE)
354 return false;
356 // Make sure the BeginImplFrame from any previous OutputSurfaces
357 // are complete before creating the new OutputSurface.
358 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_IDLE)
359 return false;
361 // We want to clear the pipline of any pending draws and activations
362 // before starting output surface initialization. This allows us to avoid
363 // weird corner cases where we abort draws or force activation while we
364 // are initializing the output surface and can potentially have a pending
365 // readback.
366 if (active_tree_needs_first_draw_ || has_pending_tree_)
367 return false;
369 // We need to create the output surface if we don't have one and we haven't
370 // started creating one yet.
371 return output_surface_state_ == OUTPUT_SURFACE_LOST;
374 bool SchedulerStateMachine::ShouldDraw() const {
375 // After a readback, make sure not to draw again until we've replaced the
376 // readback commit with a real one.
377 if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT ||
378 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION)
379 return false;
381 // Draw immediately for readbacks to unblock the main thread quickly.
382 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK)
383 return true;
385 // If we need to abort draws, we should do so ASAP since the draw could
386 // be blocking other important actions (like output surface initialization),
387 // from occuring. If we are waiting for the first draw, then perfom the
388 // aborted draw to keep things moving. If we are not waiting for the first
389 // draw however, we don't want to abort for no reason.
390 if (PendingDrawsShouldBeAborted())
391 return active_tree_needs_first_draw_;
393 // After this line, we only want to swap once per frame.
394 if (HasSwappedThisFrame())
395 return false;
397 // Except for the cases above, do not draw outside of the BeginImplFrame
398 // deadline.
399 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
400 return false;
402 // Only handle forced redraws due to timeouts on the regular deadline.
403 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
404 return true;
406 return needs_redraw_;
409 bool SchedulerStateMachine::ShouldAcquireLayerTexturesForMainThread() const {
410 if (!main_thread_needs_layer_textures_)
411 return false;
412 if (texture_state_ == LAYER_TEXTURE_STATE_UNLOCKED)
413 return true;
414 DCHECK_EQ(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD);
415 return false;
418 bool SchedulerStateMachine::ShouldActivatePendingTree() const {
419 // There is nothing to activate.
420 if (!has_pending_tree_)
421 return false;
423 // We should not activate a second tree before drawing the first one.
424 // Even if we need to force activation of the pending tree, we should abort
425 // drawing the active tree first.
426 if (active_tree_needs_first_draw_)
427 return false;
429 // If we want to force activation, do so ASAP.
430 if (PendingActivationsShouldBeForced())
431 return true;
433 // At this point, only activate if we are ready to activate.
434 return pending_tree_is_ready_for_activation_;
437 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const {
438 if (!settings_.impl_side_painting)
439 return false;
440 if (HasUpdatedVisibleTilesThisFrame())
441 return false;
443 // There's no reason to check for tiles if we don't have an output surface.
444 if (!HasInitializedOutputSurface())
445 return false;
447 // We should not check for visible tiles until we've entered the deadline so
448 // we check as late as possible and give the tiles more time to initialize.
449 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
450 return false;
452 // If the last swap drew with checkerboard or missing tiles, we should
453 // poll for any new visible tiles so we can be notified to draw again
454 // when there are.
455 if (swap_used_incomplete_tile_)
456 return true;
458 return false;
461 bool SchedulerStateMachine::ShouldSendBeginMainFrame() const {
462 if (!needs_commit_)
463 return false;
465 // Only send BeginMainFrame when there isn't another commit pending already.
466 if (commit_state_ != COMMIT_STATE_IDLE)
467 return false;
469 // Don't send BeginMainFrame early if we are prioritizing the active tree
470 // because of smoothness_takes_priority.
471 if (smoothness_takes_priority_ &&
472 (has_pending_tree_ || active_tree_needs_first_draw_)) {
473 return false;
476 // We want to handle readback commits immediately to unblock the main thread.
477 // Note: This BeginMainFrame will correspond to the replacement commit that
478 // comes after the readback commit itself, so we only send the BeginMainFrame
479 // if a commit isn't already pending behind the readback.
480 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME)
481 return !CommitPending();
483 // We do not need commits if we are not visible, unless there's a
484 // request for a readback.
485 if (!visible_)
486 return false;
488 // We want to start the first commit after we get a new output surface ASAP.
489 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT)
490 return true;
492 // We should not send BeginMainFrame while we are in
493 // BEGIN_IMPL_FRAME_STATE_IDLE since we might have new
494 // user input arriving soon.
495 // TODO(brianderson): Allow sending BeginMainFrame while idle when the main
496 // thread isn't consuming user input.
497 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE &&
498 BeginImplFrameNeeded())
499 return false;
501 // We need a new commit for the forced redraw. This honors the
502 // single commit per interval because the result will be swapped to screen.
503 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT)
504 return true;
506 // After this point, we only start a commit once per frame.
507 if (HasSentBeginMainFrameThisFrame())
508 return false;
510 // We shouldn't normally accept commits if there isn't an OutputSurface.
511 if (!HasInitializedOutputSurface())
512 return false;
514 if (skip_begin_main_frame_to_reduce_latency_)
515 return false;
517 return true;
520 bool SchedulerStateMachine::ShouldCommit() const {
521 if (commit_state_ != COMMIT_STATE_READY_TO_COMMIT)
522 return false;
524 // We must not finish the commit until the pending tree is free.
525 if (has_pending_tree_) {
526 DCHECK(settings_.main_frame_before_activation_enabled);
527 return false;
530 // Prioritize drawing the previous commit before finishing the next commit.
531 if (active_tree_needs_first_draw_)
532 return false;
534 return true;
537 bool SchedulerStateMachine::ShouldManageTiles() const {
538 // ManageTiles only really needs to be called immediately after commit
539 // and then periodically after that. Use a funnel to make sure we average
540 // one ManageTiles per BeginImplFrame in the long run.
541 if (manage_tiles_funnel_ > 0)
542 return false;
544 // Limiting to once per-frame is not enough, since we only want to
545 // manage tiles _after_ draws. Polling for draw triggers and
546 // begin-frame are mutually exclusive, so we limit to these two cases.
547 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE &&
548 !inside_poll_for_anticipated_draw_triggers_)
549 return false;
550 return needs_manage_tiles_;
553 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
554 if (ShouldAcquireLayerTexturesForMainThread())
555 return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD;
556 if (ShouldUpdateVisibleTiles())
557 return ACTION_UPDATE_VISIBLE_TILES;
558 if (ShouldActivatePendingTree())
559 return ACTION_ACTIVATE_PENDING_TREE;
560 if (ShouldCommit())
561 return ACTION_COMMIT;
562 if (ShouldDraw()) {
563 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK)
564 return ACTION_DRAW_AND_READBACK;
565 else if (PendingDrawsShouldBeAborted())
566 return ACTION_DRAW_AND_SWAP_ABORT;
567 else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
568 return ACTION_DRAW_AND_SWAP_FORCED;
569 else
570 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
572 if (ShouldManageTiles())
573 return ACTION_MANAGE_TILES;
574 if (ShouldSendBeginMainFrame())
575 return ACTION_SEND_BEGIN_MAIN_FRAME;
576 if (ShouldBeginOutputSurfaceCreation())
577 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION;
578 return ACTION_NONE;
581 void SchedulerStateMachine::CheckInvariants() {
582 // We should never try to perform a draw for readback and forced draw due to
583 // timeout simultaneously.
584 DCHECK(!(forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW &&
585 readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK));
587 // Main thread should never have the texture locked when there is a pending
588 // tree or active tree is not drawn for the first time.
589 if (has_pending_tree_ || active_tree_needs_first_draw_)
590 DCHECK(texture_state_ != LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD);
593 void SchedulerStateMachine::UpdateState(Action action) {
594 switch (action) {
595 case ACTION_NONE:
596 return;
598 case ACTION_UPDATE_VISIBLE_TILES:
599 last_frame_number_update_visible_tiles_was_called_ =
600 current_frame_number_;
601 return;
603 case ACTION_ACTIVATE_PENDING_TREE:
604 UpdateStateOnActivation();
605 return;
607 case ACTION_SEND_BEGIN_MAIN_FRAME:
608 DCHECK(!has_pending_tree_ ||
609 settings_.main_frame_before_activation_enabled);
610 DCHECK(!active_tree_needs_first_draw_ ||
611 settings_.main_frame_before_draw_enabled);
612 DCHECK(visible_ ||
613 readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME);
614 commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_SENT;
615 needs_commit_ = false;
616 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME)
617 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
618 last_frame_number_begin_main_frame_sent_ =
619 current_frame_number_;
620 return;
622 case ACTION_COMMIT: {
623 bool commit_was_aborted = false;
624 UpdateStateOnCommit(commit_was_aborted);
625 return;
628 case ACTION_DRAW_AND_SWAP_FORCED:
629 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: {
630 bool did_swap = true;
631 UpdateStateOnDraw(did_swap);
632 return;
635 case ACTION_DRAW_AND_SWAP_ABORT:
636 case ACTION_DRAW_AND_READBACK: {
637 bool did_swap = false;
638 UpdateStateOnDraw(did_swap);
639 return;
642 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
643 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST);
644 output_surface_state_ = OUTPUT_SURFACE_CREATING;
646 // The following DCHECKs make sure we are in the proper quiescent state.
647 // The pipeline should be flushed entirely before we start output
648 // surface creation to avoid complicated corner cases.
649 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE);
650 DCHECK(!has_pending_tree_);
651 DCHECK(!active_tree_needs_first_draw_);
652 return;
654 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
655 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD;
656 main_thread_needs_layer_textures_ = false;
657 return;
659 case ACTION_MANAGE_TILES:
660 UpdateStateOnManageTiles();
661 return;
665 void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) {
666 commit_count_++;
668 if (commit_was_aborted || settings_.main_frame_before_activation_enabled) {
669 commit_state_ = COMMIT_STATE_IDLE;
670 } else if (settings_.main_frame_before_draw_enabled) {
671 commit_state_ = settings_.impl_side_painting
672 ? COMMIT_STATE_WAITING_FOR_ACTIVATION
673 : COMMIT_STATE_IDLE;
674 } else {
675 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
678 // If we are impl-side-painting but the commit was aborted, then we behave
679 // mostly as if we are not impl-side-painting since there is no pending tree.
680 has_pending_tree_ = settings_.impl_side_painting && !commit_was_aborted;
682 // Update state related to readbacks.
683 if (readback_state_ == READBACK_STATE_WAITING_FOR_COMMIT) {
684 // Update the state if this is the readback commit.
685 readback_state_ = has_pending_tree_
686 ? READBACK_STATE_WAITING_FOR_ACTIVATION
687 : READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
688 } else if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT) {
689 // Update the state if this is the commit replacing the readback commit.
690 readback_state_ = has_pending_tree_
691 ? READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION
692 : READBACK_STATE_IDLE;
693 } else {
694 DCHECK(readback_state_ == READBACK_STATE_IDLE);
697 // Readbacks can interrupt output surface initialization and forced draws,
698 // so we do not want to advance those states if we are in the middle of a
699 // readback. Note: It is possible for the readback's replacement commit to
700 // be the output surface's first commit and/or the forced redraw's commit.
701 if (readback_state_ == READBACK_STATE_IDLE ||
702 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) {
703 // Update state related to forced draws.
704 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) {
705 forced_redraw_state_ = has_pending_tree_
706 ? FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION
707 : FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
710 // Update the output surface state.
711 DCHECK_NE(output_surface_state_,
712 OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION);
713 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) {
714 if (has_pending_tree_) {
715 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION;
716 } else {
717 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
718 needs_redraw_ = true;
723 // Update state if we have a new active tree to draw, or if the active tree
724 // was unchanged but we need to do a readback or forced draw.
725 if (!has_pending_tree_ &&
726 (!commit_was_aborted ||
727 readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK ||
728 forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)) {
729 needs_redraw_ = true;
730 active_tree_needs_first_draw_ = true;
733 // This post-commit work is common to both completed and aborted commits.
734 pending_tree_is_ready_for_activation_ = false;
736 if (draw_if_possible_failed_)
737 last_frame_number_swap_performed_ = -1;
739 // If we are planing to draw with the new commit, lock the layer textures for
740 // use on the impl thread. Otherwise, leave them unlocked.
741 if (has_pending_tree_ || needs_redraw_)
742 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD;
743 else
744 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED;
746 if (continuous_painting_)
747 needs_commit_ = true;
750 void SchedulerStateMachine::UpdateStateOnActivation() {
751 if (commit_state_ == COMMIT_STATE_WAITING_FOR_ACTIVATION)
752 commit_state_ = COMMIT_STATE_IDLE;
754 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
755 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
757 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION)
758 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
760 if (readback_state_ == READBACK_STATE_WAITING_FOR_ACTIVATION) {
761 readback_state_ = READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
762 } else if (readback_state_ ==
763 READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) {
764 if (needs_back_to_back_readback_) {
765 if (commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT) {
766 // If main_frame_before_activation_enabled is true, it is possible that
767 // we will have already sent the BeginMainFrame here.
768 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
769 } else {
770 // Replacement commit for incoming forced commit should be scheduled
771 // after current commit's draw & swap is finished.
772 needs_commit_ = true;
773 readback_state_ = READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME;
775 needs_back_to_back_readback_ = false;
776 } else {
777 readback_state_ = READBACK_STATE_IDLE;
781 has_pending_tree_ = false;
782 pending_tree_is_ready_for_activation_ = false;
783 active_tree_needs_first_draw_ = true;
784 needs_redraw_ = true;
787 void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) {
788 DCHECK(readback_state_ != READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT &&
789 readback_state_ != READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION)
790 << *AsValue();
792 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) {
793 // The draw corresponds to a readback commit.
794 // We are blocking commits from the main thread until after this draw, so
795 // we should not have a pending tree.
796 DCHECK(!has_pending_tree_);
797 // We transition to COMMIT_STATE_BEGIN_MAIN_FRAME_SENT because there is a
798 // pending BeginMainFrame behind the readback request.
799 commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_SENT;
800 readback_state_ = READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT;
801 } else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
802 forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
805 if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW)
806 commit_state_ = COMMIT_STATE_IDLE;
808 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD)
809 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED;
811 needs_redraw_ = false;
812 draw_if_possible_failed_ = false;
813 active_tree_needs_first_draw_ = false;
815 if (did_swap)
816 last_frame_number_swap_performed_ = current_frame_number_;
819 void SchedulerStateMachine::UpdateStateOnManageTiles() {
820 needs_manage_tiles_ = false;
823 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() {
824 DCHECK(!main_thread_needs_layer_textures_);
825 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD);
826 main_thread_needs_layer_textures_ = true;
829 void SchedulerStateMachine::SetSkipNextBeginMainFrameToReduceLatency() {
830 skip_next_begin_main_frame_to_reduce_latency_ = true;
833 bool SchedulerStateMachine::BeginImplFrameNeeded() const {
834 // Proactive BeginImplFrames are bad for the synchronous compositor because we
835 // have to draw when we get the BeginImplFrame and could end up drawing many
836 // duplicate frames if our new frame isn't ready in time.
837 // To poll for state with the synchronous compositor without having to draw,
838 // we rely on ShouldPollForAnticipatedDrawTriggers instead.
839 if (!SupportsProactiveBeginImplFrame())
840 return BeginImplFrameNeededToDraw();
842 return BeginImplFrameNeededToDraw() ||
843 ProactiveBeginImplFrameWanted();
846 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const {
847 // ShouldPollForAnticipatedDrawTriggers is what we use in place of
848 // ProactiveBeginImplFrameWanted when we are using the synchronous
849 // compositor.
850 if (!SupportsProactiveBeginImplFrame()) {
851 return !BeginImplFrameNeededToDraw() &&
852 ProactiveBeginImplFrameWanted();
855 // Non synchronous compositors should rely on
856 // ProactiveBeginImplFrameWanted to poll for state instead.
857 return false;
860 bool SchedulerStateMachine::SupportsProactiveBeginImplFrame() const {
861 // Both the synchronous compositor and disabled vsync settings
862 // make it undesirable to proactively request BeginImplFrames.
863 // If this is true, the scheduler should poll.
864 return !settings_.using_synchronous_renderer_compositor &&
865 settings_.throttle_frame_production;
868 // These are the cases where we definitely (or almost definitely) have a
869 // new frame to draw and can draw.
870 bool SchedulerStateMachine::BeginImplFrameNeededToDraw() const {
871 // The output surface is the provider of BeginImplFrames, so we are not going
872 // to get them even if we ask for them.
873 if (!HasInitializedOutputSurface())
874 return false;
876 // If we can't draw, don't tick until we are notified that we can draw again.
877 if (!can_draw_)
878 return false;
880 // The forced draw respects our normal draw scheduling, so we need to
881 // request a BeginImplFrame for it.
882 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
883 return true;
885 // There's no need to produce frames if we are not visible.
886 if (!visible_)
887 return false;
889 // We need to draw a more complete frame than we did the last BeginImplFrame,
890 // so request another BeginImplFrame in anticipation that we will have
891 // additional visible tiles.
892 if (swap_used_incomplete_tile_)
893 return true;
895 return needs_redraw_;
898 // These are cases where we are very likely to draw soon, but might not
899 // actually have a new frame to draw when we receive the next BeginImplFrame.
900 // Proactively requesting the BeginImplFrame helps hide the round trip latency
901 // of the SetNeedsBeginImplFrame request that has to go to the Browser.
902 bool SchedulerStateMachine::ProactiveBeginImplFrameWanted() const {
903 // The output surface is the provider of BeginImplFrames,
904 // so we are not going to get them even if we ask for them.
905 if (!HasInitializedOutputSurface())
906 return false;
908 // Do not be proactive when invisible.
909 if (!visible_)
910 return false;
912 // We should proactively request a BeginImplFrame if a commit is pending
913 // because we will want to draw if the commit completes quickly.
914 if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE)
915 return true;
917 // If the pending tree activates quickly, we'll want a BeginImplFrame soon
918 // to draw the new active tree.
919 if (has_pending_tree_)
920 return true;
922 // Changing priorities may allow us to activate (given the new priorities),
923 // which may result in a new frame.
924 if (needs_manage_tiles_)
925 return true;
927 // If we just swapped, it's likely that we are going to produce another
928 // frame soon. This helps avoid negative glitches in our
929 // SetNeedsBeginImplFrame requests, which may propagate to the BeginImplFrame
930 // provider and get sampled at an inopportune time, delaying the next
931 // BeginImplFrame.
932 if (last_frame_number_swap_performed_ == current_frame_number_)
933 return true;
935 return false;
938 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) {
939 AdvanceCurrentFrameNumber();
940 last_begin_impl_frame_args_ = args;
941 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) << *AsValue();
942 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING;
945 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() {
946 DCHECK_EQ(begin_impl_frame_state_,
947 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING)
948 << *AsValue();
949 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME;
952 void SchedulerStateMachine::OnBeginImplFrameDeadline() {
953 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
954 << *AsValue();
955 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
958 void SchedulerStateMachine::OnBeginImplFrameIdle() {
959 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
960 << *AsValue();
961 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE;
964 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineEarly() const {
965 // TODO(brianderson): This should take into account multiple commit sources.
967 // If we are in the middle of the readback, we won't swap, so there is
968 // no reason to trigger the deadline early.
969 if (readback_state_ != READBACK_STATE_IDLE)
970 return false;
972 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
973 return false;
975 // If we've lost the output surface, end the current BeginImplFrame ASAP
976 // so we can start creating the next output surface.
977 if (output_surface_state_ == OUTPUT_SURFACE_LOST)
978 return true;
980 if (active_tree_needs_first_draw_)
981 return true;
983 if (!needs_redraw_)
984 return false;
986 // This is used to prioritize impl-thread draws when the main thread isn't
987 // producing anything, e.g., after an aborted commit. We also check that we
988 // don't have a pending tree -- otherwise we should give it a chance to
989 // activate.
990 // TODO(skyostil): Revisit this when we have more accurate deadline estimates.
991 if (commit_state_ == COMMIT_STATE_IDLE && !has_pending_tree_)
992 return true;
994 // Prioritize impl-thread draws in smoothness mode.
995 if (smoothness_takes_priority_)
996 return true;
998 return false;
1001 bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const {
1002 // If a commit is pending before the previous commit has been drawn, we
1003 // are definitely in a high latency mode.
1004 if (CommitPending() && (active_tree_needs_first_draw_ || has_pending_tree_))
1005 return true;
1007 // If we just sent a BeginMainFrame and haven't hit the deadline yet, the main
1008 // thread is in a low latency mode.
1009 if (last_frame_number_begin_main_frame_sent_ == current_frame_number_ &&
1010 (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING ||
1011 begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME))
1012 return false;
1014 // If there's a commit in progress it must either be from the previous frame
1015 // or it started after the impl thread's deadline. In either case the main
1016 // thread is in high latency mode.
1017 if (commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
1018 commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED ||
1019 commit_state_ == COMMIT_STATE_READY_TO_COMMIT)
1020 return true;
1022 // Similarly, if there's a pending tree the main thread is in high latency
1023 // mode, because either
1024 // it's from the previous frame
1025 // or
1026 // we're currently drawing the active tree and the pending tree will thus
1027 // only be drawn in the next frame.
1028 if (has_pending_tree_)
1029 return true;
1031 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) {
1032 // Even if there's a new active tree to draw at the deadline or we've just
1033 // drawn it, it may have been triggered by a previous BeginImplFrame, in
1034 // which case the main thread is in a high latency mode.
1035 return (active_tree_needs_first_draw_ ||
1036 last_frame_number_swap_performed_ == current_frame_number_) &&
1037 last_frame_number_begin_main_frame_sent_ != current_frame_number_;
1040 // If the active tree needs its first draw in any other state, we know the
1041 // main thread is in a high latency mode.
1042 return active_tree_needs_first_draw_;
1045 void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() {
1046 AdvanceCurrentFrameNumber();
1047 inside_poll_for_anticipated_draw_triggers_ = true;
1050 void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() {
1051 inside_poll_for_anticipated_draw_triggers_ = false;
1054 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }
1056 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }
1058 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }
1060 void SchedulerStateMachine::SetNeedsManageTiles() {
1061 if (!needs_manage_tiles_) {
1062 TRACE_EVENT0("cc",
1063 "SchedulerStateMachine::SetNeedsManageTiles");
1064 needs_manage_tiles_ = true;
1068 void SchedulerStateMachine::SetSwapUsedIncompleteTile(
1069 bool used_incomplete_tile) {
1070 swap_used_incomplete_tile_ = used_incomplete_tile;
1073 void SchedulerStateMachine::SetSmoothnessTakesPriority(
1074 bool smoothness_takes_priority) {
1075 smoothness_takes_priority_ = smoothness_takes_priority;
1078 void SchedulerStateMachine::DidDrawIfPossibleCompleted(
1079 DrawSwapReadbackResult::DrawResult result) {
1080 switch (result) {
1081 case DrawSwapReadbackResult::INVALID_RESULT:
1082 NOTREACHED() << "Uninitialized DrawSwapReadbackResult.";
1083 break;
1084 case DrawSwapReadbackResult::DRAW_ABORTED_CANT_DRAW:
1085 case DrawSwapReadbackResult::DRAW_ABORTED_CANT_READBACK:
1086 case DrawSwapReadbackResult::DRAW_ABORTED_CONTEXT_LOST:
1087 NOTREACHED() << "Invalid return value from DrawAndSwapIfPossible:"
1088 << result;
1089 break;
1090 case DrawSwapReadbackResult::DRAW_SUCCESS:
1091 consecutive_checkerboard_animations_ = 0;
1092 forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
1093 break;
1094 case DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS:
1095 needs_redraw_ = true;
1097 // If we're already in the middle of a redraw, we don't need to
1098 // restart it.
1099 if (forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE)
1100 return;
1102 needs_commit_ = true;
1103 consecutive_checkerboard_animations_++;
1104 if (settings_.timeout_and_draw_when_animation_checkerboards &&
1105 consecutive_checkerboard_animations_ >=
1106 settings_.maximum_number_of_failed_draws_before_draw_is_forced_) {
1107 consecutive_checkerboard_animations_ = 0;
1108 // We need to force a draw, but it doesn't make sense to do this until
1109 // we've committed and have new textures.
1110 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT;
1112 break;
1113 case DrawSwapReadbackResult::DRAW_ABORTED_MISSING_HIGH_RES_CONTENT:
1114 // It's not clear whether this missing content is because of missing
1115 // pictures (which requires a commit) or because of memory pressure
1116 // removing textures (which might not). To be safe, request a commit
1117 // anyway.
1118 needs_commit_ = true;
1119 break;
1123 void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; }
1125 void SchedulerStateMachine::SetNeedsForcedCommitForReadback() {
1126 // If this is called in READBACK_STATE_IDLE, this is a "first" readback
1127 // request.
1128 // If this is called in READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT, this
1129 // is a back-to-back readback request that started before the replacement
1130 // commit had a chance to land.
1131 // If this is called in READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION,
1132 // this is a readback-commit-readback request when replacement commit is in
1133 // impl-side painting.
1134 DCHECK(readback_state_ == READBACK_STATE_IDLE ||
1135 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT ||
1136 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION);
1138 if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) {
1139 // If new forced commit is requested when impl-side painting of replacement
1140 // commit is in progress, it should not interrupt the draw & swap of current
1141 // commit(replacement commit). New commit(incoming forced commit) should be
1142 // started after current commit is finished.
1143 needs_back_to_back_readback_ = true;
1144 } else if (commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT) {
1145 // If there is already a commit in progress when we get the readback request
1146 // then we don't need to send a BeginMainFrame for the replacement commit,
1147 // since there's already a BeginMainFrame behind the readback request. In
1148 // that case, we can skip READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME and go
1149 // directly to READBACK_STATE_WAITING_FOR_COMMIT.
1150 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
1151 } else {
1152 // Set needs_commit_ to true to trigger scheduling BeginMainFrame().
1153 needs_commit_ = true;
1154 readback_state_ = READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME;
1158 void SchedulerStateMachine::NotifyReadyToCommit() {
1159 DCHECK(commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED) << *AsValue();
1160 commit_state_ = COMMIT_STATE_READY_TO_COMMIT;
1163 void SchedulerStateMachine::BeginMainFrameAborted(bool did_handle) {
1164 DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
1165 if (did_handle) {
1166 bool commit_was_aborted = true;
1167 UpdateStateOnCommit(commit_was_aborted);
1168 } else {
1169 DCHECK_NE(readback_state_, READBACK_STATE_WAITING_FOR_COMMIT);
1170 commit_state_ = COMMIT_STATE_IDLE;
1171 SetNeedsCommit();
1175 void SchedulerStateMachine::DidManageTiles() {
1176 needs_manage_tiles_ = false;
1177 // "Fill" the ManageTiles funnel.
1178 manage_tiles_funnel_++;
1181 void SchedulerStateMachine::DidLoseOutputSurface() {
1182 if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
1183 output_surface_state_ == OUTPUT_SURFACE_CREATING)
1184 return;
1185 output_surface_state_ = OUTPUT_SURFACE_LOST;
1186 needs_redraw_ = false;
1189 void SchedulerStateMachine::NotifyReadyToActivate() {
1190 if (has_pending_tree_)
1191 pending_tree_is_ready_for_activation_ = true;
1194 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
1195 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING);
1196 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT;
1198 if (did_create_and_initialize_first_output_surface_) {
1199 // TODO(boliu): See if we can remove this when impl-side painting is always
1200 // on. Does anything on the main thread need to update after recreate?
1201 needs_commit_ = true;
1203 did_create_and_initialize_first_output_surface_ = true;
1206 void SchedulerStateMachine::NotifyBeginMainFrameStarted() {
1207 DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
1209 DCHECK(readback_state_ == READBACK_STATE_IDLE ||
1210 readback_state_ == READBACK_STATE_WAITING_FOR_COMMIT ||
1211 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT);
1213 commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED;
1216 bool SchedulerStateMachine::HasInitializedOutputSurface() const {
1217 switch (output_surface_state_) {
1218 case OUTPUT_SURFACE_LOST:
1219 case OUTPUT_SURFACE_CREATING:
1220 return false;
1222 case OUTPUT_SURFACE_ACTIVE:
1223 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
1224 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
1225 return true;
1227 NOTREACHED();
1228 return false;
1231 } // namespace cc