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 93e2cc26faa84e547c97b8c21202b6d947a22f42..fcabba797509ea18f5ca08cd463817a98274d065 100644 |
| --- a/cc/scheduler/scheduler_state_machine_unittest.cc |
| +++ b/cc/scheduler/scheduler_state_machine_unittest.cc |
| @@ -7,6 +7,7 @@ |
| #include <stddef.h> |
| #include "base/trace_event/trace_event.h" |
| +#include "cc/output/begin_frame_args.h" |
| #include "cc/scheduler/scheduler.h" |
| #include "cc/test/begin_frame_args_test.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| @@ -86,6 +87,8 @@ class StateMachine : public SchedulerStateMachine { |
| compositor_frame_sink_state_ = COMPOSITOR_FRAME_SINK_ACTIVE; |
| } |
| + void OnBeginImplFrame() { OnBeginImplFrame(0, next_begin_frame_number_++); } |
| + |
| void SetBeginMainFrameState(BeginMainFrameState cs) { |
| begin_main_frame_state_ = cs; |
| } |
| @@ -150,12 +153,21 @@ class StateMachine : public SchedulerStateMachine { |
| has_pending_tree_ = has_pending_tree; |
| } |
| + uint64_t last_frame_number_pending_tree_was_fresh() const { |
| + return last_frame_number_pending_tree_was_fresh_; |
| + } |
| + uint64_t last_frame_number_active_tree_was_fresh() const { |
| + return last_frame_number_active_tree_was_fresh_; |
| + } |
| + |
| using SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately; |
| using SchedulerStateMachine::ProactiveBeginFrameWanted; |
| using SchedulerStateMachine::WillCommit; |
| + using SchedulerStateMachine::OnBeginImplFrame; |
| protected: |
| DrawResult draw_result_for_test_; |
| + uint64_t next_begin_frame_number_ = BeginFrameArgs::kStartingFrameNumber; |
| }; |
| void PerformAction(StateMachine* sm, SchedulerStateMachine::Action action) { |
| @@ -2150,5 +2162,332 @@ TEST(SchedulerStateMachineTest, CompositorFrameSinkCreationWhileCommitPending) { |
| SchedulerStateMachine::ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION); |
| } |
| +TEST(SchedulerStateMachineTest, TestFrameNumbering) { |
| + SchedulerSettings default_scheduler_settings; |
| + |
| + { |
|
Sami
2017/01/16 10:41:02
nit: Consider splitting each scope to a separate u
Eric Seckler
2017/01/16 14:33:01
Done.
|
| + // Initially, we report a valid current frame number, but invalid frame |
| + // numbers for freshness. |
| + StateMachine state(default_scheduler_settings); |
| + SET_UP_STATE(state) |
| + EXPECT_EQ(BeginFrameArgs::kStartingFrameNumber, |
| + state.current_frame_number()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_compositor_frame_was_fresh()); |
| + } |
| + |
| + { |
| + // Setup without any requested updates. |
| + StateMachine state(default_scheduler_settings); |
| + SET_UP_STATE(state) |
| + state.SetNeedsRedraw(false); |
| + EXPECT_FALSE(state.RedrawPending()); |
| + EXPECT_FALSE(state.NeedsCommit()); |
| + |
| + // OnBeginImplFrame() updates the current frame number. |
| + state.OnBeginImplFrame(0, 10); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_EQ(10u, state.current_frame_number()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_compositor_frame_was_fresh()); |
| + |
| + // When no updates are required, OnBeginImplFrameDeadline() updates active |
| + // tree and compositor frame freshness. |
| + state.OnBeginImplFrameDeadline(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_EQ(10u, state.current_frame_number()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(10u, state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(10u, state.last_frame_number_compositor_frame_was_fresh()); |
| + state.OnBeginImplFrameIdle(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + } |
| + |
| + { |
| + // Setup with an impl-thread draw requested. |
| + StateMachine state(default_scheduler_settings); |
| + SET_UP_STATE(state) |
| + state.SetNeedsRedraw(true); |
| + EXPECT_TRUE(state.RedrawPending()); |
| + EXPECT_FALSE(state.NeedsCommit()); |
| + |
| + // OnBeginImplFrame() updates the current frame number. |
| + state.OnBeginImplFrame(0, 10); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_EQ(10u, state.current_frame_number()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_compositor_frame_was_fresh()); |
| + |
| + // With only an impl-thread draw requested, OnBeginImplFrameDeadline() |
| + // updates the active tree freshness. |
| + state.OnBeginImplFrameDeadline(); |
| + EXPECT_EQ(10u, state.current_frame_number()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(10u, state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_compositor_frame_was_fresh()); |
| + |
| + // Compositor frame freshness is updated when active tree is drawn. |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_FALSE(state.RedrawPending()); |
| + state.DidSubmitCompositorFrame(); |
| + state.DidReceiveCompositorFrameAck(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_EQ(10u, state.current_frame_number()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(10u, state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(10u, state.last_frame_number_compositor_frame_was_fresh()); |
| + state.OnBeginImplFrameIdle(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + } |
| + |
| + { |
| + // Setup with a BeginMainFrame requested. |
| + StateMachine state(default_scheduler_settings); |
| + SET_UP_STATE(state) |
| + state.SetNeedsRedraw(false); |
| + state.SetNeedsBeginMainFrameForTest(true); |
| + EXPECT_FALSE(state.RedrawPending()); |
| + EXPECT_TRUE(state.NeedsCommit()); |
| + |
| + // OnBeginImplFrame() updates the current frame number. |
| + state.OnBeginImplFrame(0, 10); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_FALSE(state.NeedsCommit()); |
| + EXPECT_TRUE(state.CommitPending()); |
| + EXPECT_EQ(10u, state.current_frame_number()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_compositor_frame_was_fresh()); |
| + |
| + // When a BeginMainFrame is needed, OnBeginImplFrameDeadline() updates no |
| + // freshness numbers. |
| + state.OnBeginImplFrameDeadline(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_EQ(10u, state.current_frame_number()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_compositor_frame_was_fresh()); |
| + state.OnBeginImplFrameIdle(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // When a main frame is in progress, OnBeginImplFrameDeadline() updates no |
| + // freshness numbers. |
| + state.NotifyBeginMainFrameStarted(); |
| + state.OnBeginImplFrame(0, 11); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + state.OnBeginImplFrameDeadline(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_EQ(11u, state.current_frame_number()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_compositor_frame_was_fresh()); |
| + state.OnBeginImplFrameIdle(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // Pending tree freshness is updated when the new pending tree is committed. |
| + state.NotifyReadyToCommit(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_FALSE(state.CommitPending()); |
| + EXPECT_TRUE(state.has_pending_tree()); |
| + EXPECT_EQ(11u, state.current_frame_number()); |
| + EXPECT_EQ(10u, state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_compositor_frame_was_fresh()); |
| + |
| + // If no further BeginMainFrame is needed, OnBeginFrameImplDeadline() |
| + // updates the pending tree's frame number. |
| + state.OnBeginImplFrame(0, 12); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + state.OnBeginImplFrameDeadline(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_EQ(12u, state.current_frame_number()); |
| + EXPECT_EQ(12u, state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_compositor_frame_was_fresh()); |
| + state.OnBeginImplFrameIdle(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // If a further BeginMainFrame is needed, OnBeginFrameImplDeadline() |
| + // updates no freshness numbers. |
| + state.SetNeedsBeginMainFrameForTest(true); |
| + EXPECT_TRUE(state.NeedsCommit()); |
| + state.OnBeginImplFrame(0, 13); |
| + // BMF will be sent only after pending_tree activation. |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + state.OnBeginImplFrameDeadline(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_EQ(13u, state.current_frame_number()); |
| + EXPECT_EQ(12u, state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_compositor_frame_was_fresh()); |
| + state.OnBeginImplFrameIdle(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // Active tree freshness is updated when pending frame is activated. |
| + state.NotifyReadyToActivate(); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_FALSE(state.has_pending_tree()); |
| + EXPECT_EQ(13u, state.current_frame_number()); |
| + EXPECT_EQ(12u, state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(12u, state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_compositor_frame_was_fresh()); |
| + EXPECT_TRUE(state.RedrawPending()); |
| + |
| + // BMF requested above will be sent after activation. |
| + state.OnBeginImplFrame(0, 14); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // Active tree freshness is updated when commit didn't have updates. |
| + state.NotifyBeginMainFrameStarted(); |
| + state.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES); |
| + EXPECT_EQ(14u, state.current_frame_number()); |
| + EXPECT_EQ(12u, state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(14u, state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_compositor_frame_was_fresh()); |
| + |
| + // Compositor frame freshness is updated when active tree is drawn. |
| + state.OnBeginImplFrameDeadline(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_FALSE(state.RedrawPending()); |
| + state.DidSubmitCompositorFrame(); |
| + state.DidReceiveCompositorFrameAck(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_EQ(14u, state.current_frame_number()); |
| + EXPECT_EQ(12u, state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(14u, state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(14u, state.last_frame_number_compositor_frame_was_fresh()); |
| + state.OnBeginImplFrameIdle(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // When no updates are required, OnBeginImplFrameDeadline() updates active |
| + // tree and compositor frame freshness. |
| + state.OnBeginImplFrame(0, 15); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + state.OnBeginImplFrameDeadline(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_EQ(15u, state.current_frame_number()); |
| + EXPECT_EQ(12u, state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(15u, state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(15u, state.last_frame_number_compositor_frame_was_fresh()); |
| + state.OnBeginImplFrameIdle(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + |
| + // When the source changes, the current frame number is updated and frame |
| + // numbers for freshness are reset to the prior frame number of the source. |
| + state.OnBeginImplFrame(1, 5); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_EQ(5u, state.current_frame_number()); |
| + EXPECT_EQ(4u, state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(4u, state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(4u, state.last_frame_number_compositor_frame_was_fresh()); |
| + |
| + // When no updates are required, OnBeginImplFrameDeadline() updates active |
| + // tree and compositor frame freshness. |
| + state.OnBeginImplFrameDeadline(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_EQ(5u, state.current_frame_number()); |
| + EXPECT_EQ(4u, state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(5u, state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(5u, state.last_frame_number_compositor_frame_was_fresh()); |
| + state.OnBeginImplFrameIdle(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + } |
| + |
| + { |
| + // Setup with main_frame_before_activation_enabled, a pending tree, and a |
| + // new BeginMainFrame requested. |
| + SchedulerSettings settings; |
| + settings.main_frame_before_activation_enabled = true; |
| + StateMachine state(settings); |
| + SET_UP_STATE(state) |
| + state.SetHasPendingTree(true); |
| + state.SetNeedsRedraw(false); |
| + state.SetNeedsBeginMainFrameForTest(true); |
| + EXPECT_FALSE(state.RedrawPending()); |
| + EXPECT_TRUE(state.NeedsCommit()); |
| + |
| + // OnBeginImplFrame() updates the current frame number. |
| + state.OnBeginImplFrame(0, 10); |
| + EXPECT_ACTION_UPDATE_STATE( |
| + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_FALSE(state.NeedsCommit()); |
| + EXPECT_TRUE(state.CommitPending()); |
| + EXPECT_EQ(10u, state.current_frame_number()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_compositor_frame_was_fresh()); |
| + |
| + // Pending tree freshness is updated when commit didn't have updates, but an |
| + // older pending tree is still pending. |
| + state.NotifyBeginMainFrameStarted(); |
| + state.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES); |
| + EXPECT_EQ(10u, state.current_frame_number()); |
| + EXPECT_EQ(10u, state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_compositor_frame_was_fresh()); |
| + |
| + // As no further BeginMainFrame is needed, OnBeginFrameImplDeadline() |
| + // updates the pending tree's frame number, but without any visible change. |
| + state.OnBeginImplFrameDeadline(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + EXPECT_EQ(10u, state.current_frame_number()); |
| + EXPECT_EQ(10u, state.last_frame_number_pending_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_active_tree_was_fresh()); |
| + EXPECT_EQ(BeginFrameArgs::kInvalidFrameNumber, |
| + state.last_frame_number_compositor_frame_was_fresh()); |
| + state.OnBeginImplFrameIdle(); |
| + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); |
| + } |
| +} |
| + |
| } // namespace |
| } // namespace cc |