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: BeginFrameState will always cycle through all the states in order.
49 // Whether or not it actually waits or draws, it will at least try to wait in
50 // BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME and try to draw in
51 // BEGIN_FRAME_STATE_INSIDE_DEADLINE
52 enum BeginFrameState
{
53 BEGIN_FRAME_STATE_IDLE
,
54 BEGIN_FRAME_STATE_BEGIN_FRAME_STARTING
,
55 BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME
,
56 BEGIN_FRAME_STATE_INSIDE_DEADLINE
,
58 static const char* BeginFrameStateToString(BeginFrameState 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_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_FRAME_TO_MAIN_THREAD
,
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 main thread needs a begin frame callback in order to
129 bool BeginFrameNeededByImplThread() const;
131 // Idicates that we need to independently poll for new state and actions
132 // because we can't expect a BeginFrame. 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 BeginFrame callback.
138 // The scheduler will not draw more than once in a given BeginFrame
139 // callback nor send more than one BeginFrame message.
140 void OnBeginFrame(const BeginFrameArgs
& args
);
141 void OnBeginFrameDeadlinePending();
142 void OnBeginFrameDeadline();
143 void OnBeginFrameIdle();
144 bool ShouldTriggerBeginFrameDeadlineEarly() const;
145 BeginFrameState
begin_frame_state() const {
146 return begin_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 ACTION_DRAW_AND_SWAP_IF_POSSIBLE drew to the screen.
175 void DidDrawIfPossibleCompleted(bool success
);
177 // Indicates that a new commit flow needs to be performed, either to pull
178 // updates from the main thread to the impl, or to push deltas from the impl
180 void SetNeedsCommit();
182 // As SetNeedsCommit(), but ensures the begin frame will be sent to the main
183 // thread even if we are not visible. After this call we expect to go through
184 // the forced commit flow and then return to waiting for a non-forced
185 // begin frame to finish.
186 void SetNeedsForcedCommitForReadback();
188 // Call this only in response to receiving an
189 // ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD from NextAction.
190 // Indicates that all painting is complete.
193 // Call this only in response to receiving an
194 // ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD from NextAction if the client
195 // rejects the begin frame message. If did_handle is false, then
196 // another commit will be retried soon.
197 void BeginFrameAbortedByMainThread(bool did_handle
);
199 // Request exclusive access to the textures that back single buffered
200 // layers on behalf of the main thread. Upon acquisition,
201 // ACTION_DRAW_AND_SWAP_IF_POSSIBLE will not draw until the main thread
203 // textures to the impl thread by committing the layers.
204 void SetMainThreadNeedsLayerTextures();
206 // Set that we can create the first OutputSurface and start the scheduler.
207 void SetCanStart() { can_start_
= true; }
209 // Indicates whether drawing would, at this time, make sense.
210 // CanDraw can be used to supress flashes or checkerboarding
211 // when such behavior would be undesirable.
212 void SetCanDraw(bool can
);
214 // Indicates that the pending tree is ready for activation.
215 void NotifyReadyToActivate();
217 bool has_pending_tree() const { return has_pending_tree_
; }
219 void DidLoseOutputSurface();
220 void DidCreateAndInitializeOutputSurface();
221 bool HasInitializedOutputSurface() const;
223 // True if we need to abort draws to make forward progress.
224 bool PendingDrawsShouldBeAborted() const;
226 bool SupportsProactiveBeginFrame() const;
229 bool BeginFrameNeededToDrawByImplThread() const;
230 bool ProactiveBeginFrameWantedByImplThread() const;
232 // True if we need to force activations to make forward progress.
233 bool PendingActivationsShouldBeForced() const;
235 bool ShouldBeginOutputSurfaceCreation() const;
236 bool ShouldDrawForced() const;
237 bool ShouldDraw() const;
238 bool ShouldActivatePendingTree() const;
239 bool ShouldAcquireLayerTexturesForMainThread() const;
240 bool ShouldUpdateVisibleTiles() const;
241 bool ShouldSendBeginFrameToMainThread() const;
242 bool ShouldCommit() const;
243 bool ShouldManageTiles() const;
245 bool HasSentBeginFrameToMainThreadThisFrame() const;
246 bool HasScheduledManageTilesThisFrame() const;
247 bool HasUpdatedVisibleTilesThisFrame() const;
248 bool HasSwappedThisFrame() const;
250 void UpdateStateOnCommit(bool commit_was_aborted
);
251 void UpdateStateOnActivation();
252 void UpdateStateOnDraw(bool did_swap
);
253 void UpdateStateOnManageTiles();
255 const SchedulerSettings settings_
;
257 OutputSurfaceState output_surface_state_
;
258 BeginFrameState begin_frame_state_
;
259 CommitState commit_state_
;
260 TextureState texture_state_
;
261 ForcedRedrawOnTimeoutState forced_redraw_state_
;
262 SynchronousReadbackState readback_state_
;
264 BeginFrameArgs last_begin_frame_args_
;
267 int current_frame_number_
;
268 int last_frame_number_swap_performed_
;
269 int last_frame_number_begin_frame_sent_to_main_thread_
;
270 int last_frame_number_update_visible_tiles_was_called_
;
272 int consecutive_failed_draws_
;
274 bool needs_manage_tiles_
;
275 bool swap_used_incomplete_tile_
;
277 bool main_thread_needs_layer_textures_
;
278 bool inside_poll_for_anticipated_draw_triggers_
;
282 bool has_pending_tree_
;
283 bool pending_tree_is_ready_for_activation_
;
284 bool active_tree_needs_first_draw_
;
285 bool draw_if_possible_failed_
;
286 bool did_create_and_initialize_first_output_surface_
;
289 DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine
);
294 #endif // CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_