Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(274)

Unified Diff: cc/scheduler/scheduler_state_machine_unittest.cc

Issue 1531403002: Revert "Delete CC." (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/scheduler/scheduler_state_machine.cc ('k') | cc/scheduler/scheduler_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
new file mode 100644
index 0000000000000000000000000000000000000000..4c2c267a5a493ebbbe734017265f2af8b8f7325b
--- /dev/null
+++ b/cc/scheduler/scheduler_state_machine_unittest.cc
@@ -0,0 +1,1850 @@
+// Copyright 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/scheduler/scheduler_state_machine.h"
+
+#include "base/trace_event/trace_event.h"
+#include "cc/scheduler/scheduler.h"
+#include "cc/test/begin_frame_args_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Macro to compare two enum values and get nice output.
+// Without:
+// Value of: actual() Actual: 7
+// Expected: expected() Which is: 0
+// With:
+// Value of: actual() Actual: "ACTION_ANIMATE"
+// Expected: expected() Which is: "ACTION_NONE"
+#define EXPECT_ENUM_EQ(enum_tostring, expected, actual) \
+ EXPECT_STREQ(SchedulerStateMachine::enum_tostring(expected), \
+ SchedulerStateMachine::enum_tostring(actual))
+
+#define EXPECT_IMPL_FRAME_STATE(expected) \
+ EXPECT_ENUM_EQ(BeginImplFrameStateToString, expected, \
+ state.begin_impl_frame_state()) \
+ << state.AsValue()->ToString()
+
+#define EXPECT_COMMIT_STATE(expected) \
+ EXPECT_ENUM_EQ(CommitStateToString, expected, state.CommitState())
+
+#define EXPECT_ACTION(expected) \
+ EXPECT_ENUM_EQ(ActionToString, expected, state.NextAction()) \
+ << state.AsValue()->ToString()
+
+#define EXPECT_ACTION_UPDATE_STATE(action) \
+ EXPECT_ACTION(action); \
+ if (action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE || \
+ action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED) { \
+ EXPECT_IMPL_FRAME_STATE( \
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE); \
+ } \
+ state.UpdateState(action); \
+ if (action == SchedulerStateMachine::ACTION_NONE) { \
+ if (state.begin_impl_frame_state() == \
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) \
+ state.OnBeginImplFrameDeadlinePending(); \
+ if (state.begin_impl_frame_state() == \
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) \
+ state.OnBeginImplFrameIdle(); \
+ }
+
+#define SET_UP_STATE(state) \
+ state.SetCanStart(); \
+ state.UpdateState(state.NextAction()); \
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); \
+ state.SetVisible(true); \
+ state.SetCanDraw(true);
+
+namespace cc {
+
+namespace {
+
+const SchedulerStateMachine::BeginImplFrameState all_begin_impl_frame_states[] =
+ {SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE,
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, };
+
+const SchedulerStateMachine::CommitState all_commit_states[] = {
+ SchedulerStateMachine::COMMIT_STATE_IDLE,
+ SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
+ SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED,
+ SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
+ SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_ACTIVATION,
+ SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_DRAW};
+
+// Exposes the protected state fields of the SchedulerStateMachine for testing
+class StateMachine : public SchedulerStateMachine {
+ public:
+ explicit StateMachine(const SchedulerSettings& scheduler_settings)
+ : SchedulerStateMachine(scheduler_settings) {}
+
+ void CreateAndInitializeOutputSurfaceWithActivatedCommit() {
+ DidCreateAndInitializeOutputSurface();
+ output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
+ }
+
+ void SetCommitState(CommitState cs) { commit_state_ = cs; }
+ CommitState CommitState() const { return commit_state_; }
+
+ ForcedRedrawOnTimeoutState ForcedRedrawState() const {
+ return forced_redraw_state_;
+ }
+
+ void SetBeginImplFrameState(BeginImplFrameState bifs) {
+ begin_impl_frame_state_ = bifs;
+ }
+
+ BeginImplFrameState begin_impl_frame_state() const {
+ return begin_impl_frame_state_;
+ }
+
+ OutputSurfaceState output_surface_state() const {
+ return output_surface_state_;
+ }
+
+ bool NeedsCommit() const { return needs_commit_; }
+
+ void SetNeedsRedraw(bool b) { needs_redraw_ = b; }
+
+ void SetNeedsForcedRedrawForTimeout(bool b) {
+ forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT;
+ active_tree_needs_first_draw_ = true;
+ }
+ bool NeedsForcedRedrawForTimeout() const {
+ return forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE;
+ }
+
+ void SetActiveTreeNeedsFirstDraw(bool needs_first_draw) {
+ active_tree_needs_first_draw_ = needs_first_draw;
+ }
+
+ bool CanDraw() const { return can_draw_; }
+ bool Visible() const { return visible_; }
+
+ bool PendingActivationsShouldBeForced() const {
+ return SchedulerStateMachine::PendingActivationsShouldBeForced();
+ }
+
+ void SetHasPendingTree(bool has_pending_tree) {
+ has_pending_tree_ = has_pending_tree;
+ }
+
+ using SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately;
+ using SchedulerStateMachine::ProactiveBeginFrameWanted;
+ using SchedulerStateMachine::UpdateStateOnCommit;
+};
+
+TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) {
+ SchedulerSettings default_scheduler_settings;
+
+ // If no commit needed, do nothing.
+ {
+ StateMachine state(default_scheduler_settings);
+ state.SetCanStart();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION)
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+ state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ state.SetNeedsRedraw(false);
+ state.SetVisible(true);
+
+ EXPECT_FALSE(state.BeginFrameNeeded());
+
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_FALSE(state.BeginFrameNeeded());
+ state.OnBeginImplFrame();
+
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+ }
+
+ // If commit requested but can_start is still false, do nothing.
+ {
+ StateMachine state(default_scheduler_settings);
+ state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ state.SetNeedsRedraw(false);
+ state.SetVisible(true);
+ state.SetNeedsCommit();
+
+ EXPECT_FALSE(state.BeginFrameNeeded());
+
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_FALSE(state.BeginFrameNeeded());
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+ }
+
+ // If commit requested, begin a main frame.
+ {
+ StateMachine state(default_scheduler_settings);
+ state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ state.SetCanStart();
+ state.UpdateState(state.NextAction());
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+ state.SetNeedsRedraw(false);
+ state.SetVisible(true);
+ state.SetNeedsCommit();
+
+ EXPECT_TRUE(state.BeginFrameNeeded());
+
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ }
+
+ // Begin the frame, make sure needs_commit and commit_state update correctly.
+ {
+ StateMachine state(default_scheduler_settings);
+ state.SetCanStart();
+ state.UpdateState(state.NextAction());
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+ state.SetVisible(true);
+ state.UpdateState(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_COMMIT_STATE(
+ SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_FALSE(state.NeedsCommit());
+ }
+}
+
+// Explicitly test main_frame_before_activation_enabled = true
+TEST(SchedulerStateMachineTest, MainFrameBeforeActivationEnabled) {
+ SchedulerSettings scheduler_settings;
+ scheduler_settings.impl_side_painting = true;
+ scheduler_settings.main_frame_before_activation_enabled = true;
+ StateMachine state(scheduler_settings);
+ state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ SET_UP_STATE(state)
+ state.SetNeedsRedraw(false);
+ state.SetNeedsCommit();
+
+ EXPECT_TRUE(state.BeginFrameNeeded());
+
+ // Commit to the pending tree.
+ 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);
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Verify that the next commit starts while there is still a pending tree.
+ state.SetNeedsCommit();
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Verify the pending commit doesn't overwrite the pending
+ // tree until the pending tree has been activated.
+ state.NotifyBeginMainFrameStarted();
+ state.NotifyReadyToCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Verify NotifyReadyToActivate unblocks activation, draw, and
+ // commit in that order.
+ state.NotifyReadyToActivate();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ state.DidSwapBuffersComplete();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+}
+
+TEST(SchedulerStateMachineTest,
+ TestFailedDrawForAnimationCheckerboardSetsNeedsCommitAndDoesNotDrawAgain) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ SET_UP_STATE(state)
+ state.SetNeedsRedraw(true);
+ EXPECT_TRUE(state.RedrawPending());
+ EXPECT_TRUE(state.BeginFrameNeeded());
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+
+ // We're drawing now.
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ state.DidSwapBuffersComplete();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ EXPECT_FALSE(state.RedrawPending());
+ EXPECT_FALSE(state.CommitPending());
+
+ // Failing the draw makes us require a commit.
+ state.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_TRUE(state.RedrawPending());
+ EXPECT_TRUE(state.CommitPending());
+}
+
+TEST(SchedulerStateMachineTest, TestFailedDrawForMissingHighResNeedsCommit) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ SET_UP_STATE(state)
+ state.SetNeedsRedraw(true);
+ EXPECT_TRUE(state.RedrawPending());
+ EXPECT_TRUE(state.BeginFrameNeeded());
+
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ state.DidSwapBuffersComplete();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_FALSE(state.RedrawPending());
+ EXPECT_FALSE(state.CommitPending());
+
+ // Missing high res content requires a commit (but not a redraw)
+ state.DidDrawIfPossibleCompleted(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT);
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_FALSE(state.RedrawPending());
+ EXPECT_TRUE(state.CommitPending());
+}
+
+TEST(SchedulerStateMachineTest,
+ TestsetNeedsRedrawDuringFailedDrawDoesNotRemoveNeedsRedraw) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ SET_UP_STATE(state)
+ state.SetNeedsRedraw(true);
+ EXPECT_TRUE(state.RedrawPending());
+ EXPECT_TRUE(state.BeginFrameNeeded());
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+
+ // We're drawing now.
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ state.DidSwapBuffersComplete();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_FALSE(state.RedrawPending());
+ EXPECT_FALSE(state.CommitPending());
+
+ // While still in the same BeginMainFrame callback on the main thread,
+ // set needs redraw again. This should not redraw.
+ state.SetNeedsRedraw(true);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Failing the draw for animation checkerboards makes us require a commit.
+ state.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_TRUE(state.RedrawPending());
+}
+
+TEST(SchedulerStateMachineTest,
+ TestFailedDrawsEventuallyForceDrawAfterNextCommit) {
+ SchedulerSettings scheduler_settings;
+ scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ = 1;
+ StateMachine state(scheduler_settings);
+ SET_UP_STATE(state)
+
+ // Start a commit.
+ state.SetNeedsCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_TRUE(state.CommitPending());
+
+ // Then initiate a draw.
+ state.SetNeedsRedraw(true);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+
+ // Fail the draw.
+ state.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_TRUE(state.BeginFrameNeeded());
+ EXPECT_TRUE(state.RedrawPending());
+ // But the commit is ongoing.
+ EXPECT_TRUE(state.CommitPending());
+
+ // Finish the commit. Note, we should not yet be forcing a draw, but should
+ // continue the commit as usual.
+ state.NotifyBeginMainFrameStarted();
+ state.NotifyReadyToCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_TRUE(state.RedrawPending());
+
+ // The redraw should be forced at the end of the next BeginImplFrame.
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED);
+ state.DidSwapBuffers();
+ state.DidSwapBuffersComplete();
+}
+
+TEST(SchedulerStateMachineTest, TestFailedDrawsDoNotRestartForcedDraw) {
+ SchedulerSettings scheduler_settings;
+ int draw_limit = 1;
+ scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ =
+ draw_limit;
+ scheduler_settings.impl_side_painting = true;
+ StateMachine state(scheduler_settings);
+ SET_UP_STATE(state)
+
+ // Start a commit.
+ state.SetNeedsCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_TRUE(state.CommitPending());
+
+ // Then initiate a draw.
+ state.SetNeedsRedraw(true);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+
+ // Fail the draw enough times to force a redraw,
+ // then once more for good measure.
+ for (int i = 0; i < draw_limit + 1; ++i)
+ state.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_TRUE(state.BeginFrameNeeded());
+ EXPECT_TRUE(state.RedrawPending());
+ // But the commit is ongoing.
+ EXPECT_TRUE(state.CommitPending());
+ EXPECT_TRUE(state.ForcedRedrawState() ==
+ SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_COMMIT);
+
+ state.NotifyBeginMainFrameStarted();
+ state.NotifyReadyToCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_TRUE(state.RedrawPending());
+ EXPECT_FALSE(state.CommitPending());
+
+ // Now force redraw should be in waiting for activation
+ EXPECT_TRUE(state.ForcedRedrawState() ==
+ SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION);
+
+ // After failing additional draws, we should still be in a forced
+ // redraw, but not back in WAITING_FOR_COMMIT.
+ for (int i = 0; i < draw_limit + 1; ++i)
+ state.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
+ EXPECT_TRUE(state.RedrawPending());
+ EXPECT_TRUE(state.ForcedRedrawState() ==
+ SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION);
+}
+
+TEST(SchedulerStateMachineTest, TestFailedDrawIsRetriedInNextBeginImplFrame) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ SET_UP_STATE(state)
+
+ // Start a draw.
+ state.SetNeedsRedraw(true);
+ EXPECT_TRUE(state.BeginFrameNeeded());
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_TRUE(state.RedrawPending());
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+
+ // Failing the draw for animation checkerboards makes us require a commit.
+ state.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_TRUE(state.RedrawPending());
+
+ // We should not be trying to draw again now, but we have a commit pending.
+ EXPECT_TRUE(state.BeginFrameNeeded());
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // We should try to draw again at the end of the next BeginImplFrame on
+ // the impl thread.
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ state.DidSwapBuffersComplete();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+}
+
+TEST(SchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ SET_UP_STATE(state)
+ state.SetNeedsRedraw(true);
+
+ // Draw the first frame.
+ EXPECT_TRUE(state.BeginFrameNeeded());
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ state.DidDrawIfPossibleCompleted(DRAW_SUCCESS);
+ state.DidSwapBuffersComplete();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Before the next BeginImplFrame, set needs redraw again.
+ // This should not redraw until the next BeginImplFrame.
+ state.SetNeedsRedraw(true);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Move to another frame. This should now draw.
+ EXPECT_TRUE(state.BeginFrameNeeded());
+ state.OnBeginImplFrame();
+
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ state.DidDrawIfPossibleCompleted(DRAW_SUCCESS);
+ state.DidSwapBuffersComplete();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // We just swapped, so we should proactively request another BeginImplFrame.
+ EXPECT_TRUE(state.BeginFrameNeeded());
+}
+
+TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginImplFrame) {
+ SchedulerSettings default_scheduler_settings;
+
+ // When not in BeginImplFrame deadline, or in BeginImplFrame deadline
+ // but not visible, don't draw.
+ size_t num_commit_states =
+ sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
+ size_t num_begin_impl_frame_states =
+ sizeof(all_begin_impl_frame_states) /
+ sizeof(SchedulerStateMachine::BeginImplFrameState);
+ for (size_t i = 0; i < num_commit_states; ++i) {
+ for (size_t j = 0; j < num_begin_impl_frame_states; ++j) {
+ StateMachine state(default_scheduler_settings);
+ state.SetCanStart();
+ state.UpdateState(state.NextAction());
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+ state.SetCommitState(all_commit_states[i]);
+ state.SetBeginImplFrameState(all_begin_impl_frame_states[j]);
+ bool visible =
+ (all_begin_impl_frame_states[j] !=
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
+ state.SetVisible(visible);
+
+ // Case 1: needs_commit=false
+ EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
+ state.NextAction());
+
+ // Case 2: needs_commit=true
+ state.SetNeedsCommit();
+ EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
+ state.NextAction())
+ << state.AsValue()->ToString();
+ }
+ }
+
+ // When in BeginImplFrame deadline we should always draw for SetNeedsRedraw
+ // except if we're ready to commit, in which case we expect a commit first.
+ for (size_t i = 0; i < num_commit_states; ++i) {
+ StateMachine state(default_scheduler_settings);
+ state.SetCanStart();
+ state.UpdateState(state.NextAction());
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+ state.SetCanDraw(true);
+ state.SetCommitState(all_commit_states[i]);
+ state.SetBeginImplFrameState(
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
+
+ state.SetNeedsRedraw(true);
+ state.SetVisible(true);
+
+ SchedulerStateMachine::Action expected_action;
+ if (all_commit_states[i] ==
+ SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT) {
+ expected_action = SchedulerStateMachine::ACTION_COMMIT;
+ } else {
+ expected_action = SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_ANIMATE);
+ state.UpdateState(state.NextAction());
+ }
+
+ // Case 1: needs_commit=false.
+ EXPECT_ACTION(expected_action);
+
+ // Case 2: needs_commit=true.
+ state.SetNeedsCommit();
+ EXPECT_ACTION(expected_action);
+ }
+}
+
+TEST(SchedulerStateMachineTest, TestNoCommitStatesRedrawWhenInvisible) {
+ SchedulerSettings default_scheduler_settings;
+
+ size_t num_commit_states =
+ sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
+ for (size_t i = 0; i < num_commit_states; ++i) {
+ // There shouldn't be any drawing regardless of BeginImplFrame.
+ for (size_t j = 0; j < 2; ++j) {
+ StateMachine state(default_scheduler_settings);
+ state.SetCanStart();
+ state.UpdateState(state.NextAction());
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+ state.SetCommitState(all_commit_states[i]);
+ state.SetVisible(false);
+ state.SetNeedsRedraw(true);
+ if (j == 1) {
+ state.SetBeginImplFrameState(
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
+ }
+
+ // Case 1: needs_commit=false.
+ EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
+ state.NextAction());
+
+ // Case 2: needs_commit=true.
+ state.SetNeedsCommit();
+ EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
+ state.NextAction())
+ << state.AsValue()->ToString();
+ }
+ }
+}
+
+TEST(SchedulerStateMachineTest, TestCanRedraw_StopsDraw) {
+ SchedulerSettings default_scheduler_settings;
+
+ size_t num_commit_states =
+ sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
+ for (size_t i = 0; i < num_commit_states; ++i) {
+ // There shouldn't be any drawing regardless of BeginImplFrame.
+ for (size_t j = 0; j < 2; ++j) {
+ StateMachine state(default_scheduler_settings);
+ state.SetCanStart();
+ state.UpdateState(state.NextAction());
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+ state.SetCommitState(all_commit_states[i]);
+ state.SetVisible(false);
+ state.SetNeedsRedraw(true);
+ if (j == 1)
+ state.OnBeginImplFrame();
+
+ state.SetCanDraw(false);
+ EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
+ state.NextAction());
+ }
+ }
+}
+
+TEST(SchedulerStateMachineTest,
+ TestCanRedrawWithWaitingForFirstDrawMakesProgress) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ state.SetCanStart();
+ state.UpdateState(state.NextAction());
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+
+ state.SetActiveTreeNeedsFirstDraw(true);
+ state.SetNeedsCommit();
+ state.SetNeedsRedraw(true);
+ state.SetVisible(true);
+ state.SetCanDraw(false);
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
+ 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);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+}
+
+TEST(SchedulerStateMachineTest, TestSetNeedsCommitIsNotLost) {
+ SchedulerSettings scheduler_settings;
+ StateMachine state(scheduler_settings);
+ SET_UP_STATE(state)
+ state.SetNeedsCommit();
+
+ EXPECT_TRUE(state.BeginFrameNeeded());
+
+ // Begin the frame.
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_COMMIT_STATE(
+ SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+
+ // Now, while the frame is in progress, set another commit.
+ state.SetNeedsCommit();
+ EXPECT_TRUE(state.NeedsCommit());
+
+ // Let the frame finish.
+ state.NotifyBeginMainFrameStarted();
+ state.NotifyReadyToCommit();
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT);
+
+ // Expect to commit regardless of BeginImplFrame state.
+ EXPECT_IMPL_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT);
+
+ state.OnBeginImplFrameDeadlinePending();
+ EXPECT_IMPL_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT);
+
+ state.OnBeginImplFrameDeadline();
+ EXPECT_IMPL_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT);
+
+ state.OnBeginImplFrameIdle();
+ EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT);
+
+ state.OnBeginImplFrame();
+ EXPECT_IMPL_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT);
+
+ // Finish the commit, then make sure we start the next commit immediately
+ // and draw on the next BeginImplFrame.
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ state.OnBeginImplFrameDeadline();
+
+ EXPECT_TRUE(state.active_tree_needs_first_draw());
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ state.DidDrawIfPossibleCompleted(DRAW_SUCCESS);
+ state.DidSwapBuffersComplete();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+}
+
+TEST(SchedulerStateMachineTest, TestFullCycle) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ SET_UP_STATE(state)
+
+ // Start clean and set commit.
+ state.SetNeedsCommit();
+
+ // Begin the frame.
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_COMMIT_STATE(
+ SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_FALSE(state.NeedsCommit());
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Tell the scheduler the frame finished.
+ state.NotifyBeginMainFrameStarted();
+ state.NotifyReadyToCommit();
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT);
+
+ // Commit.
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+ EXPECT_TRUE(state.active_tree_needs_first_draw());
+ EXPECT_TRUE(state.needs_redraw());
+
+ // Expect to do nothing until BeginImplFrame deadline
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // At BeginImplFrame deadline, draw.
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ state.DidDrawIfPossibleCompleted(DRAW_SUCCESS);
+ state.DidSwapBuffersComplete();
+
+ // Should be synchronized, no draw needed, no action needed.
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ EXPECT_FALSE(state.needs_redraw());
+}
+
+TEST(SchedulerStateMachineTest, TestFullCycleWithMainThreadLowLatencyMode) {
+ SchedulerSettings scheduler_settings;
+ scheduler_settings.main_thread_should_always_be_low_latency = true;
+ StateMachine state(scheduler_settings);
+ SET_UP_STATE(state)
+
+ // Start clean and set commit.
+ state.SetNeedsCommit();
+
+ // Begin the frame.
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_COMMIT_STATE(
+ SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_FALSE(state.NeedsCommit());
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Tell the scheduler the frame finished.
+ state.NotifyBeginMainFrameStarted();
+ state.NotifyReadyToCommit();
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT);
+
+ // Commit.
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+ EXPECT_TRUE(state.active_tree_needs_first_draw());
+ EXPECT_TRUE(state.needs_redraw());
+
+ // Now commit should wait for draw.
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_DRAW);
+
+ // Swap throttled. Do not draw.
+ state.DidSwapBuffers();
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.DidSwapBuffersComplete();
+
+ // Haven't draw since last commit, do not begin new main frame.
+ state.SetNeedsCommit();
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // At BeginImplFrame deadline, draw.
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ state.DidDrawIfPossibleCompleted(DRAW_SUCCESS);
+ state.DidSwapBuffersComplete();
+
+ // Now will be able to start main frame.
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ EXPECT_FALSE(state.needs_redraw());
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+}
+
+TEST(SchedulerStateMachineTest,
+ TestFullCycleWithMainThreadLowLatencyMode_ImplSidePaint) {
+ SchedulerSettings scheduler_settings;
+ scheduler_settings.main_thread_should_always_be_low_latency = true;
+ scheduler_settings.impl_side_painting = true;
+ StateMachine state(scheduler_settings);
+ SET_UP_STATE(state)
+
+ // Start clean and set commit.
+ state.SetNeedsCommit();
+
+ // Begin the frame.
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_COMMIT_STATE(
+ SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_FALSE(state.NeedsCommit());
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Tell the scheduler the frame finished.
+ state.NotifyBeginMainFrameStarted();
+ state.NotifyReadyToCommit();
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT);
+
+ // Commit.
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+
+ // Now commit should wait for activation.
+ EXPECT_COMMIT_STATE(
+ SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_ACTIVATION);
+
+ // No activation yet, so this commit is not drawn yet. Force to draw this
+ // frame, and still block BeginMainFrame.
+ state.SetNeedsRedraw(true);
+ state.SetNeedsCommit();
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Cannot BeginMainFrame yet since last commit is not yet activated and drawn.
+ state.OnBeginImplFrame();
+ EXPECT_COMMIT_STATE(
+ SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_ACTIVATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Now activate sync tree.
+ state.NotifyReadyToActivate();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_TRUE(state.active_tree_needs_first_draw());
+ EXPECT_TRUE(state.needs_redraw());
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_DRAW);
+
+ // Swap throttled. Do not draw.
+ state.DidSwapBuffers();
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.DidSwapBuffersComplete();
+
+ // Haven't draw since last commit, do not begin new main frame.
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // At BeginImplFrame deadline, draw. This draws unblocks BeginMainFrame.
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ state.DidDrawIfPossibleCompleted(DRAW_SUCCESS);
+ state.DidSwapBuffersComplete();
+
+ // Now will be able to start main frame.
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ EXPECT_FALSE(state.needs_redraw());
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+}
+
+TEST(SchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ SET_UP_STATE(state)
+
+ // Start clean and set commit.
+ state.SetNeedsCommit();
+
+ // Begin the frame.
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_COMMIT_STATE(
+ SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_FALSE(state.NeedsCommit());
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Request another commit while the commit is in flight.
+ state.SetNeedsCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Tell the scheduler the frame finished.
+ state.NotifyBeginMainFrameStarted();
+ state.NotifyReadyToCommit();
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT);
+
+ // First commit.
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+ EXPECT_TRUE(state.active_tree_needs_first_draw());
+ EXPECT_TRUE(state.needs_redraw());
+
+ // Expect to do nothing until BeginImplFrame deadline.
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // At BeginImplFrame deadline, draw.
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ state.DidDrawIfPossibleCompleted(DRAW_SUCCESS);
+ state.DidSwapBuffersComplete();
+
+ // Should be synchronized, no draw needed, no action needed.
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ EXPECT_FALSE(state.needs_redraw());
+
+ // Next BeginImplFrame should initiate second commit.
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+}
+
+TEST(SchedulerStateMachineTest, TestRequestCommitInvisible) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ state.SetCanStart();
+ state.UpdateState(state.NextAction());
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+ state.SetNeedsCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+}
+
+// See ThreadProxy::BeginMainFrame "EarlyOut_NotVisible" /
+// "EarlyOut_OutputSurfaceLost" cases.
+TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseInvisible) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ SET_UP_STATE(state)
+
+ // Start clean and set commit.
+ state.SetNeedsCommit();
+
+ // Begin the frame while visible.
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_COMMIT_STATE(
+ SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_FALSE(state.NeedsCommit());
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Become invisible and abort BeginMainFrame.
+ state.SetVisible(false);
+ state.BeginMainFrameAborted(CommitEarlyOutReason::ABORTED_NOT_VISIBLE);
+
+ // NeedsCommit should now be true again because we never actually did a
+ // commit.
+ EXPECT_TRUE(state.NeedsCommit());
+
+ // We should now be back in the idle state as if we never started the frame.
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // We shouldn't do anything on the BeginImplFrame deadline.
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Become visible again.
+ state.SetVisible(true);
+
+ // Although we have aborted on this frame and haven't cancelled the commit
+ // (i.e. need another), don't send another BeginMainFrame yet.
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_TRUE(state.NeedsCommit());
+
+ // Start a new frame.
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+
+ // We should be starting the commit now.
+ EXPECT_COMMIT_STATE(
+ SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+}
+
+// See ThreadProxy::BeginMainFrame "EarlyOut_NoUpdates" case.
+TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseCommitNotNeeded) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ state.SetCanStart();
+ state.UpdateState(state.NextAction());
+ state.DidCreateAndInitializeOutputSurface();
+ state.SetVisible(true);
+ state.SetCanDraw(true);
+
+ // Get into a begin frame / commit state.
+ state.SetNeedsCommit();
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_COMMIT_STATE(
+ SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ EXPECT_FALSE(state.NeedsCommit());
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE);
+
+ // Abort the commit, true means that the BeginMainFrame was sent but there
+ // was no work to do on the main thread.
+ state.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES);
+
+ // NeedsCommit should now be false because the commit was actually handled.
+ EXPECT_FALSE(state.NeedsCommit());
+
+ // Even though the commit was aborted, we still expect to draw the new frame.
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ state.DidSwapBuffersComplete();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Verify another commit doesn't start on another frame either.
+ EXPECT_FALSE(state.NeedsCommit());
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Verify another commit can start if requested, though.
+ state.SetNeedsCommit();
+ EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE);
+ state.OnBeginImplFrame();
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+}
+
+TEST(SchedulerStateMachineTest, TestFirstContextCreation) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ state.SetCanStart();
+ state.SetVisible(true);
+ state.SetCanDraw(true);
+
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Check that the first init does not SetNeedsCommit.
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Check that a needs commit initiates a BeginMainFrame.
+ state.SetNeedsCommit();
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+}
+
+TEST(SchedulerStateMachineTest, TestContextLostWhenCompletelyIdle) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ SET_UP_STATE(state)
+
+ EXPECT_NE(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
+ state.NextAction());
+ state.DidLoseOutputSurface();
+
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ state.UpdateState(state.NextAction());
+
+ // Once context recreation begins, nothing should happen.
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Recreate the context.
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+
+ // When the context is recreated, we should begin a commit.
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+}
+
+TEST(SchedulerStateMachineTest,
+ TestContextLostWhenIdleAndCommitRequestedWhileRecreating) {
+ SchedulerSettings default_scheduler_settings;
+ // We use impl side painting because it's the more complicated version.
+ default_scheduler_settings.impl_side_painting = true;
+ StateMachine state(default_scheduler_settings);
+ SET_UP_STATE(state)
+
+ EXPECT_NE(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
+ state.NextAction());
+ state.DidLoseOutputSurface();
+ EXPECT_EQ(state.output_surface_state(),
+ SchedulerStateMachine::OUTPUT_SURFACE_LOST);
+
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Once context recreation begins, nothing should happen.
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // While context is recreating, commits shouldn't begin.
+ state.SetNeedsCommit();
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Recreate the context
+ state.DidCreateAndInitializeOutputSurface();
+ EXPECT_EQ(state.output_surface_state(),
+ SchedulerStateMachine::OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT);
+ EXPECT_FALSE(state.RedrawPending());
+
+ // When the context is recreated, we wait until the next BeginImplFrame
+ // before starting.
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // When the BeginFrame comes in we should begin a commit
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_COMMIT_STATE(
+ SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+
+ // Until that commit finishes, we shouldn't be drawing or animate.
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Finish the commit, which should make the surface active.
+ state.NotifyBeginMainFrameStarted();
+ state.NotifyReadyToCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+ EXPECT_EQ(state.output_surface_state(),
+ SchedulerStateMachine::OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION);
+ state.NotifyReadyToActivate();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_EQ(state.output_surface_state(),
+ SchedulerStateMachine::OUTPUT_SURFACE_ACTIVE);
+
+ // Finishing the first commit after initializing an output surface should
+ // automatically cause a redraw.
+ EXPECT_TRUE(state.RedrawPending());
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_FALSE(state.RedrawPending());
+
+ // Next frame as no work to do.
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Once the context is recreated, whether we draw should be based on
+ // SetCanDraw if waiting on first draw after activate.
+ state.SetNeedsRedraw(true);
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.SetCanDraw(false);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE);
+ state.SetCanDraw(true);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Once the context is recreated, whether we draw should be based on
+ // SetCanDraw if waiting on first draw after activate.
+ state.SetNeedsRedraw(true);
+ state.SetNeedsCommit();
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ // Activate so we need the first draw
+ 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);
+ EXPECT_TRUE(state.active_tree_needs_first_draw());
+ EXPECT_TRUE(state.needs_redraw());
+
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.SetCanDraw(false);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
+ state.SetCanDraw(true);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+}
+
+TEST(SchedulerStateMachineTest, TestContextLostWhileCommitInProgress) {
+ SchedulerSettings scheduler_settings;
+ StateMachine state(scheduler_settings);
+ SET_UP_STATE(state)
+
+ // Get a commit in flight.
+ state.SetNeedsCommit();
+
+ // Set damage and expect a draw.
+ state.SetNeedsRedraw(true);
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ state.DidSwapBuffersComplete();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Cause a lost context while the BeginMainFrame is in flight.
+ state.DidLoseOutputSurface();
+
+ // Ask for another draw. Expect nothing happens.
+ state.SetNeedsRedraw(true);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE);
+
+ // Finish the frame, and commit.
+ state.NotifyBeginMainFrameStarted();
+ state.NotifyReadyToCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+
+ // We will abort the draw when the output surface is lost if we are
+ // waiting for the first draw to unblock the main thread.
+ EXPECT_TRUE(state.active_tree_needs_first_draw());
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
+
+ // Expect to begin context recreation only in BEGIN_IMPL_FRAME_STATE_IDLE
+ EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+
+ state.OnBeginImplFrame();
+ EXPECT_IMPL_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE);
+
+ state.OnBeginImplFrameDeadlinePending();
+ EXPECT_IMPL_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE);
+
+ state.OnBeginImplFrameDeadline();
+ EXPECT_IMPL_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE);
+}
+
+TEST(SchedulerStateMachineTest,
+ TestContextLostWhileCommitInProgressAndAnotherCommitRequested) {
+ SchedulerSettings scheduler_settings;
+ StateMachine state(scheduler_settings);
+ SET_UP_STATE(state)
+
+ // Get a commit in flight.
+ state.SetNeedsCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Set damage and expect a draw.
+ state.SetNeedsRedraw(true);
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ state.DidSwapBuffersComplete();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Cause a lost context while the BeginMainFrame is in flight.
+ state.DidLoseOutputSurface();
+
+ // Ask for another draw and also set needs commit. Expect nothing happens.
+ state.SetNeedsRedraw(true);
+ state.SetNeedsCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Finish the frame, and commit.
+ state.NotifyBeginMainFrameStarted();
+ state.NotifyReadyToCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+ EXPECT_TRUE(state.active_tree_needs_first_draw());
+
+ // Because the output surface is missing, we expect the draw to abort.
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
+
+ // Expect to begin context recreation only in BEGIN_IMPL_FRAME_STATE_IDLE
+ EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+
+ state.OnBeginImplFrame();
+ EXPECT_IMPL_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE);
+
+ state.OnBeginImplFrameDeadlinePending();
+ EXPECT_IMPL_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE);
+
+ state.OnBeginImplFrameDeadline();
+ EXPECT_IMPL_FRAME_STATE(
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE);
+
+ state.OnBeginImplFrameIdle();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+
+ // After we get a new output surface, the commit flow should start.
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+ 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);
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ state.DidSwapBuffersComplete();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+}
+
+TEST(SchedulerStateMachineTest, DontDrawBeforeCommitAfterLostOutputSurface) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ SET_UP_STATE(state)
+
+ state.SetNeedsRedraw(true);
+
+ // Cause a lost output surface, and restore it.
+ state.DidLoseOutputSurface();
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+ state.UpdateState(state.NextAction());
+ state.DidCreateAndInitializeOutputSurface();
+
+ EXPECT_FALSE(state.RedrawPending());
+ state.OnBeginImplFrame();
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+}
+
+TEST(SchedulerStateMachineTest,
+ TestPendingActivationsShouldBeForcedAfterLostOutputSurface) {
+ SchedulerSettings settings;
+ settings.impl_side_painting = true;
+ StateMachine state(settings);
+ SET_UP_STATE(state)
+
+ state.SetCommitState(
+ SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+
+ // Cause a lost context.
+ state.DidLoseOutputSurface();
+
+ state.NotifyBeginMainFrameStarted();
+ state.NotifyReadyToCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+
+ EXPECT_TRUE(state.PendingActivationsShouldBeForced());
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE);
+
+ EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
+}
+
+TEST(SchedulerStateMachineTest, TestNoBeginMainFrameWhenInvisible) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ state.SetCanStart();
+ state.UpdateState(state.NextAction());
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+ state.SetVisible(false);
+ state.SetNeedsCommit();
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE);
+}
+
+TEST(SchedulerStateMachineTest, TestFinishCommitWhenCommitInProgress) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ state.SetCanStart();
+ state.UpdateState(state.NextAction());
+ state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
+ state.SetVisible(false);
+ state.SetCommitState(
+ SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
+ state.SetNeedsCommit();
+
+ state.NotifyBeginMainFrameStarted();
+ state.NotifyReadyToCommit();
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT);
+ state.UpdateState(state.NextAction());
+
+ EXPECT_TRUE(state.active_tree_needs_first_draw());
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
+}
+
+TEST(SchedulerStateMachineTest, TestInitialActionsWhenContextLost) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ SET_UP_STATE(state)
+ state.SetNeedsCommit();
+ state.DidLoseOutputSurface();
+
+ // When we are visible, we normally want to begin output surface creation
+ // as soon as possible.
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
+
+ state.DidCreateAndInitializeOutputSurface();
+ EXPECT_EQ(state.output_surface_state(),
+ SchedulerStateMachine::OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT);
+
+ // We should not send a BeginMainFrame when we are invisible, even if we've
+ // lost the output surface and are trying to get the first commit, since the
+ // main thread will just abort anyway.
+ state.SetVisible(false);
+ EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE);
+}
+
+TEST(SchedulerStateMachineTest, ReportIfNotDrawing) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ SET_UP_STATE(state)
+ EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
+
+ state.SetCanDraw(false);
+ state.SetVisible(true);
+ EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
+
+ state.SetCanDraw(true);
+ state.SetVisible(false);
+ EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
+
+ state.SetCanDraw(false);
+ state.SetVisible(false);
+ EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
+
+ state.SetCanDraw(true);
+ state.SetVisible(true);
+ EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
+}
+
+TEST(SchedulerStateMachineTest,
+ TestTriggerDeadlineImmediatelyAfterAbortedCommit) {
+ SchedulerSettings settings;
+ settings.impl_side_painting = true;
+ StateMachine state(settings);
+ SET_UP_STATE(state)
+
+ // This test mirrors what happens during the first frame of a scroll gesture.
+ // First we get the input event and a BeginFrame.
+ state.OnBeginImplFrame();
+
+ // As a response the compositor requests a redraw and a commit to tell the
+ // main thread about the new scroll offset.
+ state.SetNeedsRedraw(true);
+ state.SetNeedsCommit();
+
+ // We should start the commit normally.
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Since only the scroll offset changed, the main thread will abort the
+ // commit.
+ state.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES);
+
+ // Since the commit was aborted, we should draw right away instead of waiting
+ // for the deadline.
+ EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
+}
+
+void FinishPreviousCommitAndDrawWithoutExitingDeadline(
+ StateMachine* state_ptr) {
+ // Gross, but allows us to use macros below.
+ StateMachine& state = *state_ptr;
+
+ state.NotifyBeginMainFrameStarted();
+ state.NotifyReadyToCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+ 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_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+}
+
+TEST(SchedulerStateMachineTest, TestImplLatencyTakesPriority) {
+ SchedulerSettings settings;
+ settings.impl_side_painting = true;
+ StateMachine state(settings);
+ SET_UP_STATE(state)
+
+ // This test ensures that impl-draws are prioritized over main thread updates
+ // in prefer impl latency mode.
+ state.SetNeedsRedraw(true);
+ state.SetNeedsCommit();
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Verify the deadline is not triggered early until we enter
+ // prefer impl latency mode.
+ EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
+ state.SetImplLatencyTakesPriority(true);
+ EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
+
+ // Trigger the deadline.
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+ state.DidSwapBuffers();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.DidSwapBuffersComplete();
+
+ // Request a new commit and finish the previous one.
+ state.SetNeedsCommit();
+ FinishPreviousCommitAndDrawWithoutExitingDeadline(&state);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.DidSwapBuffersComplete();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Finish the previous commit and draw it.
+ FinishPreviousCommitAndDrawWithoutExitingDeadline(&state);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ // Verify we do not send another BeginMainFrame if was are swap throttled
+ // and did not just swap.
+ state.SetNeedsCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+}
+
+TEST(SchedulerStateMachineTest,
+ TestTriggerDeadlineImmediatelyOnLostOutputSurface) {
+ SchedulerSettings default_scheduler_settings;
+ StateMachine state(default_scheduler_settings);
+ SET_UP_STATE(state)
+
+ state.SetNeedsCommit();
+
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
+
+ state.DidLoseOutputSurface();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ // The deadline should be triggered immediately when output surface is lost.
+ EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
+}
+
+TEST(SchedulerStateMachineTest, TestSetNeedsAnimate) {
+ SchedulerSettings settings;
+ settings.impl_side_painting = true;
+ StateMachine state(settings);
+ SET_UP_STATE(state)
+
+ // Test requesting an animation that, when run, causes us to draw.
+ state.SetNeedsAnimate();
+ EXPECT_TRUE(state.BeginFrameNeeded());
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+
+ state.OnBeginImplFrameDeadlinePending();
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+}
+
+TEST(SchedulerStateMachineTest, TestAnimateBeforeCommit) {
+ SchedulerSettings settings;
+ settings.impl_side_painting = true;
+ StateMachine state(settings);
+ SET_UP_STATE(state)
+
+ // Check that animations are updated before we start a commit.
+ state.SetNeedsAnimate();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.SetNeedsCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_TRUE(state.BeginFrameNeeded());
+
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+
+ state.OnBeginImplFrameDeadlinePending();
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+}
+
+TEST(SchedulerStateMachineTest, TestAnimateAfterCommitBeforeDraw) {
+ SchedulerSettings settings;
+ settings.impl_side_painting = true;
+ StateMachine state(settings);
+ SET_UP_STATE(state)
+
+ // Check that animations are updated before we start a commit.
+ state.SetNeedsAnimate();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ state.SetNeedsCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+ EXPECT_TRUE(state.BeginFrameNeeded());
+
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+
+ state.NotifyBeginMainFrameStarted();
+ state.NotifyReadyToCommit();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
+
+ state.OnBeginImplFrameDeadlinePending();
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+}
+
+TEST(SchedulerStateMachineTest, TestSetNeedsAnimateAfterAnimate) {
+ SchedulerSettings settings;
+ settings.impl_side_painting = true;
+ StateMachine state(settings);
+ SET_UP_STATE(state)
+
+ // Test requesting an animation after we have already animated during this
+ // frame.
+ state.SetNeedsRedraw(true);
+ EXPECT_TRUE(state.BeginFrameNeeded());
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
+
+ state.SetNeedsAnimate();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
+}
+
+TEST(SchedulerStateMachineTest, TestForwardBeginFramesToChildren) {
+ SchedulerSettings settings;
+ StateMachine state(settings);
+ SET_UP_STATE(state)
+
+ EXPECT_FALSE(state.BeginFrameNeeded());
+ state.SetChildrenNeedBeginFrames(true);
+ EXPECT_TRUE(state.BeginFrameNeeded());
+}
+
+TEST(SchedulerStateMachineTest, TestDeferCommit) {
+ SchedulerSettings settings;
+ StateMachine state(settings);
+ SET_UP_STATE(state)
+
+ state.SetDeferCommits(true);
+
+ state.SetNeedsCommit();
+ EXPECT_TRUE(state.BeginFrameNeeded());
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ state.OnBeginImplFrameDeadline();
+ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
+
+ state.SetDeferCommits(false);
+ state.OnBeginImplFrame();
+ EXPECT_ACTION_UPDATE_STATE(
+ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
+}
+
+TEST(SchedulerStateMachineTest, EarlyOutCommitWantsProactiveBeginFrame) {
+ SchedulerSettings settings;
+ StateMachine state(settings);
+ SET_UP_STATE(state);
+
+ EXPECT_FALSE(state.ProactiveBeginFrameWanted());
+ bool commit_has_no_updates = true;
+ state.UpdateStateOnCommit(commit_has_no_updates);
+ EXPECT_TRUE(state.ProactiveBeginFrameWanted());
+ state.OnBeginImplFrame();
+ EXPECT_FALSE(state.ProactiveBeginFrameWanted());
+}
+
+} // namespace
+} // namespace cc
« no previous file with comments | « cc/scheduler/scheduler_state_machine.cc ('k') | cc/scheduler/scheduler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698