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