Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / cc / scheduler / scheduler_state_machine.cc
1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cc/scheduler/scheduler_state_machine.h"
6
7 #include "base/debug/trace_event.h"
8 #include "base/format_macros.h"
9 #include "base/logging.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/values.h"
12 #include "ui/gfx/frame_time.h"
13
14 namespace cc {
15
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) {
51 }
52
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";
66   }
67   NOTREACHED();
68   return "???";
69 }
70
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";
82   }
83   NOTREACHED();
84   return "???";
85 }
86
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";
101   }
102   NOTREACHED();
103   return "???";
104 }
105
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";
123   }
124   NOTREACHED();
125   return "???";
126 }
127
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";
139   }
140   NOTREACHED();
141   return "???";
142 }
143
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";
170   }
171   NOTREACHED();
172   return "???";
173 }
174
175 scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const  {
176   scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
177
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());
191
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());
218
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_);
222
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_);
233
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());
265
266   return state.PassAs<base::Value>();
267 }
268
269 void SchedulerStateMachine::AdvanceCurrentFrameNumber() {
270   current_frame_number_++;
271
272   // "Drain" the ManageTiles funnel.
273   if (manage_tiles_funnel_ > 0)
274     manage_tiles_funnel_--;
275
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;
279 }
280
281 bool SchedulerStateMachine::HasSentBeginMainFrameThisFrame() const {
282   return current_frame_number_ ==
283          last_frame_number_begin_main_frame_sent_;
284 }
285
286 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const {
287   return current_frame_number_ ==
288          last_frame_number_update_visible_tiles_was_called_;
289 }
290
291 bool SchedulerStateMachine::HasSwappedThisFrame() const {
292   return current_frame_number_ == last_frame_number_swap_performed_;
293 }
294
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;
304
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;
313 }
314
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.
318
319   // There is no output surface to trigger our activations.
320   if (output_surface_state_ == OUTPUT_SURFACE_LOST)
321     return true;
322
323   return false;
324 }
325
326 bool SchedulerStateMachine::ShouldBeginOutputSurfaceCreation() const {
327   // Don't try to initialize too early.
328   if (!can_start_)
329     return false;
330
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;
335
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;
340
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;
348
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;
352 }
353
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;
360
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;
364
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_;
372
373   // After this line, we only want to swap once per frame.
374   if (HasSwappedThisFrame())
375     return false;
376
377   // Do not queue too many swaps.
378   if (pending_swaps_ >= max_pending_swaps_)
379     return false;
380
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;
385
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;
389
390   return needs_redraw_;
391 }
392
393 bool SchedulerStateMachine::ShouldActivatePendingTree() const {
394   // There is nothing to activate.
395   if (!has_pending_tree_)
396     return false;
397
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;
403
404   // If we want to force activation, do so ASAP.
405   if (PendingActivationsShouldBeForced())
406     return true;
407
408   // At this point, only activate if we are ready to activate.
409   return pending_tree_is_ready_for_activation_;
410 }
411
412 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const {
413   if (!settings_.impl_side_painting)
414     return false;
415   if (HasUpdatedVisibleTilesThisFrame())
416     return false;
417
418   // There's no reason to check for tiles if we don't have an output surface.
419   if (!HasInitializedOutputSurface())
420     return false;
421
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;
426
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;
432
433   return false;
434 }
435
436 bool SchedulerStateMachine::ShouldAnimate() const {
437   if (!can_draw_)
438     return false;
439
440   if (last_frame_number_animate_performed_ == current_frame_number_)
441     return false;
442
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;
446
447   return needs_redraw_ || needs_animate_;
448 }
449
450 bool SchedulerStateMachine::ShouldSendBeginMainFrame() const {
451   if (!needs_commit_)
452     return false;
453
454   // Only send BeginMainFrame when there isn't another commit pending already.
455   if (commit_state_ != COMMIT_STATE_IDLE)
456     return false;
457
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;
463   }
464
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();
471
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;
476
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;
480
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;
489
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;
494
495   // After this point, we only start a commit once per frame.
496   if (HasSentBeginMainFrameThisFrame())
497     return false;
498
499   // We shouldn't normally accept commits if there isn't an OutputSurface.
500   if (!HasInitializedOutputSurface())
501     return false;
502
503   // SwapAck throttle the BeginMainFrames
504   // TODO(brianderson): Remove this restriction to improve throughput.
505   if (pending_swaps_ >= max_pending_swaps_)
506     return false;
507
508   if (skip_begin_main_frame_to_reduce_latency_)
509     return false;
510
511   return true;
512 }
513
514 bool SchedulerStateMachine::ShouldCommit() const {
515   if (commit_state_ != COMMIT_STATE_READY_TO_COMMIT)
516     return false;
517
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;
522   }
523
524   // Prioritize drawing the previous commit before finishing the next commit.
525   if (active_tree_needs_first_draw_)
526     return false;
527
528   return true;
529 }
530
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;
537
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_;
545 }
546
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;
565   }
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;
573 }
574
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));
580 }
581
582 void SchedulerStateMachine::UpdateState(Action action) {
583   switch (action) {
584     case ACTION_NONE:
585       return;
586
587     case ACTION_UPDATE_VISIBLE_TILES:
588       last_frame_number_update_visible_tiles_was_called_ =
589           current_frame_number_;
590       return;
591
592     case ACTION_ACTIVATE_PENDING_TREE:
593       UpdateStateOnActivation();
594       return;
595
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;
603
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;
618
619     case ACTION_COMMIT: {
620       bool commit_was_aborted = false;
621       UpdateStateOnCommit(commit_was_aborted);
622       return;
623     }
624
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;
630     }
631
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;
637     }
638
639     case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
640       DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST);
641       output_surface_state_ = OUTPUT_SURFACE_CREATING;
642
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;
650
651     case ACTION_MANAGE_TILES:
652       UpdateStateOnManageTiles();
653       return;
654   }
655 }
656
657 void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) {
658   commit_count_++;
659
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;
668   }
669
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;
673
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);
687   }
688
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;
700     }
701
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;
711       }
712     }
713   }
714
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;
723   }
724
725   // This post-commit work is common to both completed and aborted commits.
726   pending_tree_is_ready_for_activation_ = false;
727
728   if (continuous_painting_)
729     needs_commit_ = true;
730 }
731
732 void SchedulerStateMachine::UpdateStateOnActivation() {
733   if (commit_state_ == COMMIT_STATE_WAITING_FOR_ACTIVATION)
734     commit_state_ = COMMIT_STATE_IDLE;
735
736   if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
737     output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
738
739   if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION)
740     forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
741
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;
756       }
757       needs_back_to_back_readback_ = false;
758     } else {
759       readback_state_ = READBACK_STATE_IDLE;
760     }
761   }
762
763   has_pending_tree_ = false;
764   pending_tree_is_ready_for_activation_ = false;
765   active_tree_needs_first_draw_ = true;
766   needs_redraw_ = true;
767 }
768
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();
773
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;
785   }
786
787   if (!has_pending_tree_ &&
788       commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW) {
789     commit_state_ = COMMIT_STATE_IDLE;
790   }
791
792   needs_redraw_ = false;
793   active_tree_needs_first_draw_ = false;
794
795   if (did_request_swap)
796     last_frame_number_swap_performed_ = current_frame_number_;
797 }
798
799 void SchedulerStateMachine::UpdateStateOnManageTiles() {
800   needs_manage_tiles_ = false;
801 }
802
803 void SchedulerStateMachine::SetSkipNextBeginMainFrameToReduceLatency() {
804   skip_next_begin_main_frame_to_reduce_latency_ = true;
805 }
806
807 bool SchedulerStateMachine::BeginFrameNeeded() const {
808   // Proactive BeginFrames are bad for the synchronous compositor because we
809   // have to draw when we get the BeginFrame and could end up drawing many
810   // duplicate frames if our new frame isn't ready in time.
811   // To poll for state with the synchronous compositor without having to draw,
812   // we rely on ShouldPollForAnticipatedDrawTriggers instead.
813   if (!SupportsProactiveBeginFrame())
814     return BeginFrameNeededToAnimateOrDraw();
815
816   return BeginFrameNeededToAnimateOrDraw() || ProactiveBeginFrameWanted();
817 }
818
819 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const {
820   // ShouldPollForAnticipatedDrawTriggers is what we use in place of
821   // ProactiveBeginFrameWanted when we are using the synchronous
822   // compositor.
823   if (!SupportsProactiveBeginFrame()) {
824     return !BeginFrameNeededToAnimateOrDraw() && ProactiveBeginFrameWanted();
825   }
826
827   // Non synchronous compositors should rely on
828   // ProactiveBeginFrameWanted to poll for state instead.
829   return false;
830 }
831
832 // Note: If SupportsProactiveBeginFrame is false, the scheduler should poll
833 // for changes in it's draw state so it can request a BeginFrame when it's
834 // actually ready.
835 bool SchedulerStateMachine::SupportsProactiveBeginFrame() const {
836   // It is undesirable to proactively request BeginFrames if we are
837   // using a synchronous compositor because we *must* draw for every
838   // BeginFrame, which could cause duplicate draws.
839   return !settings_.using_synchronous_renderer_compositor;
840 }
841
842 // These are the cases where we definitely (or almost definitely) have a
843 // new frame to animate and/or draw and can draw.
844 bool SchedulerStateMachine::BeginFrameNeededToAnimateOrDraw() const {
845   // The output surface is the provider of BeginImplFrames, so we are not going
846   // to get them even if we ask for them.
847   if (!HasInitializedOutputSurface())
848     return false;
849
850   // If we can't draw, don't tick until we are notified that we can draw again.
851   if (!can_draw_)
852     return false;
853
854   // The forced draw respects our normal draw scheduling, so we need to
855   // request a BeginImplFrame for it.
856   if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
857     return true;
858
859   // There's no need to produce frames if we are not visible.
860   if (!visible_)
861     return false;
862
863   // We need to draw a more complete frame than we did the last BeginImplFrame,
864   // so request another BeginImplFrame in anticipation that we will have
865   // additional visible tiles.
866   if (swap_used_incomplete_tile_)
867     return true;
868
869   if (needs_animate_)
870     return true;
871
872   return needs_redraw_;
873 }
874
875 // These are cases where we are very likely to draw soon, but might not
876 // actually have a new frame to draw when we receive the next BeginImplFrame.
877 // Proactively requesting the BeginImplFrame helps hide the round trip latency
878 // of the SetNeedsBeginFrame request that has to go to the Browser.
879 bool SchedulerStateMachine::ProactiveBeginFrameWanted() const {
880   // The output surface is the provider of BeginImplFrames,
881   // so we are not going to get them even if we ask for them.
882   if (!HasInitializedOutputSurface())
883     return false;
884
885   // Do not be proactive when invisible.
886   if (!visible_)
887     return false;
888
889   // We should proactively request a BeginImplFrame if a commit is pending
890   // because we will want to draw if the commit completes quickly.
891   if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE)
892     return true;
893
894   // If the pending tree activates quickly, we'll want a BeginImplFrame soon
895   // to draw the new active tree.
896   if (has_pending_tree_)
897     return true;
898
899   // Changing priorities may allow us to activate (given the new priorities),
900   // which may result in a new frame.
901   if (needs_manage_tiles_)
902     return true;
903
904   // If we just swapped, it's likely that we are going to produce another
905   // frame soon. This helps avoid negative glitches in our
906   // SetNeedsBeginFrame requests, which may propagate to the BeginImplFrame
907   // provider and get sampled at an inopportune time, delaying the next
908   // BeginImplFrame.
909   if (last_frame_number_swap_performed_ == current_frame_number_)
910     return true;
911
912   return false;
913 }
914
915 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) {
916   AdvanceCurrentFrameNumber();
917   begin_impl_frame_args_ = args;
918   DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) << *AsValue();
919   begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING;
920 }
921
922 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() {
923   DCHECK_EQ(begin_impl_frame_state_,
924             BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING)
925       << *AsValue();
926   begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME;
927 }
928
929 void SchedulerStateMachine::OnBeginImplFrameDeadline() {
930   DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
931       << *AsValue();
932   begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
933 }
934
935 void SchedulerStateMachine::OnBeginImplFrameIdle() {
936   DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
937       << *AsValue();
938   begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE;
939 }
940
941 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineEarly() const {
942   // TODO(brianderson): This should take into account multiple commit sources.
943
944   // If we are in the middle of the readback, we won't swap, so there is
945   // no reason to trigger the deadline early.
946   if (readback_state_ != READBACK_STATE_IDLE)
947     return false;
948
949   if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
950     return false;
951
952   // If we've lost the output surface, end the current BeginImplFrame ASAP
953   // so we can start creating the next output surface.
954   if (output_surface_state_ == OUTPUT_SURFACE_LOST)
955     return true;
956
957   // SwapAck throttle the deadline since we wont draw and swap anyway.
958   if (pending_swaps_ >= max_pending_swaps_)
959     return false;
960
961   if (active_tree_needs_first_draw_)
962     return true;
963
964   if (!needs_redraw_)
965     return false;
966
967   // This is used to prioritize impl-thread draws when the main thread isn't
968   // producing anything, e.g., after an aborted commit. We also check that we
969   // don't have a pending tree -- otherwise we should give it a chance to
970   // activate.
971   // TODO(skyostil): Revisit this when we have more accurate deadline estimates.
972   if (commit_state_ == COMMIT_STATE_IDLE && !has_pending_tree_)
973     return true;
974
975   // Prioritize impl-thread draws in smoothness mode.
976   if (smoothness_takes_priority_)
977     return true;
978
979   return false;
980 }
981
982 bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const {
983   // If a commit is pending before the previous commit has been drawn, we
984   // are definitely in a high latency mode.
985   if (CommitPending() && (active_tree_needs_first_draw_ || has_pending_tree_))
986     return true;
987
988   // If we just sent a BeginMainFrame and haven't hit the deadline yet, the main
989   // thread is in a low latency mode.
990   if (last_frame_number_begin_main_frame_sent_ == current_frame_number_ &&
991       (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING ||
992        begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME))
993     return false;
994
995   // If there's a commit in progress it must either be from the previous frame
996   // or it started after the impl thread's deadline. In either case the main
997   // thread is in high latency mode.
998   if (commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
999       commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED ||
1000       commit_state_ == COMMIT_STATE_READY_TO_COMMIT)
1001     return true;
1002
1003   // Similarly, if there's a pending tree the main thread is in high latency
1004   // mode, because either
1005   //   it's from the previous frame
1006   // or
1007   //   we're currently drawing the active tree and the pending tree will thus
1008   //   only be drawn in the next frame.
1009   if (has_pending_tree_)
1010     return true;
1011
1012   if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) {
1013     // Even if there's a new active tree to draw at the deadline or we've just
1014     // drawn it, it may have been triggered by a previous BeginImplFrame, in
1015     // which case the main thread is in a high latency mode.
1016     return (active_tree_needs_first_draw_ ||
1017             last_frame_number_swap_performed_ == current_frame_number_) &&
1018            last_frame_number_begin_main_frame_sent_ != current_frame_number_;
1019   }
1020
1021   // If the active tree needs its first draw in any other state, we know the
1022   // main thread is in a high latency mode.
1023   return active_tree_needs_first_draw_;
1024 }
1025
1026 void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() {
1027   AdvanceCurrentFrameNumber();
1028   inside_poll_for_anticipated_draw_triggers_ = true;
1029 }
1030
1031 void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() {
1032   inside_poll_for_anticipated_draw_triggers_ = false;
1033 }
1034
1035 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }
1036
1037 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }
1038
1039 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }
1040
1041 void SchedulerStateMachine::SetNeedsAnimate() {
1042   needs_animate_ = true;
1043 }
1044
1045 void SchedulerStateMachine::SetNeedsManageTiles() {
1046   if (!needs_manage_tiles_) {
1047     TRACE_EVENT0("cc",
1048                  "SchedulerStateMachine::SetNeedsManageTiles");
1049     needs_manage_tiles_ = true;
1050   }
1051 }
1052
1053 void SchedulerStateMachine::SetMaxSwapsPending(int max) {
1054   max_pending_swaps_ = max;
1055 }
1056
1057 void SchedulerStateMachine::DidSwapBuffers() {
1058   pending_swaps_++;
1059   DCHECK_LE(pending_swaps_, max_pending_swaps_);
1060 }
1061
1062 void SchedulerStateMachine::SetSwapUsedIncompleteTile(
1063     bool used_incomplete_tile) {
1064   swap_used_incomplete_tile_ = used_incomplete_tile;
1065 }
1066
1067 void SchedulerStateMachine::DidSwapBuffersComplete() {
1068   DCHECK_GT(pending_swaps_, 0);
1069   pending_swaps_--;
1070 }
1071
1072 void SchedulerStateMachine::SetSmoothnessTakesPriority(
1073     bool smoothness_takes_priority) {
1074   smoothness_takes_priority_ = smoothness_takes_priority;
1075 }
1076
1077 void SchedulerStateMachine::DidDrawIfPossibleCompleted(
1078     DrawSwapReadbackResult::DrawResult result) {
1079   switch (result) {
1080     case DrawSwapReadbackResult::INVALID_RESULT:
1081       NOTREACHED() << "Uninitialized DrawSwapReadbackResult.";
1082       break;
1083     case DrawSwapReadbackResult::DRAW_ABORTED_CANT_DRAW:
1084     case DrawSwapReadbackResult::DRAW_ABORTED_CANT_READBACK:
1085     case DrawSwapReadbackResult::DRAW_ABORTED_CONTEXT_LOST:
1086       NOTREACHED() << "Invalid return value from DrawAndSwapIfPossible:"
1087                    << result;
1088       break;
1089     case DrawSwapReadbackResult::DRAW_SUCCESS:
1090       consecutive_checkerboard_animations_ = 0;
1091       forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
1092       break;
1093     case DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS:
1094       needs_redraw_ = true;
1095
1096       // If we're already in the middle of a redraw, we don't need to
1097       // restart it.
1098       if (forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE)
1099         return;
1100
1101       needs_commit_ = true;
1102       consecutive_checkerboard_animations_++;
1103       if (settings_.timeout_and_draw_when_animation_checkerboards &&
1104           consecutive_checkerboard_animations_ >=
1105               settings_.maximum_number_of_failed_draws_before_draw_is_forced_) {
1106         consecutive_checkerboard_animations_ = 0;
1107         // We need to force a draw, but it doesn't make sense to do this until
1108         // we've committed and have new textures.
1109         forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT;
1110       }
1111       break;
1112     case DrawSwapReadbackResult::DRAW_ABORTED_MISSING_HIGH_RES_CONTENT:
1113       // It's not clear whether this missing content is because of missing
1114       // pictures (which requires a commit) or because of memory pressure
1115       // removing textures (which might not).  To be safe, request a commit
1116       // anyway.
1117       needs_commit_ = true;
1118       break;
1119   }
1120 }
1121
1122 void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; }
1123
1124 void SchedulerStateMachine::SetNeedsForcedCommitForReadback() {
1125   // If this is called in READBACK_STATE_IDLE, this is a "first" readback
1126   // request.
1127   // If this is called in READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT, this
1128   // is a back-to-back readback request that started before the replacement
1129   // commit had a chance to land.
1130   // If this is called in READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION,
1131   // this is a readback-commit-readback request when replacement commit is in
1132   // impl-side painting.
1133   DCHECK(readback_state_ == READBACK_STATE_IDLE ||
1134          readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT ||
1135          readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION);
1136
1137   if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) {
1138     // If new forced commit is requested when impl-side painting of replacement
1139     // commit is in progress, it should not interrupt the draw & swap of current
1140     // commit(replacement commit). New commit(incoming forced commit) should be
1141     // started after current commit is finished.
1142     needs_back_to_back_readback_ = true;
1143   } else if (commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT) {
1144     // If there is already a commit in progress when we get the readback request
1145     // then we don't need to send a BeginMainFrame for the replacement commit,
1146     // since there's already a BeginMainFrame behind the readback request. In
1147     // that case, we can skip READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME and go
1148     // directly to READBACK_STATE_WAITING_FOR_COMMIT.
1149     readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
1150   } else {
1151     // Set needs_commit_ to true to trigger scheduling BeginMainFrame().
1152     needs_commit_ = true;
1153     readback_state_ = READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME;
1154   }
1155 }
1156
1157 void SchedulerStateMachine::NotifyReadyToCommit() {
1158   DCHECK(commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED) << *AsValue();
1159   commit_state_ = COMMIT_STATE_READY_TO_COMMIT;
1160 }
1161
1162 void SchedulerStateMachine::BeginMainFrameAborted(bool did_handle) {
1163   DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
1164   if (did_handle) {
1165     bool commit_was_aborted = true;
1166     UpdateStateOnCommit(commit_was_aborted);
1167   } else {
1168     DCHECK_NE(readback_state_, READBACK_STATE_WAITING_FOR_COMMIT);
1169     commit_state_ = COMMIT_STATE_IDLE;
1170     SetNeedsCommit();
1171   }
1172 }
1173
1174 void SchedulerStateMachine::DidManageTiles() {
1175   needs_manage_tiles_ = false;
1176   // "Fill" the ManageTiles funnel.
1177   manage_tiles_funnel_++;
1178 }
1179
1180 void SchedulerStateMachine::DidLoseOutputSurface() {
1181   if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
1182       output_surface_state_ == OUTPUT_SURFACE_CREATING)
1183     return;
1184   output_surface_state_ = OUTPUT_SURFACE_LOST;
1185   needs_redraw_ = false;
1186 }
1187
1188 void SchedulerStateMachine::NotifyReadyToActivate() {
1189   if (has_pending_tree_)
1190     pending_tree_is_ready_for_activation_ = true;
1191 }
1192
1193 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
1194   DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING);
1195   output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT;
1196
1197   if (did_create_and_initialize_first_output_surface_) {
1198     // TODO(boliu): See if we can remove this when impl-side painting is always
1199     // on. Does anything on the main thread need to update after recreate?
1200     needs_commit_ = true;
1201   }
1202   did_create_and_initialize_first_output_surface_ = true;
1203   pending_swaps_ = 0;
1204 }
1205
1206 void SchedulerStateMachine::NotifyBeginMainFrameStarted() {
1207   DCHECK_EQ(commit_state_, COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
1208
1209   DCHECK(readback_state_ == READBACK_STATE_IDLE ||
1210          readback_state_ == READBACK_STATE_WAITING_FOR_COMMIT ||
1211          readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT);
1212
1213   commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED;
1214 }
1215
1216 bool SchedulerStateMachine::HasInitializedOutputSurface() const {
1217   switch (output_surface_state_) {
1218     case OUTPUT_SURFACE_LOST:
1219     case OUTPUT_SURFACE_CREATING:
1220       return false;
1221
1222     case OUTPUT_SURFACE_ACTIVE:
1223     case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
1224     case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
1225       return true;
1226   }
1227   NOTREACHED();
1228   return false;
1229 }
1230
1231 }  // namespace cc