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