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/scheduler_settings.h"
     16 
     17 namespace base {
     18 class Value;
     19 }
     20 
     21 namespace cc {
     22 
     23 // The SchedulerStateMachine decides how to coordinate main thread activites
     24 // like painting/running javascript with rendering and input activities on the
     25 // impl thread.
     26 //
     27 // The state machine tracks internal state but is also influenced by external
     28 // state.  Internal state includes things like whether a frame has been
     29 // requested, while external state includes things like the current time being
     30 // near to the vblank time.
     31 //
     32 // The scheduler seperates "what to do next" from the updating of its internal
     33 // state to make testing cleaner.
     34 class CC_EXPORT SchedulerStateMachine {
     35  public:
     36   // settings must be valid for the lifetime of this class.
     37   explicit SchedulerStateMachine(const SchedulerSettings& settings);
     38 
     39   enum OutputSurfaceState {
     40     OUTPUT_SURFACE_ACTIVE,
     41     OUTPUT_SURFACE_LOST,
     42     OUTPUT_SURFACE_CREATING,
     43     OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT,
     44     OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION,
     45   };
     46   static const char* OutputSurfaceStateToString(OutputSurfaceState state);
     47 
     48   // Note: BeginImplFrameState will always cycle through all the states in
     49   // order. Whether or not it actually waits or draws, it will at least try to
     50   // wait in BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME and try to draw in
     51   // BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
     52   enum BeginImplFrameState {
     53     BEGIN_IMPL_FRAME_STATE_IDLE,
     54     BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
     55     BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
     56     BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE,
     57   };
     58   static const char* BeginImplFrameStateToString(BeginImplFrameState state);
     59 
     60   enum CommitState {
     61     COMMIT_STATE_IDLE,
     62     COMMIT_STATE_FRAME_IN_PROGRESS,
     63     COMMIT_STATE_READY_TO_COMMIT,
     64     COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
     65   };
     66   static const char* CommitStateToString(CommitState state);
     67 
     68   enum TextureState {
     69     LAYER_TEXTURE_STATE_UNLOCKED,
     70     LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD,
     71     LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD,
     72   };
     73   static const char* TextureStateToString(TextureState state);
     74 
     75   enum SynchronousReadbackState {
     76     READBACK_STATE_IDLE,
     77     READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME,
     78     READBACK_STATE_WAITING_FOR_COMMIT,
     79     READBACK_STATE_WAITING_FOR_ACTIVATION,
     80     READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK,
     81     READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT,
     82     READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION,
     83   };
     84   static const char* SynchronousReadbackStateToString(
     85       SynchronousReadbackState state);
     86 
     87   enum ForcedRedrawOnTimeoutState {
     88     FORCED_REDRAW_STATE_IDLE,
     89     FORCED_REDRAW_STATE_WAITING_FOR_COMMIT,
     90     FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION,
     91     FORCED_REDRAW_STATE_WAITING_FOR_DRAW,
     92   };
     93   static const char* ForcedRedrawOnTimeoutStateToString(
     94       ForcedRedrawOnTimeoutState state);
     95 
     96   bool CommitPending() const {
     97     return commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS ||
     98            commit_state_ == COMMIT_STATE_READY_TO_COMMIT;
     99   }
    100 
    101   bool RedrawPending() const { return needs_redraw_; }
    102   bool ManageTilesPending() const { return needs_manage_tiles_; }
    103 
    104   enum Action {
    105     ACTION_NONE,
    106     ACTION_SEND_BEGIN_MAIN_FRAME,
    107     ACTION_COMMIT,
    108     ACTION_UPDATE_VISIBLE_TILES,
    109     ACTION_ACTIVATE_PENDING_TREE,
    110     ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
    111     ACTION_DRAW_AND_SWAP_FORCED,
    112     ACTION_DRAW_AND_SWAP_ABORT,
    113     ACTION_DRAW_AND_READBACK,
    114     ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
    115     ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD,
    116     ACTION_MANAGE_TILES,
    117   };
    118   static const char* ActionToString(Action action);
    119 
    120   scoped_ptr<base::Value> AsValue() const;
    121 
    122   Action NextAction() const;
    123   void UpdateState(Action action);
    124 
    125   void CheckInvariants();
    126 
    127   // Indicates whether the impl thread needs a BeginImplFrame callback in order
    128   // to make progress.
    129   bool BeginImplFrameNeeded() const;
    130 
    131   // Indicates that we need to independently poll for new state and actions
    132   // because we can't expect a BeginImplFrame. This is mostly used to avoid
    133   // drawing repeat frames with the synchronous compositor without dropping
    134   // necessary actions on the floor.
    135   bool ShouldPollForAnticipatedDrawTriggers() const;
    136 
    137   // Indicates that the system has entered and left a BeginImplFrame callback.
    138   // The scheduler will not draw more than once in a given BeginImplFrame
    139   // callback nor send more than one BeginMainFrame message.
    140   void OnBeginImplFrame(const BeginFrameArgs& args);
    141   void OnBeginImplFrameDeadlinePending();
    142   void OnBeginImplFrameDeadline();
    143   void OnBeginImplFrameIdle();
    144   bool ShouldTriggerBeginImplFrameDeadlineEarly() const;
    145   BeginImplFrameState begin_impl_frame_state() const {
    146     return begin_impl_frame_state_;
    147   }
    148 
    149   // If the main thread didn't manage to produce a new frame in time for the
    150   // impl thread to draw, it is in a high latency mode.
    151   bool MainThreadIsInHighLatencyMode() const;
    152 
    153   // PollForAnticipatedDrawTriggers is used by the synchronous compositor to
    154   // avoid requesting BeginImplFrames when we won't actually draw but still
    155   // need to advance our state at vsync intervals.
    156   void DidEnterPollForAnticipatedDrawTriggers();
    157   void DidLeavePollForAnticipatedDrawTriggers();
    158   bool inside_poll_for_anticipated_draw_triggers() const {
    159     return inside_poll_for_anticipated_draw_triggers_;
    160   }
    161 
    162   // Indicates whether the LayerTreeHostImpl is visible.
    163   void SetVisible(bool visible);
    164 
    165   // Indicates that a redraw is required, either due to the impl tree changing
    166   // or the screen being damaged and simply needing redisplay.
    167   void SetNeedsRedraw();
    168   bool needs_redraw() const { return needs_redraw_; }
    169 
    170   // Indicates that manage-tiles is required. This guarantees another
    171   // ManageTiles will occur shortly (even if no redraw is required).
    172   void SetNeedsManageTiles();
    173 
    174   // Indicates whether a redraw is required because we are currently rendering
    175   // with a low resolution or checkerboarded tile.
    176   void SetSwapUsedIncompleteTile(bool used_incomplete_tile);
    177 
    178   // Indicates whether to prioritize animation smoothness over new content
    179   // activation.
    180   void SetSmoothnessTakesPriority(bool smoothness_takes_priority);
    181 
    182   // Indicates whether ACTION_DRAW_AND_SWAP_IF_POSSIBLE drew to the screen.
    183   void DidDrawIfPossibleCompleted(bool success);
    184 
    185   // Indicates that a new commit flow needs to be performed, either to pull
    186   // updates from the main thread to the impl, or to push deltas from the impl
    187   // thread to main.
    188   void SetNeedsCommit();
    189 
    190   // As SetNeedsCommit(), but ensures the BeginMainFrame will be sent even
    191   // if we are not visible.  After this call we expect to go through
    192   // the forced commit flow and then return to waiting for a non-forced
    193   // BeginMainFrame to finish.
    194   void SetNeedsForcedCommitForReadback();
    195 
    196   // Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME
    197   // from NextAction.
    198   // Indicates that all painting is complete.
    199   void FinishCommit();
    200 
    201   // Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME
    202   // from NextAction if the client rejects the BeginMainFrame message.
    203   // If did_handle is false, then another commit will be retried soon.
    204   void BeginMainFrameAborted(bool did_handle);
    205 
    206   // Request exclusive access to the textures that back single buffered
    207   // layers on behalf of the main thread. Upon acquisition,
    208   // ACTION_DRAW_AND_SWAP_IF_POSSIBLE will not draw until the main thread
    209   // releases the
    210   // textures to the impl thread by committing the layers.
    211   void SetMainThreadNeedsLayerTextures();
    212 
    213   // Set that we can create the first OutputSurface and start the scheduler.
    214   void SetCanStart() { can_start_ = true; }
    215 
    216   void SetSkipBeginMainFrameToReduceLatency(bool skip);
    217 
    218   // Indicates whether drawing would, at this time, make sense.
    219   // CanDraw can be used to suppress flashes or checkerboarding
    220   // when such behavior would be undesirable.
    221   void SetCanDraw(bool can);
    222 
    223   // Indicates that the pending tree is ready for activation.
    224   void NotifyReadyToActivate();
    225 
    226   bool has_pending_tree() const { return has_pending_tree_; }
    227 
    228   void DidManageTiles();
    229   void DidLoseOutputSurface();
    230   void DidCreateAndInitializeOutputSurface();
    231   bool HasInitializedOutputSurface() const;
    232 
    233   // True if we need to abort draws to make forward progress.
    234   bool PendingDrawsShouldBeAborted() const;
    235 
    236   bool SupportsProactiveBeginImplFrame() const;
    237 
    238   bool IsCommitStateWaiting() const;
    239 
    240  protected:
    241   bool BeginImplFrameNeededToDraw() const;
    242   bool ProactiveBeginImplFrameWanted() const;
    243 
    244   // True if we need to force activations to make forward progress.
    245   bool PendingActivationsShouldBeForced() const;
    246 
    247   bool ShouldBeginOutputSurfaceCreation() const;
    248   bool ShouldDrawForced() const;
    249   bool ShouldDraw() const;
    250   bool ShouldActivatePendingTree() const;
    251   bool ShouldAcquireLayerTexturesForMainThread() const;
    252   bool ShouldUpdateVisibleTiles() const;
    253   bool ShouldSendBeginMainFrame() const;
    254   bool ShouldCommit() const;
    255   bool ShouldManageTiles() const;
    256 
    257   bool HasSentBeginMainFrameThisFrame() const;
    258   bool HasScheduledManageTilesThisFrame() const;
    259   bool HasUpdatedVisibleTilesThisFrame() const;
    260   bool HasSwappedThisFrame() const;
    261 
    262   void UpdateStateOnCommit(bool commit_was_aborted);
    263   void UpdateStateOnActivation();
    264   void UpdateStateOnDraw(bool did_swap);
    265   void UpdateStateOnManageTiles();
    266 
    267   const SchedulerSettings settings_;
    268 
    269   OutputSurfaceState output_surface_state_;
    270   BeginImplFrameState begin_impl_frame_state_;
    271   CommitState commit_state_;
    272   TextureState texture_state_;
    273   ForcedRedrawOnTimeoutState forced_redraw_state_;
    274   SynchronousReadbackState readback_state_;
    275 
    276   BeginFrameArgs last_begin_impl_frame_args_;
    277 
    278   int commit_count_;
    279   int current_frame_number_;
    280   int last_frame_number_swap_performed_;
    281   int last_frame_number_begin_main_frame_sent_;
    282   int last_frame_number_update_visible_tiles_was_called_;
    283   int last_frame_number_manage_tiles_called_;
    284 
    285   int consecutive_failed_draws_;
    286   bool needs_redraw_;
    287   bool needs_manage_tiles_;
    288   bool swap_used_incomplete_tile_;
    289   bool needs_commit_;
    290   bool main_thread_needs_layer_textures_;
    291   bool inside_poll_for_anticipated_draw_triggers_;
    292   bool visible_;
    293   bool can_start_;
    294   bool can_draw_;
    295   bool has_pending_tree_;
    296   bool pending_tree_is_ready_for_activation_;
    297   bool active_tree_needs_first_draw_;
    298   bool draw_if_possible_failed_;
    299   bool did_create_and_initialize_first_output_surface_;
    300   bool smoothness_takes_priority_;
    301   bool skip_begin_main_frame_to_reduce_latency_;
    302 
    303  private:
    304   DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine);
    305 };
    306 
    307 }  // namespace cc
    308 
    309 #endif  // CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_
    310