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.
5 #ifndef CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_
6 #define CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_
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"
23 // The SchedulerStateMachine decides how to coordinate main thread activites
24 // like painting/running javascript with rendering and input activities on the
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.
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 {
36 // settings must be valid for the lifetime of this class.
37 explicit SchedulerStateMachine(const SchedulerSettings& settings);
39 enum OutputSurfaceState {
40 OUTPUT_SURFACE_ACTIVE,
42 OUTPUT_SURFACE_CREATING,
43 OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT,
44 OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION,
46 static const char* OutputSurfaceStateToString(OutputSurfaceState state);
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,
58 static const char* BeginImplFrameStateToString(BeginImplFrameState state);
62 COMMIT_STATE_FRAME_IN_PROGRESS,
63 COMMIT_STATE_READY_TO_COMMIT,
64 COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
66 static const char* CommitStateToString(CommitState state);
69 LAYER_TEXTURE_STATE_UNLOCKED,
70 LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD,
71 LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD,
73 static const char* TextureStateToString(TextureState state);
75 enum SynchronousReadbackState {
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,
84 static const char* SynchronousReadbackStateToString(
85 SynchronousReadbackState state);
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,
93 static const char* ForcedRedrawOnTimeoutStateToString(
94 ForcedRedrawOnTimeoutState state);
96 bool CommitPending() const {
97 return commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS ||
98 commit_state_ == COMMIT_STATE_READY_TO_COMMIT;
101 bool RedrawPending() const { return needs_redraw_; }
102 bool ManageTilesPending() const { return needs_manage_tiles_; }
106 ACTION_SEND_BEGIN_MAIN_FRAME,
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,
118 static const char* ActionToString(Action action);
120 scoped_ptr<base::Value> AsValue() const;
122 Action NextAction() const;
123 void UpdateState(Action action);
125 void CheckInvariants();
127 // Indicates whether the impl thread needs a BeginImplFrame callback in order
129 bool BeginImplFrameNeeded() const;
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;
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_;
149 // PollForAnticipatedDrawTriggers is used by the synchronous compositor to
150 // avoid requesting BeginImplFrames when we won't actually draw but still
151 // need to advance our state at vsync intervals.
152 void DidEnterPollForAnticipatedDrawTriggers();
153 void DidLeavePollForAnticipatedDrawTriggers();
154 bool inside_poll_for_anticipated_draw_triggers() const {
155 return inside_poll_for_anticipated_draw_triggers_;
158 // Indicates whether the LayerTreeHostImpl is visible.
159 void SetVisible(bool visible);
161 // Indicates that a redraw is required, either due to the impl tree changing
162 // or the screen being damaged and simply needing redisplay.
163 void SetNeedsRedraw();
164 bool needs_redraw() const { return needs_redraw_; }
166 // Indicates that manage-tiles is required. This guarantees another
167 // ManageTiles will occur shortly (even if no redraw is required).
168 void SetNeedsManageTiles();
170 // Indicates whether a redraw is required because we are currently rendering
171 // with a low resolution or checkerboarded tile.
172 void SetSwapUsedIncompleteTile(bool used_incomplete_tile);
174 // Indicates whether to prioritize animation smoothness over new content
176 void SetSmoothnessTakesPriority(bool smoothness_takes_priority);
178 // Indicates whether ACTION_DRAW_AND_SWAP_IF_POSSIBLE drew to the screen.
179 void DidDrawIfPossibleCompleted(bool success);
181 // Indicates that a new commit flow needs to be performed, either to pull
182 // updates from the main thread to the impl, or to push deltas from the impl
184 void SetNeedsCommit();
186 // As SetNeedsCommit(), but ensures the BeginMainFrame will be sent even
187 // if we are not visible. After this call we expect to go through
188 // the forced commit flow and then return to waiting for a non-forced
189 // BeginMainFrame to finish.
190 void SetNeedsForcedCommitForReadback();
192 // Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME
194 // Indicates that all painting is complete.
197 // Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME
198 // from NextAction if the client rejects the BeginMainFrame message.
199 // If did_handle is false, then another commit will be retried soon.
200 void BeginMainFrameAborted(bool did_handle);
202 // Request exclusive access to the textures that back single buffered
203 // layers on behalf of the main thread. Upon acquisition,
204 // ACTION_DRAW_AND_SWAP_IF_POSSIBLE will not draw until the main thread
206 // textures to the impl thread by committing the layers.
207 void SetMainThreadNeedsLayerTextures();
209 // Set that we can create the first OutputSurface and start the scheduler.
210 void SetCanStart() { can_start_ = true; }
212 // Indicates whether drawing would, at this time, make sense.
213 // CanDraw can be used to suppress flashes or checkerboarding
214 // when such behavior would be undesirable.
215 void SetCanDraw(bool can);
217 // Indicates that the pending tree is ready for activation.
218 void NotifyReadyToActivate();
220 bool has_pending_tree() const { return has_pending_tree_; }
222 void DidLoseOutputSurface();
223 void DidCreateAndInitializeOutputSurface();
224 bool HasInitializedOutputSurface() const;
226 // True if we need to abort draws to make forward progress.
227 bool PendingDrawsShouldBeAborted() const;
229 bool SupportsProactiveBeginImplFrame() const;
232 bool BeginImplFrameNeededToDraw() const;
233 bool ProactiveBeginImplFrameWanted() const;
235 // True if we need to force activations to make forward progress.
236 bool PendingActivationsShouldBeForced() const;
238 bool ShouldBeginOutputSurfaceCreation() const;
239 bool ShouldDrawForced() const;
240 bool ShouldDraw() const;
241 bool ShouldActivatePendingTree() const;
242 bool ShouldAcquireLayerTexturesForMainThread() const;
243 bool ShouldUpdateVisibleTiles() const;
244 bool ShouldSendBeginMainFrame() const;
245 bool ShouldCommit() const;
246 bool ShouldManageTiles() const;
248 bool HasSentBeginMainFrameThisFrame() const;
249 bool HasScheduledManageTilesThisFrame() const;
250 bool HasUpdatedVisibleTilesThisFrame() const;
251 bool HasSwappedThisFrame() const;
253 void UpdateStateOnCommit(bool commit_was_aborted);
254 void UpdateStateOnActivation();
255 void UpdateStateOnDraw(bool did_swap);
256 void UpdateStateOnManageTiles();
258 const SchedulerSettings settings_;
260 OutputSurfaceState output_surface_state_;
261 BeginImplFrameState begin_impl_frame_state_;
262 CommitState commit_state_;
263 TextureState texture_state_;
264 ForcedRedrawOnTimeoutState forced_redraw_state_;
265 SynchronousReadbackState readback_state_;
267 BeginFrameArgs last_begin_impl_frame_args_;
270 int current_frame_number_;
271 int last_frame_number_swap_performed_;
272 int last_frame_number_begin_main_frame_sent_;
273 int last_frame_number_update_visible_tiles_was_called_;
275 int consecutive_failed_draws_;
277 bool needs_manage_tiles_;
278 bool swap_used_incomplete_tile_;
280 bool main_thread_needs_layer_textures_;
281 bool inside_poll_for_anticipated_draw_triggers_;
285 bool has_pending_tree_;
286 bool pending_tree_is_ready_for_activation_;
287 bool active_tree_needs_first_draw_;
288 bool draw_if_possible_failed_;
289 bool did_create_and_initialize_first_output_surface_;
290 bool smoothness_takes_priority_;
293 DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine);
298 #endif // CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_