summaryrefslogtreecommitdiffstats
path: root/chromium/cc/scheduler/scheduler_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/cc/scheduler/scheduler_unittest.cc')
-rw-r--r--chromium/cc/scheduler/scheduler_unittest.cc1931
1 files changed, 1282 insertions, 649 deletions
diff --git a/chromium/cc/scheduler/scheduler_unittest.cc b/chromium/cc/scheduler/scheduler_unittest.cc
index 6f5eb2c2dcd..7d5a163dacc 100644
--- a/chromium/cc/scheduler/scheduler_unittest.cc
+++ b/chromium/cc/scheduler/scheduler_unittest.cc
@@ -11,43 +11,78 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/time/time.h"
+#include "cc/test/begin_frame_args_test.h"
+#include "cc/test/ordered_simple_task_runner.h"
#include "cc/test/scheduler_test_common.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
- EXPECT_EQ(expected_num_actions, client.num_actions_()); \
- ASSERT_LT(action_index, client.num_actions_()); \
do { \
- EXPECT_STREQ(action, client.Action(action_index)); \
+ EXPECT_EQ(expected_num_actions, client.num_actions_()); \
+ if (action_index >= 0) { \
+ ASSERT_LT(action_index, client.num_actions_()) << scheduler; \
+ EXPECT_STREQ(action, client.Action(action_index)); \
+ } \
for (int i = expected_num_actions; i < client.num_actions_(); ++i) \
- ADD_FAILURE() << "Unexpected action: " << client.Action(i) << \
- " with state:\n" << client.StateForAction(action_index); \
+ ADD_FAILURE() << "Unexpected action: " << client.Action(i) \
+ << " with state:\n" << client.StateForAction(i); \
} while (false)
+#define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0)
+
#define EXPECT_SINGLE_ACTION(action, client) \
EXPECT_ACTION(action, client, 0, 1)
namespace cc {
namespace {
-void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler) {
- scheduler->DidCreateAndInitializeOutputSurface();
- scheduler->SetNeedsCommit();
- scheduler->FinishCommit();
- // Go through the motions to draw the commit.
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
- // We need another BeginImplFrame so Scheduler calls
- // SetNeedsBeginImplFrame(false).
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
-}
+class FakeSchedulerClient;
+
+void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler,
+ FakeSchedulerClient* client);
+
+class TestScheduler : public Scheduler {
+ public:
+ static scoped_ptr<TestScheduler> Create(
+ SchedulerClient* client,
+ const SchedulerSettings& scheduler_settings,
+ int layer_tree_host_id,
+ const scoped_refptr<base::SingleThreadTaskRunner>& impl_task_runner) {
+ return make_scoped_ptr(new TestScheduler(
+ client, scheduler_settings, layer_tree_host_id, impl_task_runner));
+ }
+
+ virtual ~TestScheduler() {}
+
+ bool IsBeginRetroFrameArgsEmpty() const {
+ return begin_retro_frame_args_.empty();
+ }
+
+ bool IsSyntheticBeginFrameSourceActive() const {
+ return synthetic_begin_frame_source_->IsActive();
+ }
+
+ private:
+ TestScheduler(
+ SchedulerClient* client,
+ const SchedulerSettings& scheduler_settings,
+ int layer_tree_host_id,
+ const scoped_refptr<base::SingleThreadTaskRunner> & impl_task_runner)
+ : Scheduler(client,
+ scheduler_settings,
+ layer_tree_host_id,
+ impl_task_runner) {
+ }
+};
class FakeSchedulerClient : public SchedulerClient {
public:
FakeSchedulerClient()
- : needs_begin_impl_frame_(false) {
+ : needs_begin_frame_(false),
+ automatic_swap_ack_(true),
+ swap_contains_incomplete_tile_(false),
+ redraw_will_happen_if_update_visible_tiles_happens_(false) {
Reset();
}
@@ -60,8 +95,9 @@ class FakeSchedulerClient : public SchedulerClient {
log_anticipated_draw_time_change_ = false;
}
- Scheduler* CreateScheduler(const SchedulerSettings& settings) {
- scheduler_ = Scheduler::Create(this, settings, 0);
+ TestScheduler* CreateScheduler(const SchedulerSettings& settings) {
+ task_runner_ = new OrderedSimpleTaskRunner;
+ scheduler_ = TestScheduler::Create(this, settings, 0, task_runner_);
return scheduler_.get();
}
@@ -70,11 +106,16 @@ class FakeSchedulerClient : public SchedulerClient {
void set_log_anticipated_draw_time_change(bool log) {
log_anticipated_draw_time_change_ = log;
}
- bool needs_begin_impl_frame() { return needs_begin_impl_frame_; }
+ bool needs_begin_frame() { return needs_begin_frame_; }
int num_draws() const { return num_draws_; }
int num_actions_() const { return static_cast<int>(actions_.size()); }
const char* Action(int i) const { return actions_[i]; }
base::Value& StateForAction(int i) const { return *states_[i]; }
+ base::TimeTicks posted_begin_impl_frame_deadline() const {
+ return posted_begin_impl_frame_deadline_;
+ }
+
+ OrderedSimpleTaskRunner& task_runner() { return *task_runner_; }
int ActionIndex(const char* action) const {
for (size_t i = 0; i < actions_.size(); i++)
@@ -83,6 +124,10 @@ class FakeSchedulerClient : public SchedulerClient {
return -1;
}
+ void SetSwapContainsIncompleteTile(bool contain) {
+ swap_contains_incomplete_tile_ = contain;
+ }
+
bool HasAction(const char* action) const {
return ActionIndex(action) >= 0;
}
@@ -93,67 +138,78 @@ class FakeSchedulerClient : public SchedulerClient {
void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
}
-
+ void SetAutomaticSwapAck(bool automatic_swap_ack) {
+ automatic_swap_ack_ = automatic_swap_ack;
+ }
+ void SetRedrawWillHappenIfUpdateVisibleTilesHappens(bool redraw) {
+ redraw_will_happen_if_update_visible_tiles_happens_ = redraw;
+ }
// SchedulerClient implementation.
- virtual void SetNeedsBeginImplFrame(bool enable) OVERRIDE {
- actions_.push_back("SetNeedsBeginImplFrame");
- states_.push_back(scheduler_->StateAsValue().release());
- needs_begin_impl_frame_ = enable;
+ virtual void SetNeedsBeginFrame(bool enable) OVERRIDE {
+ actions_.push_back("SetNeedsBeginFrame");
+ states_.push_back(scheduler_->AsValue().release());
+ needs_begin_frame_ = enable;
+ }
+ virtual void WillBeginImplFrame(const BeginFrameArgs& args) OVERRIDE {
+ actions_.push_back("WillBeginImplFrame");
+ states_.push_back(scheduler_->AsValue().release());
}
virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {
actions_.push_back("ScheduledActionSendBeginMainFrame");
- states_.push_back(scheduler_->StateAsValue().release());
+ states_.push_back(scheduler_->AsValue().release());
}
- virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
- OVERRIDE {
+ virtual void ScheduledActionAnimate() OVERRIDE {
+ actions_.push_back("ScheduledActionAnimate");
+ states_.push_back(scheduler_->AsValue().release());
+ }
+ virtual DrawResult ScheduledActionDrawAndSwapIfPossible() OVERRIDE {
actions_.push_back("ScheduledActionDrawAndSwapIfPossible");
- states_.push_back(scheduler_->StateAsValue().release());
+ states_.push_back(scheduler_->AsValue().release());
num_draws_++;
- bool did_readback = false;
- return DrawSwapReadbackResult(
- draw_will_happen_,
- draw_will_happen_ && swap_will_happen_if_draw_happens_,
- did_readback);
+ DrawResult result =
+ draw_will_happen_ ? DRAW_SUCCESS : DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
+ bool swap_will_happen =
+ draw_will_happen_ && swap_will_happen_if_draw_happens_;
+ if (swap_will_happen) {
+ scheduler_->DidSwapBuffers();
+ if (swap_contains_incomplete_tile_) {
+ scheduler_->SetSwapUsedIncompleteTile(true);
+ swap_contains_incomplete_tile_ = false;
+ } else {
+ scheduler_->SetSwapUsedIncompleteTile(false);
+ }
+
+ if (automatic_swap_ack_)
+ scheduler_->DidSwapBuffersComplete();
+ }
+ return result;
}
- virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
+ virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE {
actions_.push_back("ScheduledActionDrawAndSwapForced");
- states_.push_back(scheduler_->StateAsValue().release());
- bool did_draw = true;
- bool did_swap = swap_will_happen_if_draw_happens_;
- bool did_readback = false;
- return DrawSwapReadbackResult(did_draw, did_swap, did_readback);
- }
- virtual DrawSwapReadbackResult ScheduledActionDrawAndReadback() OVERRIDE {
- actions_.push_back("ScheduledActionDrawAndReadback");
- states_.push_back(scheduler_->StateAsValue().release());
- bool did_draw = true;
- bool did_swap = false;
- bool did_readback = true;
- return DrawSwapReadbackResult(did_draw, did_swap, did_readback);
+ states_.push_back(scheduler_->AsValue().release());
+ return DRAW_SUCCESS;
}
virtual void ScheduledActionCommit() OVERRIDE {
actions_.push_back("ScheduledActionCommit");
- states_.push_back(scheduler_->StateAsValue().release());
+ states_.push_back(scheduler_->AsValue().release());
}
virtual void ScheduledActionUpdateVisibleTiles() OVERRIDE {
actions_.push_back("ScheduledActionUpdateVisibleTiles");
- states_.push_back(scheduler_->StateAsValue().release());
+ states_.push_back(scheduler_->AsValue().release());
+ if (redraw_will_happen_if_update_visible_tiles_happens_)
+ scheduler_->SetNeedsRedraw();
}
virtual void ScheduledActionActivatePendingTree() OVERRIDE {
actions_.push_back("ScheduledActionActivatePendingTree");
- states_.push_back(scheduler_->StateAsValue().release());
+ states_.push_back(scheduler_->AsValue().release());
}
virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {
actions_.push_back("ScheduledActionBeginOutputSurfaceCreation");
- states_.push_back(scheduler_->StateAsValue().release());
- }
- virtual void ScheduledActionAcquireLayerTexturesForMainThread() OVERRIDE {
- actions_.push_back("ScheduledActionAcquireLayerTexturesForMainThread");
- states_.push_back(scheduler_->StateAsValue().release());
+ states_.push_back(scheduler_->AsValue().release());
}
virtual void ScheduledActionManageTiles() OVERRIDE {
actions_.push_back("ScheduledActionManageTiles");
- states_.push_back(scheduler_->StateAsValue().release());
+ states_.push_back(scheduler_->AsValue().release());
}
virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {
if (log_anticipated_draw_time_change_)
@@ -169,29 +225,64 @@ class FakeSchedulerClient : public SchedulerClient {
return base::TimeDelta();
}
- virtual void PostBeginImplFrameDeadline(const base::Closure& closure,
- base::TimeTicks deadline) OVERRIDE {
- actions_.push_back("PostBeginImplFrameDeadlineTask");
- states_.push_back(scheduler_->StateAsValue().release());
- }
-
virtual void DidBeginImplFrameDeadline() OVERRIDE {}
protected:
- bool needs_begin_impl_frame_;
+ bool needs_begin_frame_;
bool draw_will_happen_;
bool swap_will_happen_if_draw_happens_;
+ bool automatic_swap_ack_;
int num_draws_;
bool log_anticipated_draw_time_change_;
+ bool swap_contains_incomplete_tile_;
+ bool redraw_will_happen_if_update_visible_tiles_happens_;
+ base::TimeTicks posted_begin_impl_frame_deadline_;
std::vector<const char*> actions_;
ScopedVector<base::Value> states_;
- scoped_ptr<Scheduler> scheduler_;
+ scoped_ptr<TestScheduler> scheduler_;
+ scoped_refptr<OrderedSimpleTaskRunner> task_runner_;
};
+void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler,
+ FakeSchedulerClient* client) {
+ bool client_initiates_begin_frame =
+ scheduler->settings().begin_frame_scheduling_enabled &&
+ scheduler->settings().throttle_frame_production;
+
+ scheduler->DidCreateAndInitializeOutputSurface();
+ scheduler->SetNeedsCommit();
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
+ if (scheduler->settings().impl_side_painting)
+ scheduler->NotifyReadyToActivate();
+ // Go through the motions to draw the commit.
+ if (client_initiates_begin_frame)
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ else
+ client->task_runner().RunPendingTasks(); // Run posted BeginFrame.
+
+ // Run the posted deadline task.
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ client->task_runner().RunPendingTasks();
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+
+ // We need another BeginImplFrame so Scheduler calls
+ // SetNeedsBeginFrame(false).
+ if (client_initiates_begin_frame)
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ else
+ client->task_runner().RunPendingTasks(); // Run posted BeginFrame.
+
+ // Run the posted deadline task.
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ client->task_runner().RunPendingTasks();
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+}
+
TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) {
FakeSchedulerClient client;
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
+ TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -199,127 +290,99 @@ TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) {
EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
client.Reset();
scheduler->DidCreateAndInitializeOutputSurface();
- EXPECT_EQ(0, client.num_actions_());
+ EXPECT_NO_ACTION(client);
}
-void RequestCommit(bool deadline_scheduling_enabled) {
+TEST(SchedulerTest, RequestCommit) {
FakeSchedulerClient client;
SchedulerSettings scheduler_settings;
- scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
- Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
- InitializeOutputSurfaceAndFirstCommit(scheduler);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
// SetNeedsCommit should begin the frame on the next BeginImplFrame.
client.Reset();
scheduler->SetNeedsCommit();
- EXPECT_TRUE(client.needs_begin_impl_frame());
- if (deadline_scheduling_enabled) {
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- } else {
- EXPECT_EQ(client.num_actions_(), 2);
- EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
- EXPECT_TRUE(client.HasAction("SetNeedsBeginImplFrame"));
- }
+ EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- if (deadline_scheduling_enabled) {
- EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
- EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
- } else {
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
- }
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
client.Reset();
- // If we don't swap on the deadline, we need to request another
- // BeginImplFrame.
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ // If we don't swap on the deadline, we wait for the next BeginFrame.
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_NO_ACTION(client);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
client.Reset();
- // FinishCommit should commit
- scheduler->FinishCommit();
+ // NotifyReadyToCommit should trigger the commit.
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
client.Reset();
// BeginImplFrame should prepare the draw.
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
client.Reset();
// BeginImplFrame deadline should draw.
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
client.Reset();
- // The following BeginImplFrame deadline should SetNeedsBeginImplFrame(false)
+ // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
// to avoid excessive toggles.
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- EXPECT_FALSE(client.needs_begin_impl_frame());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
+ EXPECT_FALSE(client.needs_begin_frame());
client.Reset();
}
-TEST(SchedulerTest, RequestCommit) {
- bool deadline_scheduling_enabled = false;
- RequestCommit(deadline_scheduling_enabled);
-}
-
-TEST(SchedulerTest, RequestCommit_Deadline) {
- bool deadline_scheduling_enabled = true;
- RequestCommit(deadline_scheduling_enabled);
-}
-
-void RequestCommitAfterBeginMainFrameSent(
- bool deadline_scheduling_enabled) {
+TEST(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
FakeSchedulerClient client;
SchedulerSettings scheduler_settings;
- scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
- Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
- InitializeOutputSurfaceAndFirstCommit(scheduler);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
client.Reset();
// SetNeedsCommit should begin the frame.
scheduler->SetNeedsCommit();
- if (deadline_scheduling_enabled) {
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- } else {
- EXPECT_EQ(client.num_actions_(), 2);
- EXPECT_TRUE(client.HasAction("SetNeedsBeginImplFrame"));
- EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
- }
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- if (deadline_scheduling_enabled) {
- EXPECT_EQ(client.num_actions_(), 2);
- EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
- EXPECT_TRUE(client.HasAction("PostBeginImplFrameDeadlineTask"));
- } else {
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
- }
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
client.Reset();
// Now SetNeedsCommit again. Calling here means we need a second commit.
@@ -328,358 +391,54 @@ void RequestCommitAfterBeginMainFrameSent(
client.Reset();
// Finish the first commit.
- scheduler->FinishCommit();
- EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
- EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
- client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- if (deadline_scheduling_enabled) {
- EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
- } else {
- EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 3);
- EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 3);
- EXPECT_ACTION("SetNeedsBeginImplFrame", client, 2, 3);
- }
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
+ EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ client.Reset();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
// Because we just swapped, the Scheduler should also request the next
// BeginImplFrame from the OutputSurface.
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
client.Reset();
-
// Since another commit is needed, the next BeginImplFrame should initiate
// the second commit.
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- if (deadline_scheduling_enabled) {
- EXPECT_EQ(client.num_actions_(), 2);
- EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
- EXPECT_TRUE(client.HasAction("PostBeginImplFrameDeadlineTask"));
- } else {
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
- }
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
client.Reset();
// Finishing the commit before the deadline should post a new deadline task
// to trigger the deadline early.
- scheduler->FinishCommit();
- EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
- EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
+ EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
client.Reset();
// On the next BeginImplFrame, verify we go back to a quiescent state and
// no longer request BeginImplFrames.
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_FALSE(client.needs_begin_impl_frame());
- client.Reset();
-}
-
-TEST(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
- bool deadline_scheduling_enabled = false;
- RequestCommitAfterBeginMainFrameSent(deadline_scheduling_enabled);
-}
-
-TEST(SchedulerTest, RequestCommitAfterBeginMainFrameSent_Deadline) {
- bool deadline_scheduling_enabled = true;
- RequestCommitAfterBeginMainFrameSent(deadline_scheduling_enabled);
-}
-
-void TextureAcquisitionCausesCommitInsteadOfDraw(
- bool deadline_scheduling_enabled) {
- FakeSchedulerClient client;
- SchedulerSettings scheduler_settings;
- scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
- Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
- scheduler->SetCanStart();
- scheduler->SetVisible(true);
- scheduler->SetCanDraw(true);
- EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
-
- InitializeOutputSurfaceAndFirstCommit(scheduler);
- client.Reset();
- scheduler->SetNeedsRedraw();
- EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- EXPECT_TRUE(client.needs_begin_impl_frame());
-
- client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
- client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
- EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
-
- client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
- client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_FALSE(client.needs_begin_impl_frame());
-
- client.Reset();
- scheduler->SetMainThreadNeedsLayerTextures();
- EXPECT_SINGLE_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
- client);
-
- // We should request a BeginImplFrame in anticipation of a draw.
- client.Reset();
- scheduler->SetNeedsRedraw();
- EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- EXPECT_TRUE(client.needs_begin_impl_frame());
-
- // No draw happens since the textures are acquired by the main thread.
- client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_FALSE(client.needs_begin_frame());
client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
-
- client.Reset();
- scheduler->SetNeedsCommit();
- if (deadline_scheduling_enabled) {
- EXPECT_EQ(0, client.num_actions_());
- } else {
- EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client);
- }
-
- client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- if (deadline_scheduling_enabled) {
- EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
- EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
- } else {
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
- }
-
- // Commit will release the texture.
- client.Reset();
- scheduler->FinishCommit();
- EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
- EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
- EXPECT_TRUE(scheduler->RedrawPending());
-
- // Now we can draw again after the commit happens.
- client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
- EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
-
- // Make sure we stop requesting BeginImplFrames if we don't swap.
- client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
- client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- EXPECT_FALSE(client.needs_begin_impl_frame());
-}
-
-TEST(SchedulerTest, TextureAcquisitionCausesCommitInsteadOfDraw) {
- bool deadline_scheduling_enabled = false;
- TextureAcquisitionCausesCommitInsteadOfDraw(deadline_scheduling_enabled);
-}
-
-TEST(SchedulerTest, TextureAcquisitionCausesCommitInsteadOfDraw_Deadline) {
- bool deadline_scheduling_enabled = true;
- TextureAcquisitionCausesCommitInsteadOfDraw(deadline_scheduling_enabled);
-}
-
-void TextureAcquisitionCollision(bool deadline_scheduling_enabled) {
- FakeSchedulerClient client;
- SchedulerSettings scheduler_settings;
- scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
- Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
- scheduler->SetCanStart();
- scheduler->SetVisible(true);
- scheduler->SetCanDraw(true);
-
- EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
- InitializeOutputSurfaceAndFirstCommit(scheduler);
-
- client.Reset();
- scheduler->SetNeedsCommit();
-if (deadline_scheduling_enabled) {
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- } else {
- EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
- }
-
- client.Reset();
- scheduler->SetMainThreadNeedsLayerTextures();
- EXPECT_SINGLE_ACTION(
- "ScheduledActionAcquireLayerTexturesForMainThread", client);
-
- client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- if (deadline_scheduling_enabled) {
- EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
- EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
- } else {
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
- }
-
- client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
-
- // Although the compositor cannot draw because textures are locked by main
- // thread, we continue requesting SetNeedsBeginImplFrame in anticipation of
- // the unlock.
- EXPECT_TRUE(client.needs_begin_impl_frame());
-
- // Trigger the commit
- scheduler->FinishCommit();
- EXPECT_TRUE(client.needs_begin_impl_frame());
-
- // Between commit and draw, texture acquisition for main thread delayed,
- // and main thread blocks.
- client.Reset();
- scheduler->SetMainThreadNeedsLayerTextures();
- EXPECT_EQ(0, client.num_actions_());
-
- // No implicit commit is expected.
- client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
-
- client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 3);
- EXPECT_ACTION(
- "ScheduledActionAcquireLayerTexturesForMainThread", client, 1, 3);
- EXPECT_ACTION("SetNeedsBeginImplFrame", client, 2, 3);
- EXPECT_TRUE(client.needs_begin_impl_frame());
-
- // The compositor should not draw because textures are locked by main
- // thread.
- client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
- client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- EXPECT_FALSE(client.needs_begin_impl_frame());
-
- // The impl thread need an explicit commit from the main thread to lock
- // the textures.
- client.Reset();
- scheduler->SetNeedsCommit();
- if (deadline_scheduling_enabled) {
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- } else {
- EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
- }
- EXPECT_TRUE(client.needs_begin_impl_frame());
-
- client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- if (deadline_scheduling_enabled) {
- EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
- EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
- } else {
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
- }
- client.Reset();
-
- // Trigger the commit, which will trigger the deadline task early.
- scheduler->FinishCommit();
- EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
- EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
- EXPECT_TRUE(client.needs_begin_impl_frame());
- client.Reset();
-
- // Verify we draw on the next BeginImplFrame deadline
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
- EXPECT_TRUE(client.needs_begin_impl_frame());
- client.Reset();
-}
-
-TEST(SchedulerTest, TextureAcquisitionCollision) {
- bool deadline_scheduling_enabled = false;
- TextureAcquisitionCollision(deadline_scheduling_enabled);
-}
-
-TEST(SchedulerTest, TextureAcquisitionCollision_Deadline) {
- bool deadline_scheduling_enabled = true;
- TextureAcquisitionCollision(deadline_scheduling_enabled);
-}
-
-void VisibilitySwitchWithTextureAcquisition(bool deadline_scheduling_enabled) {
- FakeSchedulerClient client;
- SchedulerSettings scheduler_settings;
- scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
- Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
- scheduler->SetCanStart();
- scheduler->SetVisible(true);
- scheduler->SetCanDraw(true);
-
- EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
- client.Reset();
- scheduler->DidCreateAndInitializeOutputSurface();
-
- scheduler->SetNeedsCommit();
- if (deadline_scheduling_enabled) {
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
- }
- scheduler->FinishCommit();
- scheduler->SetMainThreadNeedsLayerTextures();
- scheduler->SetNeedsCommit();
- client.Reset();
- // Verify that pending texture acquisition fires when visibility
- // is lost in order to avoid a deadlock.
- scheduler->SetVisible(false);
- EXPECT_SINGLE_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
- client);
-
- client.Reset();
- scheduler->SetVisible(true);
- EXPECT_EQ(0, client.num_actions_());
- EXPECT_TRUE(client.needs_begin_impl_frame());
-
- // Regaining visibility with textures acquired by main thread while
- // compositor is waiting for first draw should result in a request
- // for a new frame in order to escape a deadlock.
- client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
- EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
-}
-
-TEST(SchedulerTest, VisibilitySwitchWithTextureAcquisition) {
- bool deadline_scheduling_enabled = false;
- VisibilitySwitchWithTextureAcquisition(deadline_scheduling_enabled);
-}
-
-TEST(SchedulerTest, VisibilitySwitchWithTextureAcquisition_Deadline) {
- bool deadline_scheduling_enabled = true;
- VisibilitySwitchWithTextureAcquisition(deadline_scheduling_enabled);
}
class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
public:
virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
- virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
+ virtual DrawResult ScheduledActionDrawAndSwapIfPossible()
OVERRIDE {
// Only SetNeedsRedraw the first time this is called
if (!num_draws_)
@@ -687,12 +446,9 @@ class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
}
- virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
+ virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE {
NOTREACHED();
- bool did_draw = true;
- bool did_swap = true;
- bool did_readback = false;
- return DrawSwapReadbackResult(did_draw, did_swap, did_readback);
+ return DRAW_SUCCESS;
}
virtual void ScheduledActionCommit() OVERRIDE {}
@@ -707,84 +463,84 @@ class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
TEST(SchedulerTest, RequestRedrawInsideDraw) {
SchedulerClientThatsetNeedsDrawInsideDraw client;
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
+ TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
- InitializeOutputSurfaceAndFirstCommit(scheduler);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
client.Reset();
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
EXPECT_EQ(0, client.num_draws());
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(1, client.num_draws());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(2, client.num_draws());
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
// We stop requesting BeginImplFrames after a BeginImplFrame where we don't
// swap.
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(2, client.num_draws());
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_FALSE(client.needs_begin_impl_frame());
+ EXPECT_FALSE(client.needs_begin_frame());
}
// Test that requesting redraw inside a failed draw doesn't lose the request.
TEST(SchedulerTest, RequestRedrawInsideFailedDraw) {
SchedulerClientThatsetNeedsDrawInsideDraw client;
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
+ TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
- InitializeOutputSurfaceAndFirstCommit(scheduler);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
client.Reset();
client.SetDrawWillHappen(false);
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
EXPECT_EQ(0, client.num_draws());
// Fail the draw.
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(1, client.num_draws());
// We have a commit pending and the draw failed, and we didn't lose the redraw
// request.
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
// Fail the draw again.
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(2, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
// Draw successfully.
client.SetDrawWillHappen(true);
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(3, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
}
class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
@@ -793,7 +549,7 @@ class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
: set_needs_commit_on_next_draw_(false) {}
virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
- virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
+ virtual DrawResult ScheduledActionDrawAndSwapIfPossible()
OVERRIDE {
// Only SetNeedsCommit the first time this is called
if (set_needs_commit_on_next_draw_) {
@@ -803,12 +559,9 @@ class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
}
- virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
+ virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE {
NOTREACHED();
- bool did_draw = true;
- bool did_swap = false;
- bool did_readback = false;
- return DrawSwapReadbackResult(did_draw, did_swap, did_readback);
+ return DRAW_SUCCESS;
}
virtual void ScheduledActionCommit() OVERRIDE {}
@@ -826,172 +579,131 @@ class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
TEST(SchedulerTest, RequestCommitInsideDraw) {
SchedulerClientThatSetNeedsCommitInsideDraw client;
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
+ TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
- InitializeOutputSurfaceAndFirstCommit(scheduler);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
client.Reset();
- EXPECT_FALSE(client.needs_begin_impl_frame());
+ EXPECT_FALSE(client.needs_begin_frame());
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
EXPECT_EQ(0, client.num_draws());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
client.SetNeedsCommitOnNextDraw();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
client.SetNeedsCommitOnNextDraw();
- scheduler->OnBeginImplFrameDeadline();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(1, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
- scheduler->FinishCommit();
+ EXPECT_TRUE(client.needs_begin_frame());
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(2, client.num_draws());
EXPECT_FALSE(scheduler->RedrawPending());
EXPECT_FALSE(scheduler->CommitPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
// We stop requesting BeginImplFrames after a BeginImplFrame where we don't
// swap.
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(2, client.num_draws());
EXPECT_FALSE(scheduler->RedrawPending());
EXPECT_FALSE(scheduler->CommitPending());
- EXPECT_FALSE(client.needs_begin_impl_frame());
+ EXPECT_FALSE(client.needs_begin_frame());
}
// Tests that when a draw fails then the pending commit should not be dropped.
TEST(SchedulerTest, RequestCommitInsideFailedDraw) {
SchedulerClientThatsetNeedsDrawInsideDraw client;
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
+ TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
- InitializeOutputSurfaceAndFirstCommit(scheduler);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
client.Reset();
client.SetDrawWillHappen(false);
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
EXPECT_EQ(0, client.num_draws());
// Fail the draw.
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(1, client.num_draws());
// We have a commit pending and the draw failed, and we didn't lose the commit
// request.
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
// Fail the draw again.
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(2, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
// Draw successfully.
client.SetDrawWillHappen(true);
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(3, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
}
TEST(SchedulerTest, NoSwapWhenDrawFails) {
SchedulerClientThatSetNeedsCommitInsideDraw client;
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
+ TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
- InitializeOutputSurfaceAndFirstCommit(scheduler);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
client.Reset();
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
EXPECT_EQ(0, client.num_draws());
// Draw successfully, this starts a new frame.
client.SetNeedsCommitOnNextDraw();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(1, client.num_draws());
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
// Fail to draw, this should not start a frame.
client.SetDrawWillHappen(false);
client.SetNeedsCommitOnNextDraw();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(2, client.num_draws());
}
-TEST(SchedulerTest, NoSwapWhenSwapFailsDuringForcedCommit) {
- FakeSchedulerClient client;
- SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
-
- // Tell the client that it will fail to swap.
- client.SetDrawWillHappen(true);
- client.SetSwapWillHappenIfDrawHappens(false);
-
- // Get the compositor to do a ScheduledActionDrawAndReadback.
- scheduler->SetCanDraw(true);
- scheduler->SetNeedsRedraw();
- scheduler->SetNeedsForcedCommitForReadback();
- scheduler->FinishCommit();
- EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndReadback"));
-}
-
-TEST(SchedulerTest, BackToBackReadbackAllowed) {
- // Some clients call readbacks twice in a row before the replacement
- // commit comes in. Make sure it is allowed.
- FakeSchedulerClient client;
- SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
-
- // Get the compositor to do 2 ScheduledActionDrawAndReadbacks before
- // the replacement commit comes in.
- scheduler->SetCanDraw(true);
- scheduler->SetNeedsRedraw();
- scheduler->SetNeedsForcedCommitForReadback();
- scheduler->FinishCommit();
- EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndReadback"));
-
- client.Reset();
- scheduler->SetNeedsForcedCommitForReadback();
- scheduler->FinishCommit();
- EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndReadback"));
-
- // The replacement commit comes in after 2 readbacks.
- client.Reset();
- scheduler->FinishCommit();
-}
-
-
class SchedulerClientNeedsManageTilesInDraw : public FakeSchedulerClient {
public:
- virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
+ virtual DrawResult ScheduledActionDrawAndSwapIfPossible()
OVERRIDE {
scheduler_->SetNeedsManageTiles();
return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
@@ -1002,11 +714,11 @@ class SchedulerClientNeedsManageTilesInDraw : public FakeSchedulerClient {
TEST(SchedulerTest, ManageTiles) {
SchedulerClientNeedsManageTilesInDraw client;
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
+ TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
- InitializeOutputSurfaceAndFirstCommit(scheduler);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
// Request both draw and manage tiles. ManageTiles shouldn't
// be trigged until BeginImplFrame.
@@ -1015,7 +727,7 @@ TEST(SchedulerTest, ManageTiles) {
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
EXPECT_TRUE(scheduler->ManageTilesPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
EXPECT_EQ(0, client.num_draws());
EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
@@ -1023,12 +735,14 @@ TEST(SchedulerTest, ManageTiles) {
// We have no immediate actions to perform, so the BeginImplFrame should post
// the deadline task.
client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
// On the deadline, he actions should have occured in the right order.
client.Reset();
- scheduler->OnBeginImplFrameDeadline();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(1, client.num_draws());
EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
@@ -1036,26 +750,29 @@ TEST(SchedulerTest, ManageTiles) {
client.ActionIndex("ScheduledActionManageTiles"));
EXPECT_FALSE(scheduler->RedrawPending());
EXPECT_FALSE(scheduler->ManageTilesPending());
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
// Request a draw. We don't need a ManageTiles yet.
client.Reset();
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
EXPECT_FALSE(scheduler->ManageTilesPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
EXPECT_EQ(0, client.num_draws());
// We have no immediate actions to perform, so the BeginImplFrame should post
// the deadline task.
client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
// Draw. The draw will trigger SetNeedsManageTiles, and
// then the ManageTiles action will be triggered after the Draw.
// Afterwards, neither a draw nor ManageTiles are pending.
client.Reset();
- scheduler->OnBeginImplFrameDeadline();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(1, client.num_draws());
EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
@@ -1063,75 +780,86 @@ TEST(SchedulerTest, ManageTiles) {
client.ActionIndex("ScheduledActionManageTiles"));
EXPECT_FALSE(scheduler->RedrawPending());
EXPECT_FALSE(scheduler->ManageTilesPending());
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
// We need a BeginImplFrame where we don't swap to go idle.
client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);;
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
+ EXPECT_FALSE(client.needs_begin_frame());
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
EXPECT_EQ(0, client.num_draws());
// Now trigger a ManageTiles outside of a draw. We will then need
// a begin-frame for the ManageTiles, but we don't need a draw.
client.Reset();
- EXPECT_FALSE(client.needs_begin_impl_frame());
+ EXPECT_FALSE(client.needs_begin_frame());
scheduler->SetNeedsManageTiles();
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
EXPECT_TRUE(scheduler->ManageTilesPending());
EXPECT_FALSE(scheduler->RedrawPending());
// BeginImplFrame. There will be no draw, only ManageTiles.
client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
client.Reset();
- scheduler->OnBeginImplFrameDeadline();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(0, client.num_draws());
EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
}
// Test that ManageTiles only happens once per frame. If an external caller
-// initiates it, then the state machine should not on that frame.
+// initiates it, then the state machine should not ManageTiles on that frame.
TEST(SchedulerTest, ManageTilesOncePerFrame) {
FakeSchedulerClient client;
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
+ TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
- InitializeOutputSurfaceAndFirstCommit(scheduler);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
// If DidManageTiles during a frame, then ManageTiles should not occur again.
scheduler->SetNeedsManageTiles();
scheduler->SetNeedsRedraw();
client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
EXPECT_TRUE(scheduler->ManageTilesPending());
- scheduler->DidManageTiles();
+ scheduler->DidManageTiles(); // An explicit ManageTiles.
EXPECT_FALSE(scheduler->ManageTilesPending());
client.Reset();
- scheduler->OnBeginImplFrameDeadline();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(1, client.num_draws());
EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
EXPECT_FALSE(scheduler->RedrawPending());
EXPECT_FALSE(scheduler->ManageTilesPending());
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
// Next frame without DidManageTiles should ManageTiles with draw.
scheduler->SetNeedsManageTiles();
scheduler->SetNeedsRedraw();
client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
client.Reset();
- scheduler->OnBeginImplFrameDeadline();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(1, client.num_draws());
EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
@@ -1139,6 +867,153 @@ TEST(SchedulerTest, ManageTilesOncePerFrame) {
client.ActionIndex("ScheduledActionManageTiles"));
EXPECT_FALSE(scheduler->RedrawPending());
EXPECT_FALSE(scheduler->ManageTilesPending());
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ scheduler->DidManageTiles(); // Corresponds to ScheduledActionManageTiles
+
+ // If we get another DidManageTiles within the same frame, we should
+ // not ManageTiles on the next frame.
+ scheduler->DidManageTiles(); // An explicit ManageTiles.
+ scheduler->SetNeedsManageTiles();
+ scheduler->SetNeedsRedraw();
+ client.Reset();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+
+ EXPECT_TRUE(scheduler->ManageTilesPending());
+
+ client.Reset();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_EQ(1, client.num_draws());
+ EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
+ EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
+ EXPECT_FALSE(scheduler->RedrawPending());
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+
+ // If we get another DidManageTiles, we should not ManageTiles on the next
+ // frame. This verifies we don't alternate calling ManageTiles once and twice.
+ EXPECT_TRUE(scheduler->ManageTilesPending());
+ scheduler->DidManageTiles(); // An explicit ManageTiles.
+ EXPECT_FALSE(scheduler->ManageTilesPending());
+ scheduler->SetNeedsManageTiles();
+ scheduler->SetNeedsRedraw();
+ client.Reset();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+
+ EXPECT_TRUE(scheduler->ManageTilesPending());
+
+ client.Reset();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_EQ(1, client.num_draws());
+ EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
+ EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
+ EXPECT_FALSE(scheduler->RedrawPending());
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+
+ // Next frame without DidManageTiles should ManageTiles with draw.
+ scheduler->SetNeedsManageTiles();
+ scheduler->SetNeedsRedraw();
+ client.Reset();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+
+ client.Reset();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_EQ(1, client.num_draws());
+ EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
+ EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
+ EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
+ client.ActionIndex("ScheduledActionManageTiles"));
+ EXPECT_FALSE(scheduler->RedrawPending());
+ EXPECT_FALSE(scheduler->ManageTilesPending());
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ scheduler->DidManageTiles(); // Corresponds to ScheduledActionManageTiles
+}
+
+TEST(SchedulerTest, ShouldUpdateVisibleTiles) {
+ FakeSchedulerClient client;
+ SchedulerSettings scheduler_settings;
+ scheduler_settings.impl_side_painting = true;
+ TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
+
+ client.SetRedrawWillHappenIfUpdateVisibleTilesHappens(true);
+
+ // SetNeedsCommit should begin the frame.
+ client.Reset();
+ scheduler->SetNeedsCommit();
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
+
+ client.Reset();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+
+ client.Reset();
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
+ EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
+
+ client.Reset();
+ scheduler->NotifyReadyToActivate();
+ EXPECT_SINGLE_ACTION("ScheduledActionActivatePendingTree", client);
+
+ client.Reset();
+ client.SetSwapContainsIncompleteTile(true);
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
+ EXPECT_FALSE(scheduler->RedrawPending());
+
+ client.Reset();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+
+ client.Reset();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionUpdateVisibleTiles", client, 0, 3);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 3);
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 2, 3);
+
+ client.Reset();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+
+ // No more UpdateVisibleTiles().
+ client.Reset();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
+ EXPECT_FALSE(client.needs_begin_frame());
+}
+
+TEST(SchedulerTest, TriggerBeginFrameDeadlineEarly) {
+ SchedulerClientNeedsManageTilesInDraw client;
+ SchedulerSettings default_scheduler_settings;
+ TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
+
+ client.Reset();
+ scheduler->SetNeedsRedraw();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+
+ // The deadline should be zero since there is no work other than drawing
+ // pending.
+ EXPECT_EQ(base::TimeTicks(), client.posted_begin_impl_frame_deadline());
}
class SchedulerClientWithFixedEstimates : public FakeSchedulerClient {
@@ -1170,6 +1045,7 @@ class SchedulerClientWithFixedEstimates : public FakeSchedulerClient {
void MainFrameInHighLatencyMode(int64 begin_main_frame_to_commit_estimate_in_ms,
int64 commit_to_activate_estimate_in_ms,
+ bool smoothness_takes_priority,
bool should_send_begin_main_frame) {
// Set up client with specified estimates (draw duration is set to 1).
SchedulerClientWithFixedEstimates client(
@@ -1177,33 +1053,33 @@ void MainFrameInHighLatencyMode(int64 begin_main_frame_to_commit_estimate_in_ms,
base::TimeDelta::FromMilliseconds(
begin_main_frame_to_commit_estimate_in_ms),
base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms));
- SchedulerSettings scheduler_settings;
- scheduler_settings.deadline_scheduling_enabled = true;
- scheduler_settings.switch_to_low_latency_if_possible = true;
- Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ SchedulerSettings default_scheduler_settings;
+ TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
- InitializeOutputSurfaceAndFirstCommit(scheduler);
+ scheduler->SetSmoothnessTakesPriority(smoothness_takes_priority);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
// Impl thread hits deadline before commit finishes.
client.Reset();
scheduler->SetNeedsCommit();
EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode());
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode());
- scheduler->OnBeginImplFrameDeadline();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
- scheduler->FinishCommit();
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
client.Reset();
scheduler->SetNeedsCommit();
EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
- scheduler->OnBeginImplFrameDeadline();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(scheduler->MainThreadIsInHighLatencyMode(),
should_send_begin_main_frame);
EXPECT_EQ(client.HasAction("ScheduledActionSendBeginMainFrame"),
@@ -1214,36 +1090,38 @@ TEST(SchedulerTest,
SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) {
// Set up client so that estimates indicate that we can commit and activate
// before the deadline (~8ms by default).
- MainFrameInHighLatencyMode(1, 1, false);
+ MainFrameInHighLatencyMode(1, 1, false, false);
}
TEST(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) {
// Set up client so that estimates indicate that the commit cannot finish
// before the deadline (~8ms by default).
- MainFrameInHighLatencyMode(10, 1, true);
+ MainFrameInHighLatencyMode(10, 1, false, true);
}
TEST(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) {
// Set up client so that estimates indicate that the activate cannot finish
// before the deadline (~8ms by default).
- MainFrameInHighLatencyMode(1, 10, true);
+ MainFrameInHighLatencyMode(1, 10, false, true);
}
-void SpinForMillis(int millis) {
- base::RunLoop run_loop;
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- run_loop.QuitClosure(),
- base::TimeDelta::FromMilliseconds(millis));
- run_loop.Run();
+TEST(SchedulerTest, NotSkipMainFrameInPreferSmoothnessMode) {
+ // Set up client so that estimates indicate that we can commit and activate
+ // before the deadline (~8ms by default), but also enable smoothness takes
+ // priority mode.
+ MainFrameInHighLatencyMode(1, 1, true, true);
}
TEST(SchedulerTest, PollForCommitCompletion) {
- FakeSchedulerClient client;
+ // Since we are simulating a long commit, set up a client with draw duration
+ // estimates that prevent skipping main frames to get to low latency mode.
+ SchedulerClientWithFixedEstimates client(
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMilliseconds(32),
+ base::TimeDelta::FromMilliseconds(32));
client.set_log_anticipated_draw_time_change(true);
- SchedulerSettings settings = SchedulerSettings();
- settings.throttle_frame_production = false;
- Scheduler* scheduler = client.CreateScheduler(settings);
+ SchedulerSettings default_scheduler_settings;
+ TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanDraw(true);
scheduler->SetCanStart();
@@ -1252,34 +1130,789 @@ TEST(SchedulerTest, PollForCommitCompletion) {
scheduler->SetNeedsCommit();
EXPECT_TRUE(scheduler->CommitPending());
- scheduler->FinishCommit();
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
scheduler->SetNeedsRedraw();
- BeginFrameArgs impl_frame_args = BeginFrameArgs::CreateForTesting();
- const int interval = 1;
- impl_frame_args.interval = base::TimeDelta::FromMilliseconds(interval);
- scheduler->BeginImplFrame(impl_frame_args);
- scheduler->OnBeginImplFrameDeadline();
-
- // At this point, we've drawn a frame. Start another commit, but hold off on
- // the FinishCommit for now.
+
+ BeginFrameArgs frame_args = CreateBeginFrameArgsForTesting();
+ frame_args.interval = base::TimeDelta::FromMilliseconds(1000);
+ scheduler->BeginFrame(frame_args);
+
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+
+ scheduler->DidSwapBuffers();
+ scheduler->DidSwapBuffersComplete();
+
+ // At this point, we've drawn a frame. Start another commit, but hold off on
+ // the NotifyReadyToCommit for now.
EXPECT_FALSE(scheduler->CommitPending());
scheduler->SetNeedsCommit();
+ scheduler->BeginFrame(frame_args);
EXPECT_TRUE(scheduler->CommitPending());
+ // Draw and swap the frame, but don't ack the swap to simulate the Browser
+ // blocking on the renderer.
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ scheduler->DidSwapBuffers();
+
// Spin the event loop a few times and make sure we get more
// DidAnticipateDrawTimeChange calls every time.
int actions_so_far = client.num_actions_();
// Does three iterations to make sure that the timer is properly repeating.
for (int i = 0; i < 3; ++i) {
- // Wait for 2x the frame interval to match
- // Scheduler::advance_commit_state_timer_'s rate.
- SpinForMillis(interval * 2);
+ EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
+ client.task_runner().NextPendingTaskDelay().InMicroseconds())
+ << *scheduler->AsValue();
+ client.task_runner().RunPendingTasks();
EXPECT_GT(client.num_actions_(), actions_so_far);
EXPECT_STREQ(client.Action(client.num_actions_() - 1),
"DidAnticipatedDrawTimeChange");
actions_so_far = client.num_actions_();
}
+
+ // Do the same thing after BeginMainFrame starts but still before activation.
+ scheduler->NotifyBeginMainFrameStarted();
+ for (int i = 0; i < 3; ++i) {
+ EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
+ client.task_runner().NextPendingTaskDelay().InMicroseconds())
+ << *scheduler->AsValue();
+ client.task_runner().RunPendingTasks();
+ EXPECT_GT(client.num_actions_(), actions_so_far);
+ EXPECT_STREQ(client.Action(client.num_actions_() - 1),
+ "DidAnticipatedDrawTimeChange");
+ actions_so_far = client.num_actions_();
+ }
+}
+
+TEST(SchedulerTest, BeginRetroFrame) {
+ FakeSchedulerClient client;
+ SchedulerSettings scheduler_settings;
+ TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
+
+ // SetNeedsCommit should begin the frame on the next BeginImplFrame.
+ client.Reset();
+ scheduler->SetNeedsCommit();
+ EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
+ client.Reset();
+
+ // Create a BeginFrame with a long deadline to avoid race conditions.
+ // This is the first BeginFrame, which will be handled immediately.
+ BeginFrameArgs args = CreateBeginFrameArgsForTesting();
+ args.deadline += base::TimeDelta::FromHours(1);
+ scheduler->BeginFrame(args);
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
+ client.Reset();
+
+ // Queue BeginFrames while we are still handling the previous BeginFrame.
+ args.frame_time += base::TimeDelta::FromSeconds(1);
+ scheduler->BeginFrame(args);
+ args.frame_time += base::TimeDelta::FromSeconds(1);
+ scheduler->BeginFrame(args);
+
+ // If we don't swap on the deadline, we wait for the next BeginImplFrame.
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_NO_ACTION(client);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
+ client.Reset();
+
+ // NotifyReadyToCommit should trigger the commit.
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
+ EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
+ EXPECT_TRUE(client.needs_begin_frame());
+ client.Reset();
+
+ // BeginImplFrame should prepare the draw.
+ client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
+ client.Reset();
+
+ // BeginImplFrame deadline should draw.
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
+ client.Reset();
+
+ // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
+ // to avoid excessive toggles.
+ client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
+ EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ client.Reset();
+
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
+ EXPECT_FALSE(client.needs_begin_frame());
+ client.Reset();
+}
+
+TEST(SchedulerTest, BeginRetroFrame_SwapThrottled) {
+ FakeSchedulerClient client;
+ SchedulerSettings scheduler_settings;
+ TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
+
+ // To test swap ack throttling, this test disables automatic swap acks.
+ scheduler->SetMaxSwapsPending(1);
+ client.SetAutomaticSwapAck(false);
+
+ // SetNeedsCommit should begin the frame on the next BeginImplFrame.
+ client.Reset();
+ scheduler->SetNeedsCommit();
+ EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
+ client.Reset();
+
+ // Create a BeginFrame with a long deadline to avoid race conditions.
+ // This is the first BeginFrame, which will be handled immediately.
+ BeginFrameArgs args = CreateBeginFrameArgsForTesting();
+ args.deadline += base::TimeDelta::FromHours(1);
+ scheduler->BeginFrame(args);
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
+ client.Reset();
+
+ // Queue BeginFrame while we are still handling the previous BeginFrame.
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ args.frame_time += base::TimeDelta::FromSeconds(1);
+ scheduler->BeginFrame(args);
+ EXPECT_NO_ACTION(client);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ client.Reset();
+
+ // NotifyReadyToCommit should trigger the pending commit and draw.
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
+ EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
+ EXPECT_TRUE(client.needs_begin_frame());
+ client.Reset();
+
+ // Swapping will put us into a swap throttled state.
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
+ client.Reset();
+
+ // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
+ // but not a BeginMainFrame or draw.
+ scheduler->SetNeedsCommit();
+ client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 1);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
+ client.Reset();
+
+ // Queue BeginFrame while we are still handling the previous BeginFrame.
+ args.frame_time += base::TimeDelta::FromSeconds(1);
+ scheduler->BeginFrame(args);
+ EXPECT_NO_ACTION(client);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
+ client.Reset();
+
+ // Take us out of a swap throttled state.
+ scheduler->DidSwapBuffersComplete();
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 1);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
+ client.Reset();
+
+ // BeginImplFrame deadline should draw.
+ scheduler->SetNeedsRedraw();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
+ client.Reset();
+}
+
+void BeginFramesNotFromClient(bool begin_frame_scheduling_enabled,
+ bool throttle_frame_production) {
+ FakeSchedulerClient client;
+ SchedulerSettings scheduler_settings;
+ scheduler_settings.begin_frame_scheduling_enabled =
+ begin_frame_scheduling_enabled;
+ scheduler_settings.throttle_frame_production = throttle_frame_production;
+ TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
+
+ // SetNeedsCommit should begin the frame on the next BeginImplFrame
+ // without calling SetNeedsBeginFrame.
+ client.Reset();
+ scheduler->SetNeedsCommit();
+ EXPECT_FALSE(client.needs_begin_frame());
+ EXPECT_NO_ACTION(client);
+ client.Reset();
+
+ // When the client-driven BeginFrame are disabled, the scheduler posts it's
+ // own BeginFrame tasks.
+ client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_FALSE(client.needs_begin_frame());
+ client.Reset();
+
+ // If we don't swap on the deadline, we wait for the next BeginFrame.
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_NO_ACTION(client);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_FALSE(client.needs_begin_frame());
+ client.Reset();
+
+ // NotifyReadyToCommit should trigger the commit.
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
+ EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
+ EXPECT_FALSE(client.needs_begin_frame());
+ client.Reset();
+
+ // BeginImplFrame should prepare the draw.
+ client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_FALSE(client.needs_begin_frame());
+ client.Reset();
+
+ // BeginImplFrame deadline should draw.
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_FALSE(client.needs_begin_frame());
+ client.Reset();
+
+ // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
+ // to avoid excessive toggles.
+ client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
+ EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ client.Reset();
+
+ // Make sure SetNeedsBeginFrame isn't called on the client
+ // when the BeginFrame is no longer needed.
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_NO_ACTION(client);
+ EXPECT_FALSE(client.needs_begin_frame());
+ client.Reset();
+}
+
+TEST(SchedulerTest, SyntheticBeginFrames) {
+ bool begin_frame_scheduling_enabled = false;
+ bool throttle_frame_production = true;
+ BeginFramesNotFromClient(begin_frame_scheduling_enabled,
+ throttle_frame_production);
+}
+
+TEST(SchedulerTest, VSyncThrottlingDisabled) {
+ bool begin_frame_scheduling_enabled = true;
+ bool throttle_frame_production = false;
+ BeginFramesNotFromClient(begin_frame_scheduling_enabled,
+ throttle_frame_production);
+}
+
+TEST(SchedulerTest, SyntheticBeginFrames_And_VSyncThrottlingDisabled) {
+ bool begin_frame_scheduling_enabled = false;
+ bool throttle_frame_production = false;
+ BeginFramesNotFromClient(begin_frame_scheduling_enabled,
+ throttle_frame_production);
+}
+
+void BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled,
+ bool throttle_frame_production) {
+ FakeSchedulerClient client;
+ SchedulerSettings scheduler_settings;
+ scheduler_settings.begin_frame_scheduling_enabled =
+ begin_frame_scheduling_enabled;
+ scheduler_settings.throttle_frame_production = throttle_frame_production;
+ TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
+
+ // To test swap ack throttling, this test disables automatic swap acks.
+ scheduler->SetMaxSwapsPending(1);
+ client.SetAutomaticSwapAck(false);
+
+ // SetNeedsCommit should begin the frame on the next BeginImplFrame.
+ client.Reset();
+ scheduler->SetNeedsCommit();
+ EXPECT_FALSE(client.needs_begin_frame());
+ EXPECT_NO_ACTION(client);
+ client.Reset();
+
+ // Trigger the first BeginImplFrame and BeginMainFrame
+ client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_FALSE(client.needs_begin_frame());
+ client.Reset();
+
+ // NotifyReadyToCommit should trigger the pending commit and draw.
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
+ EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
+ EXPECT_FALSE(client.needs_begin_frame());
+ client.Reset();
+
+ // Swapping will put us into a swap throttled state.
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_FALSE(client.needs_begin_frame());
+ client.Reset();
+
+ // While swap throttled, BeginFrames should trigger BeginImplFrames,
+ // but not a BeginMainFrame or draw.
+ scheduler->SetNeedsCommit();
+ client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 1);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_FALSE(client.needs_begin_frame());
+ client.Reset();
+
+ // Take us out of a swap throttled state.
+ scheduler->DidSwapBuffersComplete();
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 1);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_FALSE(client.needs_begin_frame());
+ client.Reset();
+
+ // BeginImplFrame deadline should draw.
+ scheduler->SetNeedsRedraw();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_FALSE(client.needs_begin_frame());
+ client.Reset();
+}
+
+TEST(SchedulerTest, SyntheticBeginFrames_SwapThrottled) {
+ bool begin_frame_scheduling_enabled = false;
+ bool throttle_frame_production = true;
+ BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled,
+ throttle_frame_production);
+}
+
+TEST(SchedulerTest, VSyncThrottlingDisabled_SwapThrottled) {
+ bool begin_frame_scheduling_enabled = true;
+ bool throttle_frame_production = false;
+ BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled,
+ throttle_frame_production);
+}
+
+TEST(SchedulerTest,
+ SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled) {
+ bool begin_frame_scheduling_enabled = false;
+ bool throttle_frame_production = false;
+ BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled,
+ throttle_frame_production);
+}
+
+TEST(SchedulerTest, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized) {
+ FakeSchedulerClient client;
+ SchedulerSettings scheduler_settings;
+ TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+
+ EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
+ client.Reset();
+ scheduler->DidCreateAndInitializeOutputSurface();
+ EXPECT_NO_ACTION(client);
+
+ scheduler->DidLoseOutputSurface();
+ EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
+}
+
+TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) {
+ FakeSchedulerClient client;
+ SchedulerSettings scheduler_settings;
+ TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+
+ EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
+ // SetNeedsCommit should begin the frame.
+ client.Reset();
+ scheduler->SetNeedsCommit();
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
+
+ client.Reset();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+
+ client.Reset();
+ scheduler->DidLoseOutputSurface();
+ // Do nothing when impl frame is in deadine pending state.
+ EXPECT_NO_ACTION(client);
+
+ client.Reset();
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
+ EXPECT_ACTION("ScheduledActionCommit", client, 0, 1);
+
+ client.Reset();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
+}
+
+void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
+ bool impl_side_painting) {
+ FakeSchedulerClient client;
+ SchedulerSettings scheduler_settings;
+ scheduler_settings.impl_side_painting = impl_side_painting;
+ TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+
+ EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
+
+ // SetNeedsCommit should begin the frame.
+ client.Reset();
+ scheduler->SetNeedsCommit();
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
+
+ client.Reset();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+
+ client.Reset();
+ scheduler->DidLoseOutputSurface();
+ // Do nothing when impl frame is in deadine pending state.
+ EXPECT_NO_ACTION(client);
+
+ client.Reset();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ // OnBeginImplFrameDeadline didn't schedule any actions because main frame is
+ // not yet completed.
+ EXPECT_NO_ACTION(client);
+
+ // BeginImplFrame is not started.
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_NO_ACTION(client);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+
+ client.Reset();
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
+ if (impl_side_painting) {
+ EXPECT_ACTION("ScheduledActionCommit", client, 0, 3);
+ EXPECT_ACTION("ScheduledActionActivatePendingTree", client, 1, 3);
+ EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 2, 3);
+ } else {
+ EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 1, 2);
+ }
+}
+
+TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) {
+ bool impl_side_painting = false;
+ DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
+}
+
+TEST(SchedulerTest,
+ DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint) {
+ bool impl_side_painting = true;
+ DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
+}
+
+void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting) {
+ FakeSchedulerClient client;
+ SchedulerSettings scheduler_settings;
+ scheduler_settings.impl_side_painting = impl_side_painting;
+ TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+
+ EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
+
+ // SetNeedsCommit should begin the frame.
+ client.Reset();
+ scheduler->SetNeedsCommit();
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
+
+ client.Reset();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+
+ client.Reset();
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
+ EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
+
+ client.Reset();
+ scheduler->DidLoseOutputSurface();
+ if (impl_side_painting) {
+ // Pending tree should be forced to activate.
+ EXPECT_SINGLE_ACTION("ScheduledActionActivatePendingTree", client);
+ } else {
+ // Do nothing when impl frame is in deadine pending state.
+ EXPECT_NO_ACTION(client);
+ }
+
+ client.Reset();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
+}
+
+TEST(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) {
+ DidLoseOutputSurfaceAfterReadyToCommit(false);
+}
+
+TEST(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting) {
+ DidLoseOutputSurfaceAfterReadyToCommit(true);
+}
+
+TEST(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsManageTiles) {
+ FakeSchedulerClient client;
+ SchedulerSettings scheduler_settings;
+ TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
+
+ client.Reset();
+ scheduler->SetNeedsManageTiles();
+ scheduler->SetNeedsRedraw();
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
+ EXPECT_TRUE(client.needs_begin_frame());
+
+ client.Reset();
+ scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+
+ client.Reset();
+ scheduler->DidLoseOutputSurface();
+ EXPECT_NO_ACTION(client);
+
+ client.Reset();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionManageTiles", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 1, 2);
+}
+
+TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) {
+ FakeSchedulerClient client;
+ SchedulerSettings scheduler_settings;
+ TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
+
+ // SetNeedsCommit should begin the frame on the next BeginImplFrame.
+ client.Reset();
+ scheduler->SetNeedsCommit();
+ EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
+
+ // Create a BeginFrame with a long deadline to avoid race conditions.
+ // This is the first BeginFrame, which will be handled immediately.
+ client.Reset();
+ BeginFrameArgs args = CreateBeginFrameArgsForTesting();
+ args.deadline += base::TimeDelta::FromHours(1);
+ scheduler->BeginFrame(args);
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
+
+ // Queue BeginFrames while we are still handling the previous BeginFrame.
+ args.frame_time += base::TimeDelta::FromSeconds(1);
+ scheduler->BeginFrame(args);
+ args.frame_time += base::TimeDelta::FromSeconds(1);
+ scheduler->BeginFrame(args);
+
+ // If we don't swap on the deadline, we wait for the next BeginImplFrame.
+ client.Reset();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_NO_ACTION(client);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
+
+ // NotifyReadyToCommit should trigger the commit.
+ client.Reset();
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
+ EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
+ EXPECT_TRUE(client.needs_begin_frame());
+
+ client.Reset();
+ EXPECT_FALSE(scheduler->IsBeginRetroFrameArgsEmpty());
+ scheduler->DidLoseOutputSurface();
+ EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
+ EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(scheduler->IsBeginRetroFrameArgsEmpty());
+
+ // Posted BeginRetroFrame is aborted.
+ client.Reset();
+ client.task_runner().RunPendingTasks();
+ EXPECT_NO_ACTION(client);
+}
+
+TEST(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) {
+ FakeSchedulerClient client;
+ SchedulerSettings scheduler_settings;
+ TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
+
+ // SetNeedsCommit should begin the frame on the next BeginImplFrame.
+ client.Reset();
+ scheduler->SetNeedsCommit();
+ EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
+
+ // Create a BeginFrame with a long deadline to avoid race conditions.
+ // This is the first BeginFrame, which will be handled immediately.
+ client.Reset();
+ BeginFrameArgs args = CreateBeginFrameArgsForTesting();
+ args.deadline += base::TimeDelta::FromHours(1);
+ scheduler->BeginFrame(args);
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
+
+ // Queue BeginFrames while we are still handling the previous BeginFrame.
+ args.frame_time += base::TimeDelta::FromSeconds(1);
+ scheduler->BeginFrame(args);
+ args.frame_time += base::TimeDelta::FromSeconds(1);
+ scheduler->BeginFrame(args);
+
+ // If we don't swap on the deadline, we wait for the next BeginImplFrame.
+ client.Reset();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_NO_ACTION(client);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
+
+ // NotifyReadyToCommit should trigger the commit.
+ client.Reset();
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
+ EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
+ EXPECT_TRUE(client.needs_begin_frame());
+
+ // BeginImplFrame should prepare the draw.
+ client.Reset();
+ client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
+
+ client.Reset();
+ EXPECT_FALSE(scheduler->IsBeginRetroFrameArgsEmpty());
+ scheduler->DidLoseOutputSurface();
+ EXPECT_NO_ACTION(client);
+ EXPECT_TRUE(scheduler->IsBeginRetroFrameArgsEmpty());
+
+ // BeginImplFrame deadline should abort drawing.
+ client.Reset();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_frame());
+
+ // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
+ client.Reset();
+ client.task_runner().RunPendingTasks();
+ EXPECT_NO_ACTION(client);
+}
+
+TEST(SchedulerTest,
+ StopBeginFrameAfterDidLoseOutputSurfaceWithSyntheticBeginFrameSource) {
+ FakeSchedulerClient client;
+ SchedulerSettings scheduler_settings;
+ scheduler_settings.begin_frame_scheduling_enabled = false;
+ TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
+
+ // SetNeedsCommit should begin the frame on the next BeginImplFrame.
+ client.Reset();
+ EXPECT_FALSE(scheduler->IsSyntheticBeginFrameSourceActive());
+ scheduler->SetNeedsCommit();
+ EXPECT_TRUE(scheduler->IsSyntheticBeginFrameSourceActive());
+
+ client.Reset();
+ client.task_runner().RunPendingTasks(); // Run posted Tick.
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(scheduler->IsSyntheticBeginFrameSourceActive());
+
+ // NotifyReadyToCommit should trigger the commit.
+ client.Reset();
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
+ EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
+ EXPECT_TRUE(scheduler->IsSyntheticBeginFrameSourceActive());
+
+ client.Reset();
+ scheduler->DidLoseOutputSurface();
+ EXPECT_EQ(0, client.num_actions_());
+ EXPECT_FALSE(scheduler->IsSyntheticBeginFrameSourceActive());
+
+ client.Reset();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
+ EXPECT_FALSE(scheduler->IsSyntheticBeginFrameSourceActive());
}
} // namespace