scheduler_state_machine.h revision 010d83a9304c5a91596085d917d248abff47903a
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_swap_readback_result.h" 16#include "cc/scheduler/scheduler_settings.h" 17 18namespace base { 19class Value; 20} 21 22namespace 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. 35class 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 SynchronousReadbackState { 72 READBACK_STATE_IDLE, 73 READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME, 74 READBACK_STATE_WAITING_FOR_COMMIT, 75 READBACK_STATE_WAITING_FOR_ACTIVATION, 76 READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK, 77 READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT, 78 READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION, 79 }; 80 static const char* SynchronousReadbackStateToString( 81 SynchronousReadbackState state); 82 83 enum ForcedRedrawOnTimeoutState { 84 FORCED_REDRAW_STATE_IDLE, 85 FORCED_REDRAW_STATE_WAITING_FOR_COMMIT, 86 FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION, 87 FORCED_REDRAW_STATE_WAITING_FOR_DRAW, 88 }; 89 static const char* ForcedRedrawOnTimeoutStateToString( 90 ForcedRedrawOnTimeoutState state); 91 92 bool CommitPending() const { 93 return commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || 94 commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED || 95 commit_state_ == COMMIT_STATE_READY_TO_COMMIT; 96 } 97 CommitState commit_state() const { return commit_state_; } 98 99 bool RedrawPending() const { return needs_redraw_; } 100 bool ManageTilesPending() const { return needs_manage_tiles_; } 101 102 enum Action { 103 ACTION_NONE, 104 ACTION_ANIMATE, 105 ACTION_SEND_BEGIN_MAIN_FRAME, 106 ACTION_COMMIT, 107 ACTION_UPDATE_VISIBLE_TILES, 108 ACTION_ACTIVATE_PENDING_TREE, 109 ACTION_DRAW_AND_SWAP_IF_POSSIBLE, 110 ACTION_DRAW_AND_SWAP_FORCED, 111 ACTION_DRAW_AND_SWAP_ABORT, 112 ACTION_DRAW_AND_READBACK, 113 ACTION_BEGIN_OUTPUT_SURFACE_CREATION, 114 ACTION_MANAGE_TILES, 115 }; 116 static const char* ActionToString(Action action); 117 118 scoped_ptr<base::Value> AsValue() const; 119 120 Action NextAction() const; 121 void UpdateState(Action action); 122 123 void CheckInvariants(); 124 125 // Indicates whether the impl thread needs a BeginImplFrame callback in order 126 // to make progress. 127 bool BeginFrameNeeded() const; 128 129 // Indicates that we need to independently poll for new state and actions 130 // because we can't expect a BeginImplFrame. This is mostly used to avoid 131 // drawing repeat frames with the synchronous compositor without dropping 132 // necessary actions on the floor. 133 bool ShouldPollForAnticipatedDrawTriggers() const; 134 135 // Indicates that the system has entered and left a BeginImplFrame callback. 136 // The scheduler will not draw more than once in a given BeginImplFrame 137 // callback nor send more than one BeginMainFrame message. 138 void OnBeginImplFrame(const BeginFrameArgs& args); 139 void OnBeginImplFrameDeadlinePending(); 140 void OnBeginImplFrameDeadline(); 141 void OnBeginImplFrameIdle(); 142 bool ShouldTriggerBeginImplFrameDeadlineEarly() const; 143 BeginImplFrameState begin_impl_frame_state() const { 144 return begin_impl_frame_state_; 145 } 146 147 // If the main thread didn't manage to produce a new frame in time for the 148 // impl thread to draw, it is in a high latency mode. 149 bool MainThreadIsInHighLatencyMode() const; 150 151 // PollForAnticipatedDrawTriggers is used by the synchronous compositor to 152 // avoid requesting BeginImplFrames when we won't actually draw but still 153 // need to advance our state at vsync intervals. 154 void DidEnterPollForAnticipatedDrawTriggers(); 155 void DidLeavePollForAnticipatedDrawTriggers(); 156 bool inside_poll_for_anticipated_draw_triggers() const { 157 return inside_poll_for_anticipated_draw_triggers_; 158 } 159 160 // Indicates whether the LayerTreeHostImpl is visible. 161 void SetVisible(bool visible); 162 163 // Indicates that a redraw is required, either due to the impl tree changing 164 // or the screen being damaged and simply needing redisplay. 165 void SetNeedsRedraw(); 166 bool needs_redraw() const { return needs_redraw_; } 167 168 void SetNeedsAnimate(); 169 bool needs_animate() const { return needs_animate_; } 170 171 // Indicates that manage-tiles is required. This guarantees another 172 // ManageTiles will occur shortly (even if no redraw is required). 173 void SetNeedsManageTiles(); 174 175 // Sets how many swaps can be pending to the OutputSurface. 176 void SetMaxSwapsPending(int max); 177 178 // If the scheduler attempted to draw and swap, this provides feedback 179 // regarding whether or not the swap actually occured. We might skip the 180 // swap when there is not damage, for example. 181 void DidSwapBuffers(); 182 183 // Indicates whether a redraw is required because we are currently rendering 184 // with a low resolution or checkerboarded tile. 185 void SetSwapUsedIncompleteTile(bool used_incomplete_tile); 186 187 // Notification from the OutputSurface that a swap has been consumed. 188 void DidSwapBuffersComplete(); 189 190 // Indicates whether to prioritize animation smoothness over new content 191 // activation. 192 void SetSmoothnessTakesPriority(bool smoothness_takes_priority); 193 bool smoothness_takes_priority() const { return smoothness_takes_priority_; } 194 195 // Indicates whether ACTION_DRAW_AND_SWAP_IF_POSSIBLE drew to the screen. 196 void DidDrawIfPossibleCompleted(DrawSwapReadbackResult::DrawResult result); 197 198 // Indicates that a new commit flow needs to be performed, either to pull 199 // updates from the main thread to the impl, or to push deltas from the impl 200 // thread to main. 201 void SetNeedsCommit(); 202 203 // As SetNeedsCommit(), but ensures the BeginMainFrame will be sent even 204 // if we are not visible. After this call we expect to go through 205 // the forced commit flow and then return to waiting for a non-forced 206 // BeginMainFrame to finish. 207 void SetNeedsForcedCommitForReadback(); 208 209 // Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME 210 // from NextAction. 211 // Indicates that all painting is complete. 212 void NotifyReadyToCommit(); 213 214 // Call this only in response to receiving an ACTION_SEND_BEGIN_MAIN_FRAME 215 // from NextAction if the client rejects the BeginMainFrame message. 216 // If did_handle is false, then another commit will be retried soon. 217 void BeginMainFrameAborted(bool did_handle); 218 219 // Set that we can create the first OutputSurface and start the scheduler. 220 void SetCanStart() { can_start_ = true; } 221 222 void SetSkipNextBeginMainFrameToReduceLatency(); 223 224 // Indicates whether drawing would, at this time, make sense. 225 // CanDraw can be used to suppress flashes or checkerboarding 226 // when such behavior would be undesirable. 227 void SetCanDraw(bool can); 228 229 // Indicates that scheduled BeginMainFrame is started. 230 void NotifyBeginMainFrameStarted(); 231 232 // Indicates that the pending tree is ready for activation. 233 void NotifyReadyToActivate(); 234 235 bool has_pending_tree() const { return has_pending_tree_; } 236 bool active_tree_needs_first_draw() const { 237 return active_tree_needs_first_draw_; 238 } 239 240 void DidManageTiles(); 241 void DidLoseOutputSurface(); 242 void DidCreateAndInitializeOutputSurface(); 243 bool HasInitializedOutputSurface() const; 244 245 // True if we need to abort draws to make forward progress. 246 bool PendingDrawsShouldBeAborted() const; 247 248 bool SupportsProactiveBeginFrame() const; 249 250 void SetContinuousPainting(bool continuous_painting) { 251 continuous_painting_ = continuous_painting; 252 } 253 254 protected: 255 bool BeginFrameNeededToAnimateOrDraw() const; 256 bool ProactiveBeginFrameWanted() const; 257 258 // True if we need to force activations to make forward progress. 259 bool PendingActivationsShouldBeForced() const; 260 261 bool ShouldAnimate() const; 262 bool ShouldBeginOutputSurfaceCreation() const; 263 bool ShouldDrawForced() const; 264 bool ShouldDraw() const; 265 bool ShouldActivatePendingTree() const; 266 bool ShouldUpdateVisibleTiles() const; 267 bool ShouldSendBeginMainFrame() const; 268 bool ShouldCommit() const; 269 bool ShouldManageTiles() const; 270 271 void AdvanceCurrentFrameNumber(); 272 bool HasSentBeginMainFrameThisFrame() const; 273 bool HasUpdatedVisibleTilesThisFrame() const; 274 bool HasSwappedThisFrame() const; 275 276 void UpdateStateOnCommit(bool commit_was_aborted); 277 void UpdateStateOnActivation(); 278 void UpdateStateOnDraw(bool did_request_swap); 279 void UpdateStateOnManageTiles(); 280 281 const SchedulerSettings settings_; 282 283 OutputSurfaceState output_surface_state_; 284 BeginImplFrameState begin_impl_frame_state_; 285 CommitState commit_state_; 286 ForcedRedrawOnTimeoutState forced_redraw_state_; 287 SynchronousReadbackState readback_state_; 288 289 BeginFrameArgs begin_impl_frame_args_; 290 291 int commit_count_; 292 int current_frame_number_; 293 int last_frame_number_animate_performed_; 294 int last_frame_number_swap_performed_; 295 int last_frame_number_begin_main_frame_sent_; 296 int last_frame_number_update_visible_tiles_was_called_; 297 298 // manage_tiles_funnel_ is "filled" each time ManageTiles is called 299 // and "drained" on each BeginImplFrame. If the funnel gets too full, 300 // we start throttling ACTION_MANAGE_TILES such that we average one 301 // ManageTile per BeginImplFrame. 302 int manage_tiles_funnel_; 303 int consecutive_checkerboard_animations_; 304 int max_pending_swaps_; 305 int pending_swaps_; 306 bool needs_redraw_; 307 bool needs_animate_; 308 bool needs_manage_tiles_; 309 bool swap_used_incomplete_tile_; 310 bool needs_commit_; 311 bool inside_poll_for_anticipated_draw_triggers_; 312 bool visible_; 313 bool can_start_; 314 bool can_draw_; 315 bool has_pending_tree_; 316 bool pending_tree_is_ready_for_activation_; 317 bool active_tree_needs_first_draw_; 318 bool did_create_and_initialize_first_output_surface_; 319 bool smoothness_takes_priority_; 320 bool skip_next_begin_main_frame_to_reduce_latency_; 321 bool skip_begin_main_frame_to_reduce_latency_; 322 bool continuous_painting_; 323 bool needs_back_to_back_readback_; 324 325 private: 326 DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine); 327}; 328 329} // namespace cc 330 331#endif // CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_ 332