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