Home | History | Annotate | Download | only in scheduler
      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 #ifndef CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_
      6 #define CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_
      7 
      8 #include <string>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/time/time.h"
     13 #include "cc/base/cc_export.h"
     14 #include "cc/output/begin_frame_args.h"
     15 #include "cc/scheduler/draw_result.h"
     16 #include "cc/scheduler/scheduler_settings.h"
     17 
     18 namespace base {
     19 namespace debug {
     20 class ConvertableToTraceForamt;
     21 class TracedValue;
     22 }
     23 class Value;
     24 }
     25 
     26 namespace cc {
     27 
     28 // The SchedulerStateMachine decides how to coordinate main thread activites
     29 // like painting/running javascript with rendering and input activities on the
     30 // impl thread.
     31 //
     32 // The state machine tracks internal state but is also influenced by external
     33 // state.  Internal state includes things like whether a frame has been
     34 // requested, while external state includes things like the current time being
     35 // near to the vblank time.
     36 //
     37 // The scheduler seperates "what to do next" from the updating of its internal
     38 // state to make testing cleaner.
     39 class CC_EXPORT SchedulerStateMachine {
     40  public:
     41   // settings must be valid for the lifetime of this class.
     42   explicit SchedulerStateMachine(const SchedulerSettings& settings);
     43 
     44   enum OutputSurfaceState {
     45     OUTPUT_SURFACE_ACTIVE,
     46     OUTPUT_SURFACE_LOST,
     47     OUTPUT_SURFACE_CREATING,
     48     OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT,
     49     OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION,
     50   };
     51   static const char* OutputSurfaceStateToString(OutputSurfaceState state);
     52 
     53   // Note: BeginImplFrameState will always cycle through all the states in
     54   // order. Whether or not it actually waits or draws, it will at least try to
     55   // wait in BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME and try to draw in
     56   // BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
     57   enum BeginImplFrameState {
     58     BEGIN_IMPL_FRAME_STATE_IDLE,
     59     BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
     60     BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
     61     BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE,
     62   };
     63   static const char* BeginImplFrameStateToString(BeginImplFrameState state);
     64 
     65   enum CommitState {
     66     COMMIT_STATE_IDLE,
     67     COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
     68     COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED,
     69     COMMIT_STATE_READY_TO_COMMIT,
     70     COMMIT_STATE_WAITING_FOR_ACTIVATION,
     71     COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
     72   };
     73   static const char* CommitStateToString(CommitState state);
     74 
     75   enum ForcedRedrawOnTimeoutState {
     76     FORCED_REDRAW_STATE_IDLE,
     77     FORCED_REDRAW_STATE_WAITING_FOR_COMMIT,
     78     FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION,
     79     FORCED_REDRAW_STATE_WAITING_FOR_DRAW,
     80   };
     81   static const char* ForcedRedrawOnTimeoutStateToString(
     82       ForcedRedrawOnTimeoutState state);
     83 
     84   bool CommitPending() const {
     85     return commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT ||
     86            commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED ||
     87            commit_state_ == COMMIT_STATE_READY_TO_COMMIT;
     88   }
     89   CommitState commit_state() const { return commit_state_; }
     90 
     91   bool RedrawPending() const { return needs_redraw_; }
     92   bool ManageTilesPending() const { return needs_manage_tiles_; }
     93 
     94   enum Action {
     95     ACTION_NONE,
     96     ACTION_ANIMATE,
     97     ACTION_SEND_BEGIN_MAIN_FRAME,
     98     ACTION_COMMIT,
     99     ACTION_UPDATE_VISIBLE_TILES,
    100     ACTION_ACTIVATE_SYNC_TREE,
    101     ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
    102     ACTION_DRAW_AND_SWAP_FORCED,
    103     ACTION_DRAW_AND_SWAP_ABORT,
    104     ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
    105     ACTION_MANAGE_TILES,
    106   };
    107   static const char* ActionToString(Action action);
    108 
    109   scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
    110   void AsValueInto(base::debug::TracedValue* dict, base::TimeTicks now) const;
    111 
    112   Action NextAction() const;
    113   void UpdateState(Action action);
    114 
    115   // Indicates whether the impl thread needs a BeginImplFrame callback in order
    116   // to make progress.
    117   bool BeginFrameNeeded() const;
    118 
    119   // Indicates that we need to independently poll for new state and actions
    120   // because we can't expect a BeginImplFrame. This is mostly used to avoid
    121   // drawing repeat frames with the synchronous compositor without dropping
    122   // necessary actions on the floor.
    123   bool ShouldPollForAnticipatedDrawTriggers() const;
    124 
    125   // Indicates that the system has entered and left a BeginImplFrame callback.
    126   // The scheduler will not draw more than once in a given BeginImplFrame
    127   // callback nor send more than one BeginMainFrame message.
    128   void OnBeginImplFrame(const BeginFrameArgs& args);
    129   void OnBeginImplFrameDeadlinePending();
    130   void OnBeginImplFrameDeadline();
    131   void OnBeginImplFrameIdle();
    132   bool ShouldTriggerBeginImplFrameDeadlineEarly() const;
    133   BeginImplFrameState begin_impl_frame_state() const {
    134     return begin_impl_frame_state_;
    135   }
    136 
    137   // If the main thread didn't manage to produce a new frame in time for the
    138   // impl thread to draw, it is in a high latency mode.
    139   bool MainThreadIsInHighLatencyMode() const;
    140 
    141   // PollForAnticipatedDrawTriggers is used by the synchronous compositor to
    142   // avoid requesting BeginImplFrames when we won't actually draw but still
    143   // need to advance our state at vsync intervals.
    144   void DidEnterPollForAnticipatedDrawTriggers();
    145   void DidLeavePollForAnticipatedDrawTriggers();
    146   bool inside_poll_for_anticipated_draw_triggers() const {
    147     return inside_poll_for_anticipated_draw_triggers_;
    148   }
    149 
    150   // Indicates whether the LayerTreeHostImpl is visible.
    151   void SetVisible(bool visible);
    152 
    153   // Indicates that a redraw is required, either due to the impl tree changing
    154   // or the screen being damaged and simply needing redisplay.
    155   void SetNeedsRedraw();
    156   bool needs_redraw() const { return needs_redraw_; }
    157 
    158   void SetNeedsAnimate();
    159   bool needs_animate() const { return needs_animate_; }
    160 
    161   // Indicates that manage-tiles is required. This guarantees another
    162   // ManageTiles will occur shortly (even if no redraw is required).
    163   void SetNeedsManageTiles();
    164 
    165   // Sets how many swaps can be pending to the OutputSurface.
    166   void SetMaxSwapsPending(int max);
    167 
    168   // If the scheduler attempted to draw and swap, this provides feedback
    169   // regarding whether or not the swap actually occured. We might skip the
    170   // swap when there is not damage, for example.
    171   void DidSwapBuffers();
    172 
    173   // Indicates whether a redraw is required because we are currently rendering
    174   // with a low resolution or checkerboarded tile.
    175   void SetSwapUsedIncompleteTile(bool used_incomplete_tile);
    176 
    177   // Notification from the OutputSurface that a swap has been consumed.
    178   void DidSwapBuffersComplete();
    179 
    180   // Indicates whether to prioritize impl thread latency (i.e., animation
    181   // smoothness) over new content activation.
    182   void SetImplLatencyTakesPriority(bool impl_latency_takes_priority);
    183   bool impl_latency_takes_priority() const {
    184     return impl_latency_takes_priority_;
    185   }
    186 
    187   // Indicates whether ACTION_DRAW_AND_SWAP_IF_POSSIBLE drew to the screen.
    188   void DidDrawIfPossibleCompleted(DrawResult result);
    189 
    190   // Indicates that a new commit flow needs to be performed, either to pull
    191   // updates from the main thread to the impl, or to push deltas from the impl
    192   // thread to main.
    193   void SetNeedsCommit();
    194 
    195   // Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME
    196   // from NextAction.
    197   // Indicates that all painting is complete.
    198   void NotifyReadyToCommit();
    199 
    200   // Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME
    201   // from NextAction if the client rejects the BeginMainFrame message.
    202   // If did_handle is false, then another commit will be retried soon.
    203   void BeginMainFrameAborted(bool did_handle);
    204 
    205   // Set that we can create the first OutputSurface and start the scheduler.
    206   void SetCanStart() { can_start_ = true; }
    207 
    208   void SetSkipNextBeginMainFrameToReduceLatency();
    209 
    210   // Indicates whether drawing would, at this time, make sense.
    211   // CanDraw can be used to suppress flashes or checkerboarding
    212   // when such behavior would be undesirable.
    213   void SetCanDraw(bool can);
    214 
    215   // Indicates that scheduled BeginMainFrame is started.
    216   void NotifyBeginMainFrameStarted();
    217 
    218   // Indicates that the pending tree is ready for activation.
    219   void NotifyReadyToActivate();
    220 
    221   bool has_pending_tree() const { return has_pending_tree_; }
    222   bool active_tree_needs_first_draw() const {
    223     return active_tree_needs_first_draw_;
    224   }
    225 
    226   void DidManageTiles();
    227   void DidLoseOutputSurface();
    228   void DidCreateAndInitializeOutputSurface();
    229   bool HasInitializedOutputSurface() const;
    230 
    231   // True if we need to abort draws to make forward progress.
    232   bool PendingDrawsShouldBeAborted() const;
    233 
    234   bool SupportsProactiveBeginFrame() const;
    235 
    236   void SetContinuousPainting(bool continuous_painting) {
    237     continuous_painting_ = continuous_painting;
    238   }
    239 
    240   bool CouldSendBeginMainFrame() const;
    241 
    242   // TODO(zmo): This is temporary for debugging crbug.com/393331.
    243   // We should remove it afterwards.
    244   std::string GetStatesForDebugging() const;
    245 
    246  protected:
    247   bool BeginFrameNeededToAnimateOrDraw() const;
    248   bool ProactiveBeginFrameWanted() const;
    249 
    250   // True if we need to force activations to make forward progress.
    251   bool PendingActivationsShouldBeForced() const;
    252 
    253   bool ShouldAnimate() const;
    254   bool ShouldBeginOutputSurfaceCreation() const;
    255   bool ShouldDrawForced() const;
    256   bool ShouldDraw() const;
    257   bool ShouldActivatePendingTree() const;
    258   bool ShouldUpdateVisibleTiles() const;
    259   bool ShouldSendBeginMainFrame() const;
    260   bool ShouldCommit() const;
    261   bool ShouldManageTiles() const;
    262 
    263   void AdvanceCurrentFrameNumber();
    264   bool HasSentBeginMainFrameThisFrame() const;
    265   bool HasUpdatedVisibleTilesThisFrame() const;
    266   bool HasRequestedSwapThisFrame() const;
    267   bool HasSwappedThisFrame() const;
    268 
    269   void UpdateStateOnCommit(bool commit_was_aborted);
    270   void UpdateStateOnActivation();
    271   void UpdateStateOnDraw(bool did_request_swap);
    272   void UpdateStateOnManageTiles();
    273 
    274   const SchedulerSettings settings_;
    275 
    276   OutputSurfaceState output_surface_state_;
    277   BeginImplFrameState begin_impl_frame_state_;
    278   CommitState commit_state_;
    279   ForcedRedrawOnTimeoutState forced_redraw_state_;
    280 
    281   BeginFrameArgs begin_impl_frame_args_;
    282 
    283   int commit_count_;
    284   int current_frame_number_;
    285   int last_frame_number_animate_performed_;
    286   int last_frame_number_swap_performed_;
    287   int last_frame_number_swap_requested_;
    288   int last_frame_number_begin_main_frame_sent_;
    289   int last_frame_number_update_visible_tiles_was_called_;
    290 
    291   // manage_tiles_funnel_ is "filled" each time ManageTiles is called
    292   // and "drained" on each BeginImplFrame. If the funnel gets too full,
    293   // we start throttling ACTION_MANAGE_TILES such that we average one
    294   // ManageTile per BeginImplFrame.
    295   int manage_tiles_funnel_;
    296   int consecutive_checkerboard_animations_;
    297   int max_pending_swaps_;
    298   int pending_swaps_;
    299   bool needs_redraw_;
    300   bool needs_animate_;
    301   bool needs_manage_tiles_;
    302   bool swap_used_incomplete_tile_;
    303   bool needs_commit_;
    304   bool inside_poll_for_anticipated_draw_triggers_;
    305   bool visible_;
    306   bool can_start_;
    307   bool can_draw_;
    308   bool has_pending_tree_;
    309   bool pending_tree_is_ready_for_activation_;
    310   bool active_tree_needs_first_draw_;
    311   bool did_create_and_initialize_first_output_surface_;
    312   bool impl_latency_takes_priority_;
    313   bool skip_next_begin_main_frame_to_reduce_latency_;
    314   bool skip_begin_main_frame_to_reduce_latency_;
    315   bool continuous_painting_;
    316 
    317  private:
    318   DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine);
    319 };
    320 
    321 }  // namespace cc
    322 
    323 #endif  // CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_
    324