Chromium Code Reviews| Index: cc/scheduler/scheduler_state_machine_unittest.cc |
| diff --git a/cc/scheduler/scheduler_state_machine_unittest.cc b/cc/scheduler/scheduler_state_machine_unittest.cc |
| index aa5c4aac39a1164318196bfee92197fcbc1a2909..a02c089aace4af6ad883284659102e93ddff4eb4 100644 |
| --- a/cc/scheduler/scheduler_state_machine_unittest.cc |
| +++ b/cc/scheduler/scheduler_state_machine_unittest.cc |
| @@ -150,6 +150,10 @@ class StateMachine : public SchedulerStateMachine { |
| has_pending_tree_ = has_pending_tree; |
| } |
| + bool needs_impl_side_invalidation() const { |
| + return needs_impl_side_invalidation_; |
| + } |
| + |
| using SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately; |
| using SchedulerStateMachine::ProactiveBeginFrameWanted; |
| using SchedulerStateMachine::WillCommit; |
| @@ -200,6 +204,10 @@ void PerformAction(StateMachine* sm, SchedulerStateMachine::Action action) { |
| case SchedulerStateMachine::ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK: |
| sm->WillInvalidateCompositorFrameSink(); |
| return; |
| + |
| + case SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION: |
| + sm->WillPerformImplSideInvalidation(); |
| + return; |
| } |
| } |
| @@ -2123,5 +2131,284 @@ TEST(SchedulerStateMachineTest, |
| SchedulerStateMachine::ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION); |
| } |
| +TEST(SchedulerStateMachineTest, NoImplSideInvalidationsWhileInvsible) { |
|
brianderson
2017/02/21 23:34:59
Invsible -> Invisible
Khushal
2017/02/22 20:24:02
Done.
|
| + SchedulerSettings settings; |
| + StateMachine state(settings); |
| + SET_UP_STATE(state); |
| + |
| + // No impl-side invalidations should be performed while we are not visible. |
| + state.SetVisible(false); |
| + state.SetNeedsImplSideInvalidation(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| +} |
| + |
| +TEST(SchedulerStateMachineTest, |
| + NoImplSideInvalidationsWhenBeginFrameSourcePaused) { |
| + SchedulerSettings settings; |
| + StateMachine state(settings); |
| + SET_UP_STATE(state); |
| + |
| + // No impl-side invalidations should be performed while we can not make impl |
| + // frames. |
| + state.SetBeginFrameSourcePaused(true); |
| + state.SetNeedsImplSideInvalidation(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| +} |
| + |
| +TEST(SchedulerStateMachineTest, |
| + NoImplSideInvalidationWithoutCompositorFrameSink) { |
| + SchedulerSettings settings; |
| + StateMachine state(settings); |
| + SET_UP_STATE(state); |
| + |
| + // Impl-side invalidations should not be triggered till the frame sink is |
| + // initialized. |
| + state.DidLoseCompositorFrameSink(); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // No impl-side invalidations should be performed during frame sink creation. |
| + state.OnBeginImplFrame(); |
| + state.SetNeedsImplSideInvalidation(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // Initializing the CompositorFrameSink puts us in a state waiting for the |
| + // first commit. |
| + state.DidCreateAndInitializeCompositorFrameSink(); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); |
| + state.NotifyBeginMainFrameStarted(); |
| + state.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION); |
| +} |
| + |
| +TEST(SchedulerStateMachineTest, ImplSideInvalidationWhenPendingTreeExists) { |
| + SchedulerSettings settings; |
| + StateMachine state(settings); |
| + SET_UP_STATE(state); |
| + |
| + // Set up request for the main frame, commit and create the pending tree. |
| + state.SetNeedsBeginMainFrame(); |
| + state.OnBeginImplFrame(); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + state.NotifyBeginMainFrameStarted(); |
| + state.NotifyReadyToCommit(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // Request an impl-side invalidation after the commit. The request should wait |
| + // till the current pending tree is activated. |
| + state.SetNeedsImplSideInvalidation(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // Activate the pending tree. Since the commit fills the impl-side |
| + // invalidation funnel as well, the request should wait until the next |
| + // BeginFrame. |
| + state.NotifyReadyToActivate(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // Since there is no main frame request, this should perform impl-side |
| + // invalidations. |
| + state.OnBeginImplFrame(); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION); |
| +} |
| + |
| +TEST(SchedulerStateMachineTest, ImplSideInvalidationWhileMainFramePending) { |
| + SchedulerSettings settings; |
| + StateMachine state(settings); |
| + SET_UP_STATE(state); |
| + |
| + // Set up request for the main frame. |
| + state.SetNeedsBeginMainFrame(); |
| + state.OnBeginImplFrame(); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // Request an impl-side invalidation. The request should wait till a response |
| + // is received from the main thread. |
| + state.SetNeedsImplSideInvalidation(); |
| + EXPECT_TRUE(state.needs_impl_side_invalidation()); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // Perform a commit, the impl-side invalidation request should be reset since |
| + // they will be merged with the commit. |
| + state.NotifyBeginMainFrameStarted(); |
| + state.NotifyReadyToCommit(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); |
| + EXPECT_FALSE(state.needs_impl_side_invalidation()); |
| +} |
| + |
| +TEST(SchedulerStateMachineTest, |
| + ConsecutiveImplSideInvalidationsWaitForBeginFrame) { |
| + SchedulerSettings settings; |
| + StateMachine state(settings); |
| + SET_UP_STATE(state); |
| + |
| + // Set up a request for impl-side invalidation. |
| + state.SetNeedsImplSideInvalidation(); |
| + state.OnBeginImplFrame(); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // Request another invalidation before the pending tree is activated. The |
| + // request should wait until the next BeginFrame. |
| + state.SetNeedsImplSideInvalidation(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + state.NotifyReadyToActivate(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + state.OnBeginImplFrame(); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION); |
| +} |
| + |
| +TEST(SchedulerStateMachineTest, ImplSideInvalidationsThrottledOnDraw) { |
| + // In commit_to_active_tree mode, performing the next invalidation should be |
| + // throttled on the active tree being drawn. |
| + SchedulerSettings settings; |
| + settings.commit_to_active_tree = true; |
| + StateMachine state(settings); |
| + SET_UP_STATE(state); |
| + |
| + // Commit to the sync tree and activate. |
| + state.SetNeedsBeginMainFrame(); |
| + state.OnBeginImplFrame(); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); |
| + state.NotifyBeginMainFrameStarted(); |
| + state.NotifyReadyToCommit(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); |
| + state.NotifyReadyToActivate(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // BeginImplFrame deadline, the draw is blocked on NotifyReadyToDraw. |
| + state.OnBeginImplFrameDeadline(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // Request impl-side invalidation which should be blocked on the active tree |
| + // being drawn and submitted. |
| + state.SetNeedsImplSideInvalidation(); |
| + state.OnBeginImplFrame(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + state.NotifyReadyToDraw(); |
| + state.OnBeginImplFrameDeadline(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE); |
| + state.DidSubmitCompositorFrame(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + state.DidReceiveCompositorFrameAck(); |
| + |
| + // The frame being acked should perform impl-side invalidation. |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION); |
| +} |
| + |
| +TEST(SchedulerStateMachineTest, |
| + ImplSideInvalidationsTakePriorityForAbortedCommits) { |
| + SchedulerSettings settings; |
| + settings.main_frame_before_activation_enabled = true; |
| + StateMachine state(settings); |
| + SET_UP_STATE(state); |
| + |
| + // Set up request for the main frame. |
| + state.SetNeedsBeginMainFrame(); |
| + state.OnBeginImplFrame(); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // Request an impl-side invalidation, which should wait until a response is |
| + // received for the BeginMainFrame. |
| + state.SetNeedsImplSideInvalidation(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // Request another main frame, and abort the sent BeginMainFrame. Aborting |
| + // this frame should create a pending tree for impl-side invalidation. |
| + state.SetNeedsBeginMainFrame(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + state.NotifyBeginMainFrameStarted(); |
| + state.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION); |
| + |
| + // Trigger the frame deadline, this should send the BeginMainFrame since MFBA |
| + // is enabled. |
| + state.OnBeginImplFrameDeadline(); |
| + state.OnBeginImplFrame(); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); |
| +} |
| + |
| +TEST(SchedulerStateMachineTest, |
| + ImplSideInvalidationsBlockedOnSendingBeginMainFrame) { |
| + SchedulerSettings settings; |
| + StateMachine state(settings); |
| + SET_UP_STATE(state); |
| + |
| + // BeginMainFrame, commit and activate the sync tree. |
| + state.SetNeedsBeginMainFrame(); |
| + state.OnBeginImplFrame(); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); |
| + state.NotifyBeginMainFrameStarted(); |
| + state.NotifyReadyToCommit(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); |
| + state.NotifyReadyToActivate(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); |
| + |
| + // Set the tree priority to smoothness mode and request a main frame and |
| + // impl-side invalidations. |
| + state.OnBeginImplFrameDeadline(); |
| + state.OnBeginImplFrame(); |
| + state.SetTreePrioritiesAndScrollState( |
| + TreePriority::SMOOTHNESS_TAKES_PRIORITY, |
| + ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER); |
| + state.SetNeedsBeginMainFrame(); |
| + state.SetNeedsImplSideInvalidation(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // The impl-side invalidations should wait until BeginMainFrame is sent and |
| + // a response is received. |
| + state.SetTreePrioritiesAndScrollState( |
| + TreePriority::SMOOTHNESS_TAKES_PRIORITY, |
| + ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); |
| + state.NotifyBeginMainFrameStarted(); |
| + state.NotifyReadyToCommit(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); |
| + EXPECT_FALSE(state.needs_impl_side_invalidation()); |
| +} |
| + |
| +TEST(SchedulerStateMachineTest, BeginMainFrameAfterImplSideInvalidation) { |
| + // A BeginMainFrame should be sent, if the request is received after an |
| + // impl-side invalidation. |
| + SchedulerSettings settings; |
| + settings.main_frame_before_activation_enabled = true; |
| + StateMachine state(settings); |
| + SET_UP_STATE(state); |
| + |
| + // Request an impl side invalidation and perform the action. |
| + state.SetNeedsImplSideInvalidation(); |
| + state.OnBeginImplFrame(); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // Request a main frame, which should be sent within the same BeginFrame in |
| + // MFBA mode. |
| + state.SetNeedsBeginMainFrame(); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); |
| +} |
| + |
| } // namespace |
| } // namespace cc |