• 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 #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 
CommitPending()96   bool CommitPending() const {
97     return commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS ||
98            commit_state_ == COMMIT_STATE_READY_TO_COMMIT;
99   }
100 
RedrawPending()101   bool RedrawPending() const { return needs_redraw_; }
ManageTilesPending()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;
begin_impl_frame_state()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();
inside_poll_for_anticipated_draw_triggers()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();
needs_redraw()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.
SetCanStart()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 
has_pending_tree()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