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