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..db632973dce70989cbcc5a4d12cd6ad2e747371e 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,255 @@ TEST(SchedulerStateMachineTest, |
SchedulerStateMachine::ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION); |
} |
+TEST(SchedulerStateMachineTest, NoImplSideInvalidationsWhileInvisible) { |
+ 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(); |
+ state.OnBeginImplFrame(); |
+ state.OnBeginImplFrameDeadline(); |
+ 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(); |
+ state.OnBeginImplFrame(); |
+ state.OnBeginImplFrameDeadline(); |
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
+} |
+ |
+TEST(SchedulerStateMachineTest, ImplSideInvalidationOnlyInsideDeadline) { |
+ SchedulerSettings settings; |
+ StateMachine state(settings); |
+ SET_UP_STATE(state); |
+ |
+ state.SetNeedsImplSideInvalidation(); |
+ state.OnBeginImplFrame(); |
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
+ state.OnBeginImplFrameDeadline(); |
+ EXPECT_ACTION_UPDATE_STATE( |
+ SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION); |
+} |
+ |
+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.SetNeedsImplSideInvalidation(); |
+ state.OnBeginImplFrame(); |
+ state.OnBeginImplFrameDeadline(); |
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
+ |
+ // Initializing the CompositorFrameSink puts us in a state waiting for the |
+ // first commit. |
+ state.DidCreateAndInitializeCompositorFrameSink(); |
+ state.OnBeginImplFrame(); |
+ EXPECT_ACTION_UPDATE_STATE( |
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); |
+ state.NotifyBeginMainFrameStarted(); |
+ state.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES); |
+ state.OnBeginImplFrameDeadline(); |
+ 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); |
+ state.NotifyBeginMainFrameStarted(); |
+ state.NotifyReadyToCommit(); |
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); |
+ |
+ // 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); |
+ state.OnBeginImplFrameDeadline(); |
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE); |
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
+ |
+ // Since there is no main frame request, this should perform impl-side |
+ // invalidations. |
+ state.OnBeginImplFrame(); |
+ state.OnBeginImplFrameDeadline(); |
+ EXPECT_ACTION_UPDATE_STATE( |
+ SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION); |
+} |
+ |
+TEST(SchedulerStateMachineTest, ImplSideInvalidationWhileReadyToCommit) { |
+ 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()); |
+ |
+ // Deadline. |
+ state.OnBeginImplFrameDeadline(); |
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
+} |
+ |
+TEST(SchedulerStateMachineTest, |
+ ConsecutiveImplSideInvalidationsWaitForBeginFrame) { |
+ SchedulerSettings settings; |
+ StateMachine state(settings); |
+ SET_UP_STATE(state); |
+ |
+ // Set up a request for impl-side invalidation. |
+ state.SetNeedsImplSideInvalidation(); |
+ state.OnBeginImplFrame(); |
+ state.OnBeginImplFrameDeadline(); |
+ EXPECT_ACTION_UPDATE_STATE( |
+ SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION); |
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
+ |
+ // Request another invalidation, which should wait until the pending tree is |
+ // activated *and* we start 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); |
+ |
+ // Now start the next frame, which will first draw the active tree and then |
+ // perform the pending impl-side invalidation request. |
+ state.OnBeginImplFrame(); |
+ state.OnBeginImplFrameDeadline(); |
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE); |
+ 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, activate and draw. |
+ 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); |
+ state.NotifyReadyToDraw(); |
+ state.OnBeginImplFrameDeadline(); |
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE); |
+ state.DidSubmitCompositorFrame(); |
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
+ |
+ // Request impl-side invalidation and start a new frame, which should be |
+ // blocked on the ack for the previous frame. |
+ state.SetNeedsImplSideInvalidation(); |
+ state.OnBeginImplFrame(); |
+ state.OnBeginImplFrameDeadline(); |
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
+ |
+ // Ack the previous frame and begin impl frame, which should perform the |
+ // invalidation now. |
+ state.DidReceiveCompositorFrameAck(); |
+ state.OnBeginImplFrame(); |
+ state.OnBeginImplFrameDeadline(); |
+ EXPECT_ACTION_UPDATE_STATE( |
+ SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION); |
+} |
+ |
+TEST(SchedulerStateMachineTest, |
+ ImplSideInvalidationsWhenMainFrameRequestIsPending) { |
+ 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 and trigger the deadline, the |
+ // invalidation should run if the request is still pending when we enter the |
+ // deadline. |
+ state.SetNeedsImplSideInvalidation(); |
+ state.OnBeginImplFrameDeadline(); |
+ EXPECT_ACTION_UPDATE_STATE( |
+ SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION); |
+} |
+ |
+TEST(SchedulerStateMachineTest, PrepareTilesWaitForImplSideInvalidation) { |
+ // PrepareTiles |
+ SchedulerSettings settings; |
+ StateMachine state(settings); |
+ SET_UP_STATE(state); |
+ |
+ // Request a PrepareTiles and impl-side invalidation. The impl-side |
+ // invalidation should run first, since it will perform PrepareTiles as well. |
+ state.SetNeedsImplSideInvalidation(); |
+ state.SetNeedsPrepareTiles(); |
+ state.OnBeginImplFrame(); |
+ state.OnBeginImplFrameDeadline(); |
+ EXPECT_ACTION_UPDATE_STATE( |
+ SchedulerStateMachine::ACTION_PERFORM_IMPL_SIDE_INVALIDATION); |
+ state.DidPrepareTiles(); |
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
+} |
+ |
} // namespace |
} // namespace cc |