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