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