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