| Index: cc/scheduler/scheduler_state_machine.cc
|
| diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc
|
| index 4e6509f527ddc35ac7be8b8355b85111f3cbbfa7..9ee7933f50d507653ef1e29d8fe23b664e48b40b 100644
|
| --- a/cc/scheduler/scheduler_state_machine.cc
|
| +++ b/cc/scheduler/scheduler_state_machine.cc
|
| @@ -26,6 +26,7 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
|
| last_frame_number_swap_performed_(-1),
|
| last_frame_number_swap_requested_(-1),
|
| last_frame_number_begin_main_frame_sent_(-1),
|
| + last_frame_number_invalidate_output_surface_performed_(-1),
|
| prepare_tiles_funnel_(0),
|
| consecutive_checkerboard_animations_(0),
|
| max_pending_swaps_(1),
|
| @@ -34,7 +35,6 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
|
| needs_animate_(false),
|
| needs_prepare_tiles_(false),
|
| needs_commit_(false),
|
| - inside_poll_for_anticipated_draw_triggers_(false),
|
| visible_(false),
|
| can_start_(false),
|
| can_draw_(false),
|
| @@ -86,6 +86,22 @@ const char* SchedulerStateMachine::BeginImplFrameStateToString(
|
| return "???";
|
| }
|
|
|
| +const char* SchedulerStateMachine::BeginImplFrameDeadlineModeToString(
|
| + BeginImplFrameDeadlineMode mode) {
|
| + switch (mode) {
|
| + case BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_SYNCHRONOUS:
|
| + return "BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_SYNCHRONOUS";
|
| + case BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_ASYNCHRONOUS:
|
| + return "BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_ASYNCHRONOUS";
|
| + case BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR:
|
| + return "BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR";
|
| + case BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE:
|
| + return "BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE";
|
| + }
|
| + NOTREACHED();
|
| + return "???";
|
| +}
|
| +
|
| const char* SchedulerStateMachine::CommitStateToString(CommitState state) {
|
| switch (state) {
|
| case COMMIT_STATE_IDLE:
|
| @@ -143,6 +159,8 @@ const char* SchedulerStateMachine::ActionToString(Action action) {
|
| return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION";
|
| case ACTION_PREPARE_TILES:
|
| return "ACTION_PREPARE_TILES";
|
| + case ACTION_INVALIDATE_OUTPUT_SURFACE:
|
| + return "ACTION_INVALIDATE_OUTPUT_SURFACE";
|
| }
|
| NOTREACHED();
|
| return "???";
|
| @@ -243,7 +261,7 @@ void SchedulerStateMachine::AsValueInto(base::trace_event::TracedValue* state,
|
| state->EndDictionary();
|
| }
|
|
|
| -void SchedulerStateMachine::AdvanceCurrentFrameNumber() {
|
| +void SchedulerStateMachine::AdvanceFrame() {
|
| current_frame_number_++;
|
|
|
| // "Drain" the PrepareTiles funnel.
|
| @@ -272,6 +290,11 @@ bool SchedulerStateMachine::HasRequestedSwapThisFrame() const {
|
| return current_frame_number_ == last_frame_number_swap_requested_;
|
| }
|
|
|
| +bool SchedulerStateMachine::HasInvalidatedOutputSurfaceThisFrame() const {
|
| + return current_frame_number_ ==
|
| + last_frame_number_invalidate_output_surface_performed_;
|
| +}
|
| +
|
| bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const {
|
| // These are all the cases where we normally cannot or do not want to draw
|
| // but, if needs_redraw_ is true and we do not draw to make forward progress,
|
| @@ -336,6 +359,11 @@ bool SchedulerStateMachine::ShouldBeginOutputSurfaceCreation() const {
|
| }
|
|
|
| bool SchedulerStateMachine::ShouldDraw() const {
|
| + // In the synchronous compositor mode, draw only when asked to.
|
| + if (settings_.using_synchronous_renderer_compositor &&
|
| + begin_impl_frame_args_.type != BeginFrameArgs::SYNCHRONOUS_DRAW)
|
| + return false;
|
| +
|
| // If we need to abort draws, we should do so ASAP since the draw could
|
| // be blocking other important actions (like output surface initialization),
|
| // from occuring. If we are waiting for the first draw, then perfom the
|
| @@ -499,14 +527,29 @@ bool SchedulerStateMachine::ShouldPrepareTiles() const {
|
| return false;
|
|
|
| // Limiting to once per-frame is not enough, since we only want to
|
| - // prepare tiles _after_ draws. Polling for draw triggers and
|
| - // begin-frame are mutually exclusive, so we limit to these two cases.
|
| - if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE &&
|
| - !inside_poll_for_anticipated_draw_triggers_)
|
| + // prepare tiles _after_ draws.
|
| + if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
|
| return false;
|
| +
|
| return needs_prepare_tiles_;
|
| }
|
|
|
| +bool SchedulerStateMachine::ShouldInvalidateOutputSurface() const {
|
| + // Only the synchronous compositor requires invalidations.
|
| + if (!settings_.using_synchronous_renderer_compositor)
|
| + return false;
|
| +
|
| + // Invalidations are only performed inside a BeginFrame deadline.
|
| + if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
|
| + return false;
|
| +
|
| + // Invalidate the output surface only once per frame.
|
| + if (HasInvalidatedOutputSurfaceThisFrame())
|
| + return false;
|
| +
|
| + return needs_redraw_;
|
| +}
|
| +
|
| SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
|
| if (ShouldActivatePendingTree())
|
| return ACTION_ACTIVATE_SYNC_TREE;
|
| @@ -526,6 +569,8 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
|
| return ACTION_PREPARE_TILES;
|
| if (ShouldSendBeginMainFrame())
|
| return ACTION_SEND_BEGIN_MAIN_FRAME;
|
| + if (ShouldInvalidateOutputSurface())
|
| + return ACTION_INVALIDATE_OUTPUT_SURFACE;
|
| if (ShouldBeginOutputSurfaceCreation())
|
| return ACTION_BEGIN_OUTPUT_SURFACE_CREATION;
|
| return ACTION_NONE;
|
| @@ -593,6 +638,11 @@ void SchedulerStateMachine::UpdateState(Action action) {
|
| case ACTION_PREPARE_TILES:
|
| UpdateStateOnPrepareTiles();
|
| return;
|
| +
|
| + case ACTION_INVALIDATE_OUTPUT_SURFACE:
|
| + last_frame_number_invalidate_output_surface_performed_ =
|
| + current_frame_number_;
|
| + return;
|
| }
|
| }
|
|
|
| @@ -706,21 +756,8 @@ bool SchedulerStateMachine::BeginFrameNeeded() const {
|
| // TODO(brianderson): Support output surface creation inside a BeginFrame.
|
| if (!HasInitializedOutputSurface())
|
| return false;
|
| -
|
| - if (SupportsProactiveBeginFrame()) {
|
| - return (BeginFrameNeededToAnimateOrDraw() ||
|
| - BeginFrameNeededForChildren() ||
|
| - ProactiveBeginFrameWanted());
|
| - }
|
| -
|
| - // Proactive BeginFrames are bad for the synchronous compositor because we
|
| - // have to draw when we get the BeginFrame and could end up drawing many
|
| - // duplicate frames if our new frame isn't ready in time.
|
| - // To poll for state with the synchronous compositor without having to draw,
|
| - // we rely on ShouldPollForAnticipatedDrawTriggers instead.
|
| - // Synchronous compositor doesn't have a browser.
|
| - DCHECK(!children_need_begin_frames_);
|
| - return BeginFrameNeededToAnimateOrDraw();
|
| + return (BeginFrameNeededToAnimateOrDraw() || BeginFrameNeededForChildren() ||
|
| + ProactiveBeginFrameWanted());
|
| }
|
|
|
| bool SchedulerStateMachine::ShouldSetNeedsBeginFrames(
|
| @@ -746,29 +783,6 @@ bool SchedulerStateMachine::ShouldSetNeedsBeginFrames(
|
| return false;
|
| }
|
|
|
| -bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const {
|
| - // ShouldPollForAnticipatedDrawTriggers is what we use in place of
|
| - // ProactiveBeginFrameWanted when we are using the synchronous
|
| - // compositor.
|
| - if (!SupportsProactiveBeginFrame()) {
|
| - return !BeginFrameNeededToAnimateOrDraw() && ProactiveBeginFrameWanted();
|
| - }
|
| -
|
| - // Non synchronous compositors should rely on
|
| - // ProactiveBeginFrameWanted to poll for state instead.
|
| - return false;
|
| -}
|
| -
|
| -// Note: If SupportsProactiveBeginFrame is false, the scheduler should poll
|
| -// for changes in it's draw state so it can request a BeginFrame when it's
|
| -// actually ready.
|
| -bool SchedulerStateMachine::SupportsProactiveBeginFrame() const {
|
| - // It is undesirable to proactively request BeginFrames if we are
|
| - // using a synchronous compositor because we *must* draw for every
|
| - // BeginFrame, which could cause duplicate draws.
|
| - return !settings_.using_synchronous_renderer_compositor;
|
| -}
|
| -
|
| void SchedulerStateMachine::SetChildrenNeedBeginFrames(
|
| bool children_need_begin_frames) {
|
| DCHECK(settings_.forward_begin_frames_to_children);
|
| @@ -826,8 +840,13 @@ bool SchedulerStateMachine::ProactiveBeginFrameWanted() const {
|
| }
|
|
|
| void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) {
|
| - AdvanceCurrentFrameNumber();
|
| begin_impl_frame_args_ = args;
|
| +
|
| + // Advance frame for synchronous compositor on SYNCHRONOUS_ANIMATE only.
|
| + if (!settings_.using_synchronous_renderer_compositor ||
|
| + begin_impl_frame_args_.type == BeginFrameArgs::SYNCHRONOUS_ANIMATE)
|
| + AdvanceFrame();
|
| +
|
| DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE)
|
| << AsValue()->ToString();
|
| begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING;
|
| @@ -854,8 +873,11 @@ void SchedulerStateMachine::OnBeginImplFrameIdle() {
|
|
|
| SchedulerStateMachine::BeginImplFrameDeadlineMode
|
| SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const {
|
| - if (ShouldTriggerBeginImplFrameDeadlineImmediately()) {
|
| - return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE;
|
| + if (settings_.using_synchronous_renderer_compositor) {
|
| + // If the synchronous compositor wants to draw now.
|
| + return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_SYNCHRONOUS;
|
| + } else if (ShouldTriggerBeginImplFrameDeadlineImmediately()) {
|
| + return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_ASYNCHRONOUS;
|
| } else if (needs_redraw_ && pending_swaps_ < max_pending_swaps_) {
|
| // We have an animation or fast input path on the impl thread that wants
|
| // to draw, so don't wait too long for a new active tree.
|
| @@ -872,7 +894,6 @@ SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const {
|
| bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately()
|
| const {
|
| // TODO(brianderson): This should take into account multiple commit sources.
|
| -
|
| if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
|
| return false;
|
|
|
| @@ -952,15 +973,6 @@ bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const {
|
| return active_tree_needs_first_draw_;
|
| }
|
|
|
| -void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() {
|
| - AdvanceCurrentFrameNumber();
|
| - inside_poll_for_anticipated_draw_triggers_ = true;
|
| -}
|
| -
|
| -void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() {
|
| - inside_poll_for_anticipated_draw_triggers_ = false;
|
| -}
|
| -
|
| void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }
|
|
|
| void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }
|
|
|