scheduler_state_machine.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  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. #ifndef CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_
  5. #define CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_
  6. #include <stdint.h>
  7. #include "cc/cc_export.h"
  8. #include "cc/scheduler/commit_earlyout_reason.h"
  9. #include "cc/scheduler/draw_result.h"
  10. #include "cc/scheduler/scheduler_settings.h"
  11. #include "cc/tiles/tile_priority.h"
  12. #include "components/viz/common/frame_sinks/begin_frame_args.h"
  13. #include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.h"
  14. namespace cc {
  15. enum class ScrollHandlerState {
  16. SCROLL_AFFECTS_SCROLL_HANDLER,
  17. SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER,
  18. };
  19. // The SchedulerStateMachine decides how to coordinate main thread activites
  20. // like painting/running javascript with rendering and input activities on the
  21. // impl thread.
  22. //
  23. // The state machine tracks internal state but is also influenced by external
  24. // state. Internal state includes things like whether a frame has been
  25. // requested, while external state includes things like the current time being
  26. // near to the vblank time.
  27. //
  28. // The scheduler seperates "what to do next" from the updating of its internal
  29. // state to make testing cleaner.
  30. class CC_EXPORT SchedulerStateMachine {
  31. public:
  32. // settings must be valid for the lifetime of this class.
  33. explicit SchedulerStateMachine(const SchedulerSettings& settings);
  34. SchedulerStateMachine(const SchedulerStateMachine&) = delete;
  35. ~SchedulerStateMachine();
  36. SchedulerStateMachine& operator=(const SchedulerStateMachine&) = delete;
  37. enum class LayerTreeFrameSinkState {
  38. NONE,
  39. ACTIVE,
  40. CREATING,
  41. WAITING_FOR_FIRST_COMMIT,
  42. WAITING_FOR_FIRST_ACTIVATION,
  43. };
  44. static perfetto::protos::pbzero::ChromeCompositorStateMachine::MajorState::
  45. LayerTreeFrameSinkState
  46. LayerTreeFrameSinkStateToProtozeroEnum(LayerTreeFrameSinkState state);
  47. // Note: BeginImplFrameState does not cycle through these states in a fixed
  48. // order on all platforms. It's up to the scheduler to set these correctly.
  49. enum class BeginImplFrameState {
  50. IDLE,
  51. INSIDE_BEGIN_FRAME,
  52. INSIDE_DEADLINE,
  53. };
  54. static perfetto::protos::pbzero::ChromeCompositorStateMachine::MajorState::
  55. BeginImplFrameState
  56. BeginImplFrameStateToProtozeroEnum(BeginImplFrameState state);
  57. // These values are persisted to logs. Entries should not be renumbered and
  58. // numeric values should never be reused.
  59. // TODO(weiliangc): The histogram is used to understanding what type of
  60. // deadline mode do we encounter in real world and is set to expire after
  61. // 2022. The Enum can be changed after the histogram is removed.
  62. // The scheduler uses a deadline to wait for main thread updates before
  63. // submitting a compositor frame. BeginImplFrameDeadlineMode specifies when
  64. // the deadline should run.
  65. enum class BeginImplFrameDeadlineMode {
  66. NONE = 0, // No deadline should be scheduled e.g. for synchronous
  67. // compositor.
  68. IMMEDIATE = 1, // Deadline should be scheduled to run immediately.
  69. REGULAR = 2, // Deadline should be scheduled to run at the deadline
  70. // provided by in the BeginFrameArgs.
  71. LATE = 3, // Deadline should be scheduled run when the next frame is
  72. // expected to arrive.
  73. BLOCKED = 4, // Deadline should be blocked indefinitely until the next
  74. // frame arrives.
  75. kMaxValue = BLOCKED,
  76. };
  77. // TODO(nuskos): Update Scheduler::ScheduleBeginImplFrameDeadline event to
  78. // used typed macros so we can remove this ToString function.
  79. static const char* BeginImplFrameDeadlineModeToString(
  80. BeginImplFrameDeadlineMode mode);
  81. static perfetto::protos::pbzero::ChromeCompositorSchedulerState::
  82. BeginImplFrameDeadlineMode
  83. BeginImplFrameDeadlineModeToProtozeroEnum(
  84. BeginImplFrameDeadlineMode mode);
  85. enum class BeginMainFrameState {
  86. IDLE, // A new BeginMainFrame can start.
  87. SENT, // A BeginMainFrame has already been issued.
  88. READY_TO_COMMIT, // A previously issued BeginMainFrame has been processed,
  89. // and is ready to commit.
  90. };
  91. static perfetto::protos::pbzero::ChromeCompositorStateMachine::MajorState::
  92. BeginMainFrameState
  93. BeginMainFrameStateToProtozeroEnum(BeginMainFrameState state);
  94. // When a redraw is forced, it goes through a complete commit -> activation ->
  95. // draw cycle. Until a redraw has been forced, it remains in IDLE state.
  96. enum class ForcedRedrawOnTimeoutState {
  97. IDLE,
  98. WAITING_FOR_COMMIT,
  99. WAITING_FOR_ACTIVATION,
  100. WAITING_FOR_DRAW,
  101. };
  102. static perfetto::protos::pbzero::ChromeCompositorStateMachine::MajorState::
  103. ForcedRedrawOnTimeoutState
  104. ForcedRedrawOnTimeoutStateToProtozeroEnum(
  105. ForcedRedrawOnTimeoutState state);
  106. BeginMainFrameState begin_main_frame_state() const {
  107. return begin_main_frame_state_;
  108. }
  109. bool CommitPending() const {
  110. return begin_main_frame_state_ != BeginMainFrameState::IDLE;
  111. }
  112. bool NewActiveTreeLikely() const {
  113. return (needs_begin_main_frame_ && !last_commit_had_no_updates_) ||
  114. CommitPending() || has_pending_tree_;
  115. }
  116. bool RedrawPending() const { return needs_redraw_; }
  117. bool PrepareTilesPending() const { return needs_prepare_tiles_; }
  118. enum class Action {
  119. NONE,
  120. SEND_BEGIN_MAIN_FRAME,
  121. COMMIT,
  122. POST_COMMIT,
  123. ACTIVATE_SYNC_TREE,
  124. PERFORM_IMPL_SIDE_INVALIDATION,
  125. DRAW_IF_POSSIBLE,
  126. DRAW_FORCED,
  127. DRAW_ABORT,
  128. BEGIN_LAYER_TREE_FRAME_SINK_CREATION,
  129. PREPARE_TILES,
  130. INVALIDATE_LAYER_TREE_FRAME_SINK,
  131. NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_UNTIL,
  132. NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_SOON,
  133. };
  134. static perfetto::protos::pbzero::ChromeCompositorSchedulerAction
  135. ActionToProtozeroEnum(Action action);
  136. void AsProtozeroInto(
  137. perfetto::protos::pbzero::ChromeCompositorStateMachine* state) const;
  138. Action NextAction() const;
  139. void WillSendBeginMainFrame();
  140. void WillNotifyBeginMainFrameNotExpectedUntil();
  141. void WillNotifyBeginMainFrameNotExpectedSoon();
  142. void WillCommit(bool commit_had_no_updates);
  143. void DidCommit();
  144. void DidPostCommit();
  145. void WillActivate();
  146. void WillDraw();
  147. void WillBeginLayerTreeFrameSinkCreation();
  148. void WillPrepareTiles();
  149. void WillInvalidateLayerTreeFrameSink();
  150. void WillPerformImplSideInvalidation();
  151. void DidDraw(DrawResult draw_result);
  152. void AbortDraw();
  153. // Indicates whether the impl thread needs a BeginImplFrame callback in order
  154. // to make progress.
  155. bool BeginFrameNeeded() const;
  156. // Indicates that the system has entered and left a BeginImplFrame callback.
  157. // The scheduler will not draw more than once in a given BeginImplFrame
  158. // callback nor send more than one BeginMainFrame message.
  159. void OnBeginImplFrame(const viz::BeginFrameId& frame_id, bool animate_only);
  160. // Indicates that the scheduler has entered the draw phase. The scheduler
  161. // will not draw more than once in a single draw phase.
  162. // TODO(sunnyps): Rename OnBeginImplFrameDeadline to OnDraw or similar.
  163. void OnBeginImplFrameDeadline();
  164. void OnBeginImplFrameIdle();
  165. int current_frame_number() const { return current_frame_number_; }
  166. BeginImplFrameState begin_impl_frame_state() const {
  167. return begin_impl_frame_state_;
  168. }
  169. // Returns BeginImplFrameDeadlineMode computed based on current state.
  170. BeginImplFrameDeadlineMode CurrentBeginImplFrameDeadlineMode() const;
  171. // If the main thread didn't manage to produce a new frame in time for the
  172. // impl thread to draw, it is in a high latency mode.
  173. bool main_thread_missed_last_deadline() const {
  174. return main_thread_missed_last_deadline_;
  175. }
  176. bool IsDrawThrottled() const;
  177. // Indicates whether the LayerTreeHostImpl is visible.
  178. void SetVisible(bool visible);
  179. bool visible() const { return visible_; }
  180. void SetBeginFrameSourcePaused(bool paused);
  181. bool begin_frame_source_paused() const { return begin_frame_source_paused_; }
  182. // Indicates that a redraw is required, either due to the impl tree changing
  183. // or the screen being damaged and simply needing redisplay. Note that if the
  184. // changes in the impl tree has not been activated yet, then |needs_redraw()|
  185. // can return false. For checking any invalidations, check
  186. // |did_invalidate_layer_tree_frame_sink()|.
  187. void SetNeedsRedraw();
  188. bool needs_redraw() const { return needs_redraw_; }
  189. bool did_invalidate_layer_tree_frame_sink() const {
  190. return did_invalidate_layer_tree_frame_sink_;
  191. }
  192. // Indicates that prepare-tiles is required. This guarantees another
  193. // PrepareTiles will occur shortly (even if no redraw is required).
  194. void SetNeedsPrepareTiles();
  195. // If the scheduler attempted to draw, this provides feedback regarding
  196. // whether or not a CompositorFrame was actually submitted. We might skip the
  197. // submitting anything when there is not damage, for example.
  198. void DidSubmitCompositorFrame();
  199. // Notification from the LayerTreeFrameSink that a submitted frame has been
  200. // consumed and it is ready for the next one.
  201. void DidReceiveCompositorFrameAck();
  202. int pending_submit_frames() const { return pending_submit_frames_; }
  203. // Indicates whether to prioritize impl thread latency (i.e., animation
  204. // smoothness) over new content activation.
  205. void SetTreePrioritiesAndScrollState(TreePriority tree_priority,
  206. ScrollHandlerState scroll_handler_state);
  207. // Indicates if the main thread will likely respond within 1 vsync.
  208. void SetCriticalBeginMainFrameToActivateIsFast(bool is_fast);
  209. // A function of SetTreePrioritiesAndScrollState and
  210. // SetCriticalBeginMainFrameToActivateIsFast.
  211. bool ImplLatencyTakesPriority() const;
  212. // Indicates that a new begin main frame flow needs to be performed, either
  213. // to pull updates from the main thread to the impl, or to push deltas from
  214. // the impl thread to main.
  215. void SetNeedsBeginMainFrame();
  216. bool needs_begin_main_frame() const { return needs_begin_main_frame_; }
  217. void SetMainThreadWantsBeginMainFrameNotExpectedMessages(bool new_state);
  218. bool wants_begin_main_frame_not_expected_messages() const {
  219. return wants_begin_main_frame_not_expected_;
  220. }
  221. // Requests a single impl frame (after the current frame if there is one
  222. // active).
  223. void SetNeedsOneBeginImplFrame();
  224. // Call this only in response to receiving an Action::SEND_BEGIN_MAIN_FRAME
  225. // from NextAction.
  226. // Indicates that all painting is complete.
  227. void NotifyReadyToCommit();
  228. // Call this only in response to receiving an Action::SEND_BEGIN_MAIN_FRAME
  229. // from NextAction if the client rejects the BeginMainFrame message.
  230. void BeginMainFrameAborted(CommitEarlyOutReason reason);
  231. // For Android WebView, resourceless software draws are allowed even when
  232. // invisible.
  233. void SetResourcelessSoftwareDraw(bool resourceless_draw);
  234. // Indicates whether drawing would, at this time, make sense.
  235. // CanDraw can be used to suppress flashes or checkerboarding
  236. // when such behavior would be undesirable.
  237. void SetCanDraw(bool can);
  238. // For Android WebView, indicates that the draw should be skipped because the
  239. // frame sink is not ready to receive frames.
  240. void SetSkipDraw(bool skip);
  241. // Indicates that the pending tree is ready for activation. Returns whether
  242. // the notification received updated the state for the current pending tree,
  243. // if any.
  244. bool NotifyReadyToActivate();
  245. bool IsReadyToActivate();
  246. // Indicates the active tree's visible tiles are ready to be drawn.
  247. void NotifyReadyToDraw();
  248. enum class AnimationWorkletState { PROCESSING, IDLE };
  249. enum class PaintWorkletState { PROCESSING, IDLE };
  250. enum class TreeType { ACTIVE, PENDING };
  251. // Indicates if currently processing animation worklets for the active or
  252. // pending tree. This is used to determine if the draw deadline should be
  253. // extended or activation delayed.
  254. void NotifyAnimationWorkletStateChange(AnimationWorkletState state,
  255. TreeType tree);
  256. // Sets whether asynchronous paint worklets are running. Paint worklets
  257. // running should block activation of the pending tree, as it isn't fully
  258. // painted until they are done.
  259. void NotifyPaintWorkletStateChange(PaintWorkletState state);
  260. void SetNeedsImplSideInvalidation(bool needs_first_draw_on_activation);
  261. bool has_pending_tree() const { return has_pending_tree_; }
  262. bool active_tree_needs_first_draw() const {
  263. return active_tree_needs_first_draw_;
  264. }
  265. void DidPrepareTiles();
  266. void DidLoseLayerTreeFrameSink();
  267. void DidCreateAndInitializeLayerTreeFrameSink();
  268. bool HasInitializedLayerTreeFrameSink() const;
  269. // True if we need to abort draws to make forward progress.
  270. bool PendingDrawsShouldBeAborted() const;
  271. bool CouldSendBeginMainFrame() const;
  272. void SetDeferBeginMainFrame(bool defer_begin_main_frame);
  273. void SetVideoNeedsBeginFrames(bool video_needs_begin_frames);
  274. bool video_needs_begin_frames() const { return video_needs_begin_frames_; }
  275. bool did_submit_in_last_frame() const { return did_submit_in_last_frame_; }
  276. bool draw_succeeded_in_last_frame() const {
  277. return draw_succeeded_in_last_frame_;
  278. }
  279. bool needs_impl_side_invalidation() const {
  280. return needs_impl_side_invalidation_;
  281. }
  282. bool previous_pending_tree_was_impl_side() const {
  283. return previous_pending_tree_was_impl_side_;
  284. }
  285. bool critical_begin_main_frame_to_activate_is_fast() const {
  286. return critical_begin_main_frame_to_activate_is_fast_;
  287. }
  288. void set_should_defer_invalidation_for_fast_main_frame(bool defer) {
  289. should_defer_invalidation_for_fast_main_frame_ = defer;
  290. }
  291. bool should_defer_invalidation_for_fast_main_frame() const {
  292. return should_defer_invalidation_for_fast_main_frame_;
  293. }
  294. int aborted_begin_main_frame_count() const {
  295. return aborted_begin_main_frame_count_;
  296. }
  297. bool pending_tree_is_ready_for_activation() const {
  298. return pending_tree_is_ready_for_activation_;
  299. }
  300. bool resourceless_draw() const { return resourceless_draw_; }
  301. protected:
  302. bool BeginFrameRequiredForAction() const;
  303. bool BeginFrameNeededForVideo() const;
  304. bool ProactiveBeginFrameWanted() const;
  305. // Indicates if we should post the deadline to draw immediately. This is true
  306. // when we aren't expecting a commit or activation, or we're prioritizing
  307. // active tree draw (see ImplLatencyTakesPriority()).
  308. bool ShouldTriggerBeginImplFrameDeadlineImmediately() const;
  309. // Indicates if we shouldn't schedule a deadline. Used to defer drawing until
  310. // the entire pipeline is flushed and active tree is ready to draw for
  311. // headless.
  312. bool ShouldBlockDeadlineIndefinitely() const;
  313. bool ShouldPerformImplSideInvalidation() const;
  314. bool CouldCreatePendingTree() const;
  315. bool ShouldDeferInvalidatingForMainFrame() const;
  316. bool ShouldAbortCurrentFrame() const;
  317. bool ShouldBeginLayerTreeFrameSinkCreation() const;
  318. bool ShouldDraw() const;
  319. bool ShouldActivateSyncTree() const;
  320. bool ShouldSendBeginMainFrame() const;
  321. bool ShouldCommit() const;
  322. bool ShouldRunPostCommit() const;
  323. bool ShouldPrepareTiles() const;
  324. bool ShouldInvalidateLayerTreeFrameSink() const;
  325. bool ShouldNotifyBeginMainFrameNotExpectedUntil() const;
  326. bool ShouldNotifyBeginMainFrameNotExpectedSoon() const;
  327. void WillDrawInternal();
  328. void WillPerformImplSideInvalidationInternal();
  329. void DidDrawInternal(DrawResult draw_result);
  330. const SchedulerSettings settings_;
  331. LayerTreeFrameSinkState layer_tree_frame_sink_state_ =
  332. LayerTreeFrameSinkState::NONE;
  333. BeginImplFrameState begin_impl_frame_state_ = BeginImplFrameState::IDLE;
  334. BeginMainFrameState begin_main_frame_state_ = BeginMainFrameState::IDLE;
  335. // A redraw is forced when too many checkerboarded-frames are produced during
  336. // an animation.
  337. ForcedRedrawOnTimeoutState forced_redraw_state_ =
  338. ForcedRedrawOnTimeoutState::IDLE;
  339. // These are used for tracing only.
  340. int commit_count_ = 0;
  341. int current_frame_number_ = 0;
  342. int last_frame_number_submit_performed_ = -1;
  343. int last_frame_number_draw_performed_ = -1;
  344. int last_frame_number_begin_main_frame_sent_ = -1;
  345. int last_frame_number_invalidate_layer_tree_frame_sink_performed_ = -1;
  346. // Inputs from the last impl frame that are required for decisions made in
  347. // this impl frame. The values from the last frame are cached before being
  348. // reset in OnBeginImplFrame.
  349. struct FrameEvents {
  350. bool commit_had_no_updates = false;
  351. bool did_commit_during_frame = false;
  352. };
  353. FrameEvents last_frame_events_;
  354. // These are used to ensure that an action only happens once per frame,
  355. // deadline, etc.
  356. bool did_draw_ = false;
  357. bool did_send_begin_main_frame_for_current_frame_ = true;
  358. // Initialized to true to prevent begin main frame before begin frames have
  359. // started. Reset to true when we stop asking for begin frames.
  360. bool did_notify_begin_main_frame_not_expected_until_ = true;
  361. bool did_notify_begin_main_frame_not_expected_soon_ = true;
  362. bool did_commit_during_frame_ = false;
  363. bool did_invalidate_layer_tree_frame_sink_ = false;
  364. bool did_perform_impl_side_invalidation_ = false;
  365. bool did_prepare_tiles_ = false;
  366. int consecutive_checkerboard_animations_ = 0;
  367. int pending_submit_frames_ = 0;
  368. int submit_frames_with_current_layer_tree_frame_sink_ = 0;
  369. bool needs_redraw_ = false;
  370. bool needs_prepare_tiles_ = false;
  371. bool needs_begin_main_frame_ = false;
  372. bool needs_one_begin_impl_frame_ = false;
  373. bool needs_post_commit_ = false;
  374. bool visible_ = false;
  375. bool begin_frame_source_paused_ = false;
  376. bool resourceless_draw_ = false;
  377. bool can_draw_ = false;
  378. bool skip_draw_ = false;
  379. bool has_pending_tree_ = false;
  380. bool pending_tree_is_ready_for_activation_ = false;
  381. bool active_tree_needs_first_draw_ = false;
  382. bool did_create_and_initialize_first_layer_tree_frame_sink_ = false;
  383. TreePriority tree_priority_ = NEW_CONTENT_TAKES_PRIORITY;
  384. ScrollHandlerState scroll_handler_state_ =
  385. ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER;
  386. bool critical_begin_main_frame_to_activate_is_fast_ = true;
  387. bool main_thread_missed_last_deadline_ = false;
  388. bool defer_begin_main_frame_ = false;
  389. bool video_needs_begin_frames_ = false;
  390. bool last_commit_had_no_updates_ = false;
  391. bool active_tree_is_ready_to_draw_ = true;
  392. bool did_attempt_draw_in_last_frame_ = false;
  393. bool draw_succeeded_in_last_frame_ = false;
  394. bool did_submit_in_last_frame_ = false;
  395. bool needs_impl_side_invalidation_ = false;
  396. bool next_invalidation_needs_first_draw_on_activation_ = false;
  397. bool should_defer_invalidation_for_fast_main_frame_ = true;
  398. bool begin_frame_is_animate_only_ = false;
  399. // Number of async mutation cycles for the active tree that are in-flight or
  400. // queued. Can be 0, 1 or 2.
  401. int processing_animation_worklets_for_active_tree_ = 0;
  402. // Indicates if an aysnc mutation cycle is in-flight or queued for the pending
  403. // tree. Only one can be running or queued at any time.
  404. bool processing_animation_worklets_for_pending_tree_ = false;
  405. // Indicates if asychronous paint worklet painting is ongoing for the pending
  406. // tree. During this time we should not activate the pending tree.
  407. bool processing_paint_worklets_for_pending_tree_ = false;
  408. bool previous_pending_tree_was_impl_side_ = false;
  409. bool current_pending_tree_is_impl_side_ = false;
  410. bool wants_begin_main_frame_not_expected_ = false;
  411. // If set to true, the pending tree must be drawn at least once after
  412. // activation before a new tree can be activated.
  413. bool pending_tree_needs_first_draw_on_activation_ = false;
  414. // Number of consecutive BeginMainFrames that were aborted without updates.
  415. int aborted_begin_main_frame_count_ = 0;
  416. };
  417. } // namespace cc
  418. #endif // CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_