#ifndef CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_
#define CC_SCHEDULER_SCHEDULER_STATE_MACHINE_H_
#include <stdint.h>
#include "base/time/time.h"
#include "base/tracing/protos/chrome_track_event.pbzero.h"
#include "cc/cc_export.h"
#include "cc/scheduler/commit_earlyout_reason.h"
#include "cc/scheduler/draw_result.h"
#include "cc/scheduler/scheduler_settings.h"
#include "cc/tiles/tile_priority.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
namespace cc {
enum class ScrollHandlerState {
SCROLL_AFFECTS_SCROLL_HANDLER,
SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER,
};
class CC_EXPORT SchedulerStateMachine {
public:
explicit SchedulerStateMachine(const SchedulerSettings& settings);
SchedulerStateMachine(const SchedulerStateMachine&) = delete;
~SchedulerStateMachine();
SchedulerStateMachine& operator=(const SchedulerStateMachine&) = delete;
enum class LayerTreeFrameSinkState {
NONE,
ACTIVE,
CREATING,
WAITING_FOR_FIRST_COMMIT,
WAITING_FOR_FIRST_ACTIVATION,
};
static perfetto::protos::pbzero::ChromeCompositorStateMachineV2::
MajorStateV2::LayerTreeFrameSinkState
LayerTreeFrameSinkStateToProtozeroEnum(LayerTreeFrameSinkState state);
enum class BeginImplFrameState {
IDLE,
INSIDE_BEGIN_FRAME,
INSIDE_DEADLINE,
};
static perfetto::protos::pbzero::ChromeCompositorStateMachineV2::
MajorStateV2::BeginImplFrameState
BeginImplFrameStateToProtozeroEnum(BeginImplFrameState state);
enum class BeginImplFrameDeadlineMode {
NONE = 0,
IMMEDIATE = 1,
WAIT_FOR_SCROLL = 2,
REGULAR = 3,
LATE = 4,
BLOCKED = 5,
kMaxValue = BLOCKED,
};
static const char* BeginImplFrameDeadlineModeToString(
BeginImplFrameDeadlineMode mode);
static perfetto::protos::pbzero::ChromeCompositorSchedulerStateV2::
BeginImplFrameDeadlineMode
BeginImplFrameDeadlineModeToProtozeroEnum(
BeginImplFrameDeadlineMode mode);
enum class BeginMainFrameState {
IDLE,
SENT,
READY_TO_COMMIT,
};
static perfetto::protos::pbzero::ChromeCompositorStateMachineV2::
MajorStateV2::BeginMainFrameState
BeginMainFrameStateToProtozeroEnum(BeginMainFrameState state);
enum class ForcedRedrawOnTimeoutState {
IDLE,
WAITING_FOR_COMMIT,
WAITING_FOR_ACTIVATION,
WAITING_FOR_DRAW,
};
static perfetto::protos::pbzero::ChromeCompositorStateMachineV2::
MajorStateV2::ForcedRedrawOnTimeoutState
ForcedRedrawOnTimeoutStateToProtozeroEnum(
ForcedRedrawOnTimeoutState state);
static constexpr base::TimeDelta kUrgentBoostDuration =
base::Milliseconds(1500);
BeginMainFrameState begin_main_frame_state() const {
return begin_main_frame_state_;
}
bool CommitPending() const {
return begin_main_frame_state_ != BeginMainFrameState::IDLE;
}
bool NewActiveTreeLikely() const {
return (needs_begin_main_frame_ && !last_commit_had_no_updates_) ||
CommitPending() || has_pending_tree_;
}
bool RedrawPending() const { return needs_redraw_; }
bool PrepareTilesPending() const { return needs_prepare_tiles_; }
enum class Action {
NONE,
SEND_BEGIN_MAIN_FRAME,
COMMIT,
POST_COMMIT,
ACTIVATE_SYNC_TREE,
PERFORM_IMPL_SIDE_INVALIDATION,
DRAW_IF_POSSIBLE,
DRAW_FORCED,
DRAW_ABORT,
BEGIN_LAYER_TREE_FRAME_SINK_CREATION,
PREPARE_TILES,
INVALIDATE_LAYER_TREE_FRAME_SINK,
NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_UNTIL,
NOTIFY_BEGIN_MAIN_FRAME_NOT_EXPECTED_SOON,
};
static perfetto::protos::pbzero::ChromeCompositorSchedulerActionV2
ActionToProtozeroEnum(Action action);
void AsProtozeroInto(
perfetto::protos::pbzero::ChromeCompositorStateMachineV2* state) const;
Action NextAction() const;
void WillSendBeginMainFrame();
void WillNotifyBeginMainFrameNotExpectedUntil();
void WillNotifyBeginMainFrameNotExpectedSoon();
void WillCommit(bool commit_had_no_updates);
void DidCommit();
void DidPostCommit();
void WillActivate();
void WillDraw();
void WillBeginLayerTreeFrameSinkCreation();
void WillPrepareTiles();
void WillInvalidateLayerTreeFrameSink();
void WillPerformImplSideInvalidation();
void DidDraw(DrawResult draw_result);
void AbortDraw();
bool BeginFrameNeeded() const;
bool ShouldSubscribeToBeginFrames() const;
void OnBeginImplFrame(const viz::BeginFrameArgs& args);
void OnBeginImplFrameDeadline();
void OnBeginImplFrameIdle();
int current_frame_number() const { return current_frame_number_; }
BeginImplFrameState begin_impl_frame_state() const {
return begin_impl_frame_state_;
}
BeginImplFrameDeadlineMode CurrentBeginImplFrameDeadlineMode() const;
bool main_thread_missed_last_deadline() const {
return main_thread_missed_last_deadline_;
}
bool IsDrawThrottled() const;
void FrameIntervalUpdated(base::TimeDelta frame_interval);
base::TimeDelta MainFrameThrottledInterval() const;
void SetVisible(bool visible);
bool visible() const { return visible_; }
void SetShouldWarmUp();
void SetBeginFrameSourcePaused(bool paused);
bool begin_frame_source_paused() const { return begin_frame_source_paused_; }
void SetNeedsRedraw();
bool needs_redraw() const { return needs_redraw_; }
bool did_invalidate_layer_tree_frame_sink() const {
return did_invalidate_layer_tree_frame_sink_;
}
void SetNeedsPrepareTiles();
void DidSubmitCompositorFrame();
void DidReceiveCompositorFrameAck();
int pending_submit_frames() const { return pending_submit_frames_; }
void SetTreePrioritiesAndScrollState(TreePriority tree_priority,
ScrollHandlerState scroll_handler_state,
bool is_current_scroll_main_painted);
void SetCriticalBeginMainFrameToActivateIsFast(bool is_fast);
bool ImplLatencyTakesPriority() const;
void SetNeedsBeginMainFrame(bool now = false);
bool needs_begin_main_frame() const { return needs_begin_main_frame_; }
void SetMainThreadWantsBeginMainFrameNotExpectedMessages(bool new_state);
void SetNeedsOneBeginImplFrame();
void NotifyReadyToCommit();
void BeginMainFrameAborted(CommitEarlyOutReason reason);
void SetResourcelessSoftwareDraw(bool resourceless_draw);
void SetCanDraw(bool can);
void SetSkipDraw(bool skip);
bool NotifyReadyToActivate();
bool IsReadyToActivate();
void NotifyReadyToDraw();
enum class AnimationWorkletState { PROCESSING, IDLE };
enum class PaintWorkletState { PROCESSING, IDLE };
enum class TreeType { ACTIVE, PENDING };
void NotifyAnimationWorkletStateChange(AnimationWorkletState state,
TreeType tree);
void NotifyPaintWorkletStateChange(PaintWorkletState state);
void SetNeedsImplSideInvalidation(bool needs_first_draw_on_activation);
bool has_pending_tree() const { return has_pending_tree_; }
bool active_tree_needs_first_draw() const {
return active_tree_needs_first_draw_;
}
void DidPrepareTiles();
void DidLoseLayerTreeFrameSink();
void DidCreateAndInitializeLayerTreeFrameSink();
bool HasInitializedLayerTreeFrameSink() const;
bool PendingDrawsShouldBeAborted() const;
bool CouldSendBeginMainFrame() const;
void SetDeferBeginMainFrame(bool defer_begin_main_frame);
void SetPauseRendering(bool pause_rendering);
void SetVideoNeedsBeginFrames(bool video_needs_begin_frames);
bool ShouldThrottleSendBeginMainFrame() const;
bool did_submit_in_last_frame() const { return did_submit_in_last_frame_; }
bool draw_succeeded_in_last_frame() const {
return draw_succeeded_in_last_frame_;
}
bool needs_impl_side_invalidation() const {
return needs_impl_side_invalidation_;
}
bool previous_pending_tree_was_impl_side() const {
return previous_pending_tree_was_impl_side_;
}
bool critical_begin_main_frame_to_activate_is_fast() const {
return critical_begin_main_frame_to_activate_is_fast_;
}
void set_should_defer_invalidation_for_fast_main_frame(bool defer) {
should_defer_invalidation_for_fast_main_frame_ = defer;
}
bool should_defer_invalidation_for_fast_main_frame() const {
return should_defer_invalidation_for_fast_main_frame_;
}
bool pending_tree_is_ready_for_activation() const {
return pending_tree_is_ready_for_activation_;
}
bool resourceless_draw() const { return resourceless_draw_; }
void set_is_scrolling(bool is_scrolling) { is_scrolling_ = is_scrolling; }
#if BUILDFLAG(ARKWEB_SLIDE_LTPO)
bool is_scrolling() const {return is_scrolling_; }
#endif
void set_waiting_for_scroll_event(bool waiting_for_scroll_event) {
waiting_for_scroll_event_ = waiting_for_scroll_event;
}
void SetShouldThrottleFrameRate(bool flag);
virtual base::TimeTicks Now() const;
protected:
bool BeginFrameRequiredForAction() const;
bool BeginFrameNeededForVideo() const;
bool ProactiveBeginFrameWanted() const;
bool ShouldWaitForScrollEvent() const;
bool ShouldTriggerBeginImplFrameDeadlineImmediately() const;
bool ShouldBlockDeadlineIndefinitely() const;
bool ShouldPerformImplSideInvalidation() const;
bool CouldCreatePendingTree() const;
bool ShouldDeferInvalidatingForMainFrame() const;
bool ShouldAbortCurrentFrame() const;
bool ShouldBeginLayerTreeFrameSinkCreation() const;
bool ShouldDraw() const;
bool ShouldActivateSyncTree() const;
bool ShouldSendBeginMainFrame() const;
bool ShouldCommit() const;
bool ShouldRunPostCommit() const;
bool ShouldPrepareTiles() const;
bool ShouldInvalidateLayerTreeFrameSink() const;
bool ShouldNotifyBeginMainFrameNotExpectedUntil() const;
bool ShouldNotifyBeginMainFrameNotExpectedSoon() const;
void WillDrawInternal();
void WillPerformImplSideInvalidationInternal();
void DidDrawInternal(DrawResult draw_result);
const SchedulerSettings settings_;
LayerTreeFrameSinkState layer_tree_frame_sink_state_ =
LayerTreeFrameSinkState::NONE;
BeginImplFrameState begin_impl_frame_state_ = BeginImplFrameState::IDLE;
BeginMainFrameState begin_main_frame_state_ = BeginMainFrameState::IDLE;
BeginMainFrameState next_begin_main_frame_state_ = BeginMainFrameState::IDLE;
ForcedRedrawOnTimeoutState forced_redraw_state_ =
ForcedRedrawOnTimeoutState::IDLE;
int commit_count_ = 0;
int current_frame_number_ = 0;
int last_frame_number_submit_performed_ = -1;
int last_frame_number_draw_performed_ = -1;
int last_frame_number_begin_main_frame_sent_ = -1;
int last_frame_number_invalidate_layer_tree_frame_sink_performed_ = -1;
base::TimeTicks last_begin_impl_frame_time_;
base::TimeTicks last_sent_begin_main_frame_time_;
base::TimeDelta main_frame_throttled_interval_;
base::TimeDelta unthrottled_frame_interval_;
base::TimeTicks last_urgent_main_frame_request_;
struct FrameEvents {
bool commit_had_no_updates = false;
bool did_commit_during_frame = false;
};
FrameEvents last_frame_events_;
bool did_draw_ = false;
bool did_send_begin_main_frame_for_current_frame_ = true;
bool did_notify_begin_main_frame_not_expected_until_ = true;
bool did_notify_begin_main_frame_not_expected_soon_ = true;
bool did_commit_during_frame_ = false;
bool did_invalidate_layer_tree_frame_sink_ = false;
bool did_perform_impl_side_invalidation_ = false;
bool did_prepare_tiles_ = false;
int consecutive_checkerboard_animations_ = 0;
int pending_submit_frames_ = 0;
int submit_frames_with_current_layer_tree_frame_sink_ = 0;
bool needs_redraw_ = false;
bool needs_prepare_tiles_ = false;
bool needs_begin_main_frame_ = false;
bool needs_one_begin_impl_frame_ = false;
bool needs_post_commit_ = false;
bool visible_ = false;
bool should_warm_up_ = false;
bool begin_frame_source_paused_ = false;
bool resourceless_draw_ = false;
bool can_draw_ = false;
bool skip_draw_ = false;
bool has_pending_tree_ = false;
bool pending_tree_is_ready_for_activation_ = false;
bool active_tree_needs_first_draw_ = false;
bool did_create_and_initialize_first_layer_tree_frame_sink_ = false;
TreePriority tree_priority_ = NEW_CONTENT_TAKES_PRIORITY;
ScrollHandlerState scroll_handler_state_ =
ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER;
bool is_current_scroll_main_painted_ = false;
bool critical_begin_main_frame_to_activate_is_fast_ = true;
bool main_thread_missed_last_deadline_ = false;
bool defer_begin_main_frame_ = false;
bool pause_rendering_ = false;
bool waiting_for_activation_after_rendering_resumed_ = false;
bool video_needs_begin_frames_ = false;
bool last_commit_had_no_updates_ = false;
bool active_tree_is_ready_to_draw_ = true;
bool did_attempt_draw_in_last_frame_ = false;
bool draw_succeeded_in_last_frame_ = false;
bool did_submit_in_last_frame_ = false;
bool needs_impl_side_invalidation_ = false;
bool next_invalidation_needs_first_draw_on_activation_ = false;
bool should_defer_invalidation_for_fast_main_frame_ = true;
bool begin_frame_is_animate_only_ = false;
int processing_animation_worklets_for_active_tree_ = 0;
bool processing_animation_worklets_for_pending_tree_ = false;
bool processing_paint_worklets_for_pending_tree_ = false;
bool previous_pending_tree_was_impl_side_ = false;
bool current_pending_tree_is_impl_side_ = false;
bool wants_begin_main_frame_not_expected_ = false;
bool pending_tree_needs_first_draw_on_activation_ = false;
bool draw_aborted_for_paused_begin_frame_ = false;
unsigned consecutive_cant_draw_count_ = 0u;
bool is_scrolling_ = false;
bool waiting_for_scroll_event_ = false;
bool throttle_frame_rate_ = false;
};
}
#endif