Upstream version 5.34.92.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_failed_draws_(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_failed_draws",
244                           consecutive_failed_draws_);
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   // We want to clear the pipline of any pending draws and activations
343   // before starting output surface initialization. This allows us to avoid
344   // weird corner cases where we abort draws or force activation while we
345   // are initializing the output surface and can potentially have a pending
346   // readback.
347   if (active_tree_needs_first_draw_ || has_pending_tree_)
348     return false;
349
350   // We need to create the output surface if we don't have one and we haven't
351   // started creating one yet.
352   return output_surface_state_ == OUTPUT_SURFACE_LOST;
353 }
354
355 bool SchedulerStateMachine::ShouldDraw() const {
356   // After a readback, make sure not to draw again until we've replaced the
357   // readback commit with a real one.
358   if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT ||
359       readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION)
360     return false;
361
362   // Draw immediately for readbacks to unblock the main thread quickly.
363   if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) {
364     DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
365     return true;
366   }
367
368   // If we need to abort draws, we should do so ASAP since the draw could
369   // be blocking other important actions (like output surface initialization),
370   // from occuring. If we are waiting for the first draw, then perfom the
371   // aborted draw to keep things moving. If we are not waiting for the first
372   // draw however, we don't want to abort for no reason.
373   if (PendingDrawsShouldBeAborted())
374     return active_tree_needs_first_draw_;
375
376   // After this line, we only want to swap once per frame.
377   if (HasSwappedThisFrame())
378     return false;
379
380   // Except for the cases above, do not draw outside of the BeginImplFrame
381   // deadline.
382   if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
383     return false;
384
385   // Only handle forced redraws due to timeouts on the regular deadline.
386   if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
387     DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
388     return true;
389   }
390
391   return needs_redraw_;
392 }
393
394 bool SchedulerStateMachine::ShouldAcquireLayerTexturesForMainThread() const {
395   if (!main_thread_needs_layer_textures_)
396     return false;
397   if (texture_state_ == LAYER_TEXTURE_STATE_UNLOCKED)
398     return true;
399   DCHECK_EQ(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD);
400   return false;
401 }
402
403 bool SchedulerStateMachine::ShouldActivatePendingTree() const {
404   // There is nothing to activate.
405   if (!has_pending_tree_)
406     return false;
407
408   // We should not activate a second tree before drawing the first one.
409   // Even if we need to force activation of the pending tree, we should abort
410   // drawing the active tree first.
411   if (active_tree_needs_first_draw_)
412     return false;
413
414   // If we want to force activation, do so ASAP.
415   if (PendingActivationsShouldBeForced())
416     return true;
417
418   // At this point, only activate if we are ready to activate.
419   return pending_tree_is_ready_for_activation_;
420 }
421
422 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const {
423   if (!settings_.impl_side_painting)
424     return false;
425   if (HasUpdatedVisibleTilesThisFrame())
426     return false;
427
428   // There's no reason to check for tiles if we don't have an output surface.
429   if (!HasInitializedOutputSurface())
430     return false;
431
432   // We should not check for visible tiles until we've entered the deadline so
433   // we check as late as possible and give the tiles more time to initialize.
434   if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
435     return false;
436
437   // If the last swap drew with checkerboard or missing tiles, we should
438   // poll for any new visible tiles so we can be notified to draw again
439   // when there are.
440   if (swap_used_incomplete_tile_)
441     return true;
442
443   return false;
444 }
445
446 bool SchedulerStateMachine::ShouldSendBeginMainFrame() const {
447   if (!needs_commit_)
448     return false;
449
450   // Only send BeginMainFrame when there isn't another commit pending already.
451   if (commit_state_ != COMMIT_STATE_IDLE)
452     return false;
453
454   // We can't accept a commit if we have a pending tree.
455   if (has_pending_tree_)
456     return false;
457
458   // We want to handle readback commits immediately to unblock the main thread.
459   // Note: This BeginMainFrame will correspond to the replacement commit that
460   // comes after the readback commit itself, so we only send the BeginMainFrame
461   // if a commit isn't already pending behind the readback.
462   if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME)
463     return !CommitPending();
464
465   // We do not need commits if we are not visible, unless there's a
466   // request for a readback.
467   if (!visible_)
468     return false;
469
470   // We want to start the first commit after we get a new output surface ASAP.
471   if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT)
472     return true;
473
474   // With deadline scheduling enabled, we should not send BeginMainFrame while
475   // we are in BEGIN_IMPL_FRAME_STATE_IDLE, since we might have new user input
476   // coming in soon.
477   // However, if we are not expecting a BeginImplFrame to take us out of idle,
478   // we should not early out here to avoid blocking commits forever.
479   // This only works well when deadline scheduling is enabled because there is
480   // an interval over which to accept the commit and draw. Without deadline
481   // scheduling, delaying the commit could prevent us from having something
482   // to draw on the next BeginImplFrame.
483   // TODO(brianderson): Allow sending BeginMainFrame while idle when the main
484   // thread isn't consuming user input.
485   if (settings_.deadline_scheduling_enabled &&
486       begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE &&
487       BeginImplFrameNeeded())
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   if (skip_begin_main_frame_to_reduce_latency_)
504     return false;
505
506   return true;
507 }
508
509 bool SchedulerStateMachine::ShouldCommit() const {
510   return commit_state_ == COMMIT_STATE_READY_TO_COMMIT;
511 }
512
513 bool SchedulerStateMachine::IsCommitStateWaiting() const {
514   return commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS;
515 }
516
517 bool SchedulerStateMachine::ShouldManageTiles() const {
518   // ManageTiles only really needs to be called immediately after commit
519   // and then periodically after that. Use a funnel to make sure we average
520   // one ManageTiles per BeginImplFrame in the long run.
521   if (manage_tiles_funnel_ > 0)
522     return false;
523
524   // Limiting to once per-frame is not enough, since we only want to
525   // manage tiles _after_ draws. Polling for draw triggers and
526   // begin-frame are mutually exclusive, so we limit to these two cases.
527   if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE &&
528       !inside_poll_for_anticipated_draw_triggers_)
529     return false;
530   return needs_manage_tiles_;
531 }
532
533 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
534   if (ShouldAcquireLayerTexturesForMainThread())
535     return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD;
536   if (ShouldUpdateVisibleTiles())
537     return ACTION_UPDATE_VISIBLE_TILES;
538   if (ShouldActivatePendingTree())
539     return ACTION_ACTIVATE_PENDING_TREE;
540   if (ShouldCommit())
541     return ACTION_COMMIT;
542   if (ShouldDraw()) {
543     if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK)
544       return ACTION_DRAW_AND_READBACK;
545     else if (PendingDrawsShouldBeAborted())
546       return ACTION_DRAW_AND_SWAP_ABORT;
547     else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
548       return ACTION_DRAW_AND_SWAP_FORCED;
549     else
550       return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
551   }
552   if (ShouldManageTiles())
553     return ACTION_MANAGE_TILES;
554   if (ShouldSendBeginMainFrame())
555     return ACTION_SEND_BEGIN_MAIN_FRAME;
556   if (ShouldBeginOutputSurfaceCreation())
557     return ACTION_BEGIN_OUTPUT_SURFACE_CREATION;
558   return ACTION_NONE;
559 }
560
561 void SchedulerStateMachine::CheckInvariants() {
562   // We should never try to perform a draw for readback and forced draw due to
563   // timeout simultaneously.
564   DCHECK(!(forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW &&
565            readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK));
566 }
567
568 void SchedulerStateMachine::UpdateState(Action action) {
569   switch (action) {
570     case ACTION_NONE:
571       return;
572
573     case ACTION_UPDATE_VISIBLE_TILES:
574       last_frame_number_update_visible_tiles_was_called_ =
575           current_frame_number_;
576       return;
577
578     case ACTION_ACTIVATE_PENDING_TREE:
579       UpdateStateOnActivation();
580       return;
581
582     case ACTION_SEND_BEGIN_MAIN_FRAME:
583       DCHECK(!has_pending_tree_);
584       DCHECK(visible_ ||
585              readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME);
586       commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
587       needs_commit_ = false;
588       if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME)
589         readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
590       last_frame_number_begin_main_frame_sent_ =
591           current_frame_number_;
592       return;
593
594     case ACTION_COMMIT: {
595       bool commit_was_aborted = false;
596       UpdateStateOnCommit(commit_was_aborted);
597       return;
598     }
599
600     case ACTION_DRAW_AND_SWAP_FORCED:
601     case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: {
602       bool did_swap = true;
603       UpdateStateOnDraw(did_swap);
604       return;
605     }
606
607     case ACTION_DRAW_AND_SWAP_ABORT:
608     case ACTION_DRAW_AND_READBACK: {
609       bool did_swap = false;
610       UpdateStateOnDraw(did_swap);
611       return;
612     }
613
614     case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
615       DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST);
616       output_surface_state_ = OUTPUT_SURFACE_CREATING;
617
618       // The following DCHECKs make sure we are in the proper quiescent state.
619       // The pipeline should be flushed entirely before we start output
620       // surface creation to avoid complicated corner cases.
621       DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE);
622       DCHECK(!has_pending_tree_);
623       DCHECK(!active_tree_needs_first_draw_);
624       return;
625
626     case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
627       texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD;
628       main_thread_needs_layer_textures_ = false;
629       return;
630
631     case ACTION_MANAGE_TILES:
632       UpdateStateOnManageTiles();
633       return;
634   }
635 }
636
637 void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) {
638   commit_count_++;
639
640   // If we are impl-side-painting but the commit was aborted, then we behave
641   // mostly as if we are not impl-side-painting since there is no pending tree.
642   has_pending_tree_ = settings_.impl_side_painting && !commit_was_aborted;
643
644   // Update state related to readbacks.
645   if (readback_state_ == READBACK_STATE_WAITING_FOR_COMMIT) {
646     // Update the state if this is the readback commit.
647     readback_state_ = has_pending_tree_
648                           ? READBACK_STATE_WAITING_FOR_ACTIVATION
649                           : READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
650   } else if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT) {
651     // Update the state if this is the commit replacing the readback commit.
652     readback_state_ = has_pending_tree_
653                           ? READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION
654                           : READBACK_STATE_IDLE;
655   } else {
656     DCHECK(readback_state_ == READBACK_STATE_IDLE);
657   }
658
659   // Readbacks can interrupt output surface initialization and forced draws,
660   // so we do not want to advance those states if we are in the middle of a
661   // readback. Note: It is possible for the readback's replacement commit to
662   // be the output surface's first commit and/or the forced redraw's commit.
663   if (readback_state_ == READBACK_STATE_IDLE ||
664       readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) {
665     // Update state related to forced draws.
666     if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) {
667       forced_redraw_state_ = has_pending_tree_
668                                  ? FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION
669                                  : FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
670     }
671
672     // Update the output surface state.
673     DCHECK_NE(output_surface_state_,
674               OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION);
675     if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) {
676       if (has_pending_tree_) {
677         output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION;
678       } else {
679         output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
680         needs_redraw_ = true;
681       }
682     }
683   }
684
685   // Update the commit state. We expect and wait for a draw if the commit
686   // was not aborted or if we are in a readback or forced draw.
687   if (!commit_was_aborted) {
688     DCHECK(commit_state_ == COMMIT_STATE_READY_TO_COMMIT);
689     commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
690   } else if (readback_state_ != READBACK_STATE_IDLE ||
691              forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE) {
692     commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
693   } else {
694     commit_state_ = COMMIT_STATE_IDLE;
695   }
696
697   // Update state if we have a new active tree to draw, or if the active tree
698   // was unchanged but we need to do a readback or forced draw.
699   if (!has_pending_tree_ &&
700       (!commit_was_aborted ||
701        readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK ||
702        forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)) {
703     needs_redraw_ = true;
704     active_tree_needs_first_draw_ = true;
705   }
706
707   // This post-commit work is common to both completed and aborted commits.
708   pending_tree_is_ready_for_activation_ = false;
709
710   if (draw_if_possible_failed_)
711     last_frame_number_swap_performed_ = -1;
712
713   // If we are planing to draw with the new commit, lock the layer textures for
714   // use on the impl thread. Otherwise, leave them unlocked.
715   if (has_pending_tree_ || needs_redraw_)
716     texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD;
717   else
718     texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED;
719 }
720
721 void SchedulerStateMachine::UpdateStateOnActivation() {
722   // Update output surface state.
723   if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
724     output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
725
726   // Update readback state
727   if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION)
728     forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
729
730   // Update forced redraw state
731   if (readback_state_ == READBACK_STATE_WAITING_FOR_ACTIVATION)
732     readback_state_ = READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
733   else if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION)
734     readback_state_ = READBACK_STATE_IDLE;
735
736   has_pending_tree_ = false;
737   pending_tree_is_ready_for_activation_ = false;
738   active_tree_needs_first_draw_ = true;
739   needs_redraw_ = true;
740 }
741
742 void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) {
743   DCHECK(readback_state_ != READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT &&
744          readback_state_ != READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION)
745       << *AsValue();
746
747   if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) {
748     // The draw correspons to a readback commit.
749     DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
750     // We are blocking commits from the main thread until after this draw, so
751     // we should not have a pending tree.
752     DCHECK(!has_pending_tree_);
753     // We transition to COMMIT_STATE_FRAME_IN_PROGRESS because there is a
754     // pending BeginMainFrame behind the readback request.
755     commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
756     readback_state_ = READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT;
757   } else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) {
758     DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
759     commit_state_ = COMMIT_STATE_IDLE;
760     forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
761   } else if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW &&
762              !has_pending_tree_) {
763     commit_state_ = COMMIT_STATE_IDLE;
764   }
765
766   if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD)
767     texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED;
768
769   needs_redraw_ = false;
770   draw_if_possible_failed_ = false;
771   active_tree_needs_first_draw_ = false;
772
773   if (did_swap)
774     last_frame_number_swap_performed_ = current_frame_number_;
775 }
776
777 void SchedulerStateMachine::UpdateStateOnManageTiles() {
778   needs_manage_tiles_ = false;
779 }
780
781 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() {
782   DCHECK(!main_thread_needs_layer_textures_);
783   DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD);
784   main_thread_needs_layer_textures_ = true;
785 }
786
787 void SchedulerStateMachine::SetSkipBeginMainFrameToReduceLatency(bool skip) {
788   skip_begin_main_frame_to_reduce_latency_ = skip;
789 }
790
791 bool SchedulerStateMachine::BeginImplFrameNeeded() const {
792   // Proactive BeginImplFrames are bad for the synchronous compositor because we
793   // have to draw when we get the BeginImplFrame and could end up drawing many
794   // duplicate frames if our new frame isn't ready in time.
795   // To poll for state with the synchronous compositor without having to draw,
796   // we rely on ShouldPollForAnticipatedDrawTriggers instead.
797   if (!SupportsProactiveBeginImplFrame())
798     return BeginImplFrameNeededToDraw();
799
800   return BeginImplFrameNeededToDraw() ||
801          ProactiveBeginImplFrameWanted();
802 }
803
804 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const {
805   // ShouldPollForAnticipatedDrawTriggers is what we use in place of
806   // ProactiveBeginImplFrameWanted when we are using the synchronous
807   // compositor.
808   if (!SupportsProactiveBeginImplFrame()) {
809     return !BeginImplFrameNeededToDraw() &&
810            ProactiveBeginImplFrameWanted();
811   }
812
813   // Non synchronous compositors should rely on
814   // ProactiveBeginImplFrameWanted to poll for state instead.
815   return false;
816 }
817
818 bool SchedulerStateMachine::SupportsProactiveBeginImplFrame() const {
819   // Both the synchronous compositor and disabled vsync settings
820   // make it undesirable to proactively request BeginImplFrames.
821   // If this is true, the scheduler should poll.
822   return !settings_.using_synchronous_renderer_compositor &&
823          settings_.throttle_frame_production;
824 }
825
826 // These are the cases where we definitely (or almost definitely) have a
827 // new frame to draw and can draw.
828 bool SchedulerStateMachine::BeginImplFrameNeededToDraw() const {
829   // The output surface is the provider of BeginImplFrames, so we are not going
830   // to get them even if we ask for them.
831   if (!HasInitializedOutputSurface())
832     return false;
833
834   // If we can't draw, don't tick until we are notified that we can draw again.
835   if (!can_draw_)
836     return false;
837
838   // The forced draw respects our normal draw scheduling, so we need to
839   // request a BeginImplFrame for it.
840   if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
841     return true;
842
843   // There's no need to produce frames if we are not visible.
844   if (!visible_)
845     return false;
846
847   // We need to draw a more complete frame than we did the last BeginImplFrame,
848   // so request another BeginImplFrame in anticipation that we will have
849   // additional visible tiles.
850   if (swap_used_incomplete_tile_)
851     return true;
852
853   return needs_redraw_;
854 }
855
856 // These are cases where we are very likely to draw soon, but might not
857 // actually have a new frame to draw when we receive the next BeginImplFrame.
858 // Proactively requesting the BeginImplFrame helps hide the round trip latency
859 // of the SetNeedsBeginImplFrame request that has to go to the Browser.
860 bool SchedulerStateMachine::ProactiveBeginImplFrameWanted() const {
861   // The output surface is the provider of BeginImplFrames,
862   // so we are not going to get them even if we ask for them.
863   if (!HasInitializedOutputSurface())
864     return false;
865
866   // Do not be proactive when invisible.
867   if (!visible_)
868     return false;
869
870   // We should proactively request a BeginImplFrame if a commit is pending
871   // because we will want to draw if the commit completes quickly.
872   if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE)
873     return true;
874
875   // If the pending tree activates quickly, we'll want a BeginImplFrame soon
876   // to draw the new active tree.
877   if (has_pending_tree_)
878     return true;
879
880   // Changing priorities may allow us to activate (given the new priorities),
881   // which may result in a new frame.
882   if (needs_manage_tiles_)
883     return true;
884
885   // If we just swapped, it's likely that we are going to produce another
886   // frame soon. This helps avoid negative glitches in our
887   // SetNeedsBeginImplFrame requests, which may propagate to the BeginImplFrame
888   // provider and get sampled at an inopportune time, delaying the next
889   // BeginImplFrame.
890   if (last_frame_number_swap_performed_ == current_frame_number_)
891     return true;
892
893   return false;
894 }
895
896 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) {
897   AdvanceCurrentFrameNumber();
898   last_begin_impl_frame_args_ = args;
899   DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) << *AsValue();
900   begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING;
901 }
902
903 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() {
904   DCHECK_EQ(begin_impl_frame_state_,
905             BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING)
906       << *AsValue();
907   begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME;
908 }
909
910 void SchedulerStateMachine::OnBeginImplFrameDeadline() {
911   DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
912       << *AsValue();
913   begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
914 }
915
916 void SchedulerStateMachine::OnBeginImplFrameIdle() {
917   DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
918       << *AsValue();
919   begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE;
920 }
921
922 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineEarly() const {
923   // TODO(brianderson): This should take into account multiple commit sources.
924
925   // If we are in the middle of the readback, we won't swap, so there is
926   // no reason to trigger the deadline early.
927   if (readback_state_ != READBACK_STATE_IDLE)
928     return false;
929
930   if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
931     return false;
932
933   if (active_tree_needs_first_draw_)
934     return true;
935
936   if (!needs_redraw_)
937     return false;
938
939   // This is used to prioritize impl-thread draws when the main thread isn't
940   // producing anything, e.g., after an aborted commit. We also check that we
941   // don't have a pending tree -- otherwise we should give it a chance to
942   // activate.
943   // TODO(skyostil): Revisit this when we have more accurate deadline estimates.
944   if (commit_state_ == COMMIT_STATE_IDLE && !has_pending_tree_)
945     return true;
946
947   // Prioritize impl-thread draws in smoothness mode.
948   if (smoothness_takes_priority_)
949     return true;
950
951   return false;
952 }
953
954 bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const {
955   // If we just sent a BeginMainFrame and haven't hit the deadline yet, the main
956   // thread is in a low latency mode.
957   if (last_frame_number_begin_main_frame_sent_ == current_frame_number_ &&
958       (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING ||
959        begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME))
960     return false;
961
962   // If there's a commit in progress it must either be from the previous frame
963   // or it started after the impl thread's deadline. In either case the main
964   // thread is in high latency mode.
965   if (commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS ||
966       commit_state_ == COMMIT_STATE_READY_TO_COMMIT)
967     return true;
968
969   // Similarly, if there's a pending tree the main thread is in high latency
970   // mode, because either
971   //   it's from the previous frame
972   // or
973   //   we're currently drawing the active tree and the pending tree will thus
974   //   only be drawn in the next frame.
975   if (has_pending_tree_)
976     return true;
977
978   if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) {
979     // Even if there's a new active tree to draw at the deadline or we've just
980     // drawn it, it may have been triggered by a previous BeginImplFrame, in
981     // which case the main thread is in a high latency mode.
982     return (active_tree_needs_first_draw_ ||
983             last_frame_number_swap_performed_ == current_frame_number_) &&
984            last_frame_number_begin_main_frame_sent_ != current_frame_number_;
985   }
986
987   // If the active tree needs its first draw in any other state, we know the
988   // main thread is in a high latency mode.
989   return active_tree_needs_first_draw_;
990 }
991
992 void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() {
993   AdvanceCurrentFrameNumber();
994   inside_poll_for_anticipated_draw_triggers_ = true;
995 }
996
997 void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() {
998   inside_poll_for_anticipated_draw_triggers_ = false;
999 }
1000
1001 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }
1002
1003 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }
1004
1005 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }
1006
1007 void SchedulerStateMachine::SetNeedsManageTiles() {
1008   if (!needs_manage_tiles_) {
1009     TRACE_EVENT0("cc",
1010                  "SchedulerStateMachine::SetNeedsManageTiles");
1011     needs_manage_tiles_ = true;
1012   }
1013 }
1014
1015 void SchedulerStateMachine::SetSwapUsedIncompleteTile(
1016     bool used_incomplete_tile) {
1017   swap_used_incomplete_tile_ = used_incomplete_tile;
1018 }
1019
1020 void SchedulerStateMachine::SetSmoothnessTakesPriority(
1021     bool smoothness_takes_priority) {
1022   smoothness_takes_priority_ = smoothness_takes_priority;
1023 }
1024
1025 void SchedulerStateMachine::DidDrawIfPossibleCompleted(bool success) {
1026   draw_if_possible_failed_ = !success;
1027   if (draw_if_possible_failed_) {
1028     needs_redraw_ = true;
1029
1030     // If we're already in the middle of a redraw, we don't need to
1031     // restart it.
1032     if (forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE)
1033       return;
1034
1035     needs_commit_ = true;
1036     consecutive_failed_draws_++;
1037     if (settings_.timeout_and_draw_when_animation_checkerboards &&
1038         consecutive_failed_draws_ >=
1039             settings_.maximum_number_of_failed_draws_before_draw_is_forced_) {
1040       consecutive_failed_draws_ = 0;
1041       // We need to force a draw, but it doesn't make sense to do this until
1042       // we've committed and have new textures.
1043       forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT;
1044     }
1045   } else {
1046     consecutive_failed_draws_ = 0;
1047     forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
1048   }
1049 }
1050
1051 void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; }
1052
1053 void SchedulerStateMachine::SetNeedsForcedCommitForReadback() {
1054   // If this is called in READBACK_STATE_IDLE, this is a "first" readback
1055   // request.
1056   // If this is called in READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT, this
1057   // is a back-to-back readback request that started before the replacement
1058   // commit had a chance to land.
1059   DCHECK(readback_state_ == READBACK_STATE_IDLE ||
1060          readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT);
1061
1062   // If there is already a commit in progress when we get the readback request
1063   // (we are in COMMIT_STATE_FRAME_IN_PROGRESS), then we don't need to send a
1064   // BeginMainFrame for the replacement commit, since there's already a
1065   // BeginMainFrame behind the readback request. In that case, we can skip
1066   // READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME and go directly to
1067   // READBACK_STATE_WAITING_FOR_COMMIT
1068   if (commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS)
1069     readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
1070   else
1071     readback_state_ = READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME;
1072 }
1073
1074 void SchedulerStateMachine::FinishCommit() {
1075   DCHECK(commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS) << *AsValue();
1076   commit_state_ = COMMIT_STATE_READY_TO_COMMIT;
1077 }
1078
1079 void SchedulerStateMachine::BeginMainFrameAborted(bool did_handle) {
1080   DCHECK_EQ(commit_state_, COMMIT_STATE_FRAME_IN_PROGRESS);
1081   if (did_handle) {
1082     bool commit_was_aborted = true;
1083     UpdateStateOnCommit(commit_was_aborted);
1084   } else {
1085     DCHECK_NE(readback_state_, READBACK_STATE_WAITING_FOR_COMMIT);
1086     commit_state_ = COMMIT_STATE_IDLE;
1087     SetNeedsCommit();
1088   }
1089 }
1090
1091 void SchedulerStateMachine::DidManageTiles() {
1092   needs_manage_tiles_ = false;
1093   // "Fill" the ManageTiles funnel.
1094   manage_tiles_funnel_++;
1095 }
1096
1097 void SchedulerStateMachine::DidLoseOutputSurface() {
1098   if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
1099       output_surface_state_ == OUTPUT_SURFACE_CREATING)
1100     return;
1101   output_surface_state_ = OUTPUT_SURFACE_LOST;
1102   needs_redraw_ = false;
1103   begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE;
1104 }
1105
1106 void SchedulerStateMachine::NotifyReadyToActivate() {
1107   if (has_pending_tree_)
1108     pending_tree_is_ready_for_activation_ = true;
1109 }
1110
1111 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
1112   DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING);
1113   output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT;
1114
1115   if (did_create_and_initialize_first_output_surface_) {
1116     // TODO(boliu): See if we can remove this when impl-side painting is always
1117     // on. Does anything on the main thread need to update after recreate?
1118     needs_commit_ = true;
1119   }
1120   did_create_and_initialize_first_output_surface_ = true;
1121 }
1122
1123 bool SchedulerStateMachine::HasInitializedOutputSurface() const {
1124   switch (output_surface_state_) {
1125     case OUTPUT_SURFACE_LOST:
1126     case OUTPUT_SURFACE_CREATING:
1127       return false;
1128
1129     case OUTPUT_SURFACE_ACTIVE:
1130     case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT:
1131     case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION:
1132       return true;
1133   }
1134   NOTREACHED();
1135   return false;
1136 }
1137
1138 }  // namespace cc