#include "base/memory/scoped_vector.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/test/test_simple_task_runner.h"
#include "base/time/time.h"
#include "cc/test/scheduler_test_common.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace cc {
namespace {
-void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler) {
- scheduler->DidCreateAndInitializeOutputSurface();
- scheduler->SetNeedsCommit();
- scheduler->NotifyBeginMainFrameStarted();
- scheduler->NotifyReadyToCommit();
- // 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 FakeSchedulerClient : public SchedulerClient {
public:
- FakeSchedulerClient()
- : needs_begin_impl_frame_(false) {
+ FakeSchedulerClient() : needs_begin_frame_(false), automatic_swap_ack_(true) {
Reset();
}
}
Scheduler* CreateScheduler(const SchedulerSettings& settings) {
- scheduler_ =
- Scheduler::Create(this, settings, 0, base::MessageLoopProxy::current());
+ task_runner_ = new base::TestSimpleTaskRunner;
+ scheduler_ = Scheduler::Create(this, settings, 0, task_runner_);
return scheduler_.get();
}
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]; }
return posted_begin_impl_frame_deadline_;
}
+ base::TestSimpleTaskRunner& task_runner() { return *task_runner_; }
+
int ActionIndex(const char* action) const {
for (size_t i = 0; i < actions_.size(); i++)
if (!strcmp(actions_[i], action))
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;
+ }
// SchedulerClient implementation.
- virtual void SetNeedsBeginImplFrame(bool enable) OVERRIDE {
- actions_.push_back("SetNeedsBeginImplFrame");
+ virtual void SetNeedsBeginFrame(bool enable) OVERRIDE {
+ actions_.push_back("SetNeedsBeginFrame");
+ states_.push_back(scheduler_->StateAsValue().release());
+ needs_begin_frame_ = enable;
+ }
+ virtual void WillBeginImplFrame(const BeginFrameArgs& args) OVERRIDE {
+ actions_.push_back("WillBeginImplFrame");
states_.push_back(scheduler_->StateAsValue().release());
- needs_begin_impl_frame_ = enable;
}
virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {
actions_.push_back("ScheduledActionSendBeginMainFrame");
states_.push_back(scheduler_->StateAsValue().release());
}
+ virtual void ScheduledActionAnimate() OVERRIDE {
+ actions_.push_back("ScheduledActionAnimate");
+ states_.push_back(scheduler_->StateAsValue().release());
+ }
virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
OVERRIDE {
actions_.push_back("ScheduledActionDrawAndSwapIfPossible");
draw_will_happen_
? DrawSwapReadbackResult::DRAW_SUCCESS
: DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
+ bool swap_will_happen =
+ draw_will_happen_ && swap_will_happen_if_draw_happens_;
+ if (swap_will_happen) {
+ scheduler_->DidSwapBuffers();
+ if (automatic_swap_ack_)
+ scheduler_->DidSwapBuffersComplete();
+ }
return DrawSwapReadbackResult(
result,
draw_will_happen_ && swap_will_happen_if_draw_happens_,
virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
actions_.push_back("ScheduledActionDrawAndSwapForced");
states_.push_back(scheduler_->StateAsValue().release());
- bool did_swap = swap_will_happen_if_draw_happens_;
+ bool did_request_swap = swap_will_happen_if_draw_happens_;
bool did_readback = false;
return DrawSwapReadbackResult(
- DrawSwapReadbackResult::DRAW_SUCCESS, did_swap, did_readback);
+ DrawSwapReadbackResult::DRAW_SUCCESS, did_request_swap, did_readback);
}
virtual DrawSwapReadbackResult ScheduledActionDrawAndReadback() OVERRIDE {
actions_.push_back("ScheduledActionDrawAndReadback");
states_.push_back(scheduler_->StateAsValue().release());
- bool did_swap = false;
+ bool did_request_swap = false;
bool did_readback = true;
return DrawSwapReadbackResult(
- DrawSwapReadbackResult::DRAW_SUCCESS, did_swap, did_readback);
+ DrawSwapReadbackResult::DRAW_SUCCESS, did_request_swap, did_readback);
}
virtual void ScheduledActionCommit() OVERRIDE {
actions_.push_back("ScheduledActionCommit");
actions_.push_back("ScheduledActionBeginOutputSurfaceCreation");
states_.push_back(scheduler_->StateAsValue().release());
}
- virtual void ScheduledActionAcquireLayerTexturesForMainThread() OVERRIDE {
- actions_.push_back("ScheduledActionAcquireLayerTexturesForMainThread");
- states_.push_back(scheduler_->StateAsValue().release());
- }
virtual void ScheduledActionManageTiles() OVERRIDE {
actions_.push_back("ScheduledActionManageTiles");
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_;
base::TimeTicks posted_begin_impl_frame_deadline_;
std::vector<const char*> actions_;
ScopedVector<base::Value> states_;
scoped_ptr<Scheduler> scheduler_;
+ scoped_refptr<base::TestSimpleTaskRunner> 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();
+ // Go through the motions to draw the commit.
+ if (client_initiates_begin_frame)
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ 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(BeginFrameArgs::CreateForTesting());
+ 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->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());
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
+ EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client);
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ 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();
- // If we don't swap on the deadline, we need to request another
- // BeginImplFrame.
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
+ // If we don't swap on the deadline, we wait for the next BeginFrame.
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_EQ(0, client.num_actions_());
EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ 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_impl_frame());
+ EXPECT_TRUE(client.needs_begin_frame());
client.Reset();
// BeginImplFrame should prepare the draw.
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_EQ(client.num_actions_(), 0);
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ 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);
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
+ 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_EQ(client.num_actions_(), 0);
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ 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();
}
scheduler->SetCanDraw(true);
EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
- InitializeOutputSurfaceAndFirstCommit(scheduler);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
client.Reset();
// SetNeedsCommit should begin the frame.
scheduler->SetNeedsCommit();
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client);
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ 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.
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);
+ 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());
- EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client);
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
client.Reset();
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);
+ 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_impl_frame());
+ 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());
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_FALSE(client.needs_begin_frame());
client.Reset();
}
-TEST(SchedulerTest, TextureAcquisitionCausesCommitInsteadOfDraw) {
- FakeSchedulerClient client;
- SchedulerSettings scheduler_settings;
- 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_EQ(client.num_actions_(), 0);
- EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
- client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
- EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
- EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
-
- client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_EQ(client.num_actions_(), 0);
- EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
- client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
- 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_EQ(client.num_actions_(), 0);
- EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
- client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
- EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_impl_frame());
-
- client.Reset();
- scheduler->SetNeedsCommit();
- EXPECT_EQ(0, client.num_actions_());
-
- client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client);
- EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
-
- // Commit will release the texture.
- client.Reset();
- scheduler->NotifyBeginMainFrameStarted();
- scheduler->NotifyReadyToCommit();
- EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
- EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
- 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->BeginImplFrameDeadlinePending());
- 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_EQ(client.num_actions_(), 0);
- EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
- client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- EXPECT_FALSE(client.needs_begin_impl_frame());
-}
-
-TEST(SchedulerTest, TextureAcquisitionCollision) {
- FakeSchedulerClient client;
- SchedulerSettings scheduler_settings;
- 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();
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
-
- client.Reset();
- scheduler->SetMainThreadNeedsLayerTextures();
- EXPECT_SINGLE_ACTION(
- "ScheduledActionAcquireLayerTexturesForMainThread", client);
-
- client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client);
- EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
-
- 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->NotifyBeginMainFrameStarted();
- scheduler->NotifyReadyToCommit();
- 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_EQ(client.num_actions_(), 0);
- EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
-
- client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 3);
- EXPECT_ACTION(
- "ScheduledActionAcquireLayerTexturesForMainThread", client, 1, 3);
- EXPECT_ACTION("SetNeedsBeginImplFrame", client, 2, 3);
- EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
- 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_EQ(client.num_actions_(), 0);
- EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
- client.Reset();
- scheduler->OnBeginImplFrameDeadline();
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- EXPECT_FALSE(client.needs_begin_impl_frame());
- EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
-
- // The impl thread need an explicit commit from the main thread to lock
- // the textures.
- client.Reset();
- scheduler->SetNeedsCommit();
- EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
- EXPECT_TRUE(client.needs_begin_impl_frame());
-
- client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client);
- EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
- client.Reset();
-
- // Trigger the commit, which will trigger the deadline task early.
- scheduler->NotifyBeginMainFrameStarted();
- scheduler->NotifyReadyToCommit();
- EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
- EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
- 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());
- EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
- client.Reset();
-}
-
-TEST(SchedulerTest, VisibilitySwitchWithTextureAcquisition) {
- FakeSchedulerClient client;
- SchedulerSettings scheduler_settings;
- 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();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
- scheduler->NotifyBeginMainFrameStarted();
- scheduler->NotifyReadyToCommit();
- 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_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client);
- EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
-}
-
class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
public:
virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
NOTREACHED();
- bool did_swap = true;
+ bool did_request_swap = true;
bool did_readback = false;
return DrawSwapReadbackResult(
- DrawSwapReadbackResult::DRAW_SUCCESS, did_swap, did_readback);
+ DrawSwapReadbackResult::DRAW_SUCCESS, did_request_swap, did_readback);
}
virtual void ScheduledActionCommit() OVERRIDE {}
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(BeginFrameArgs::CreateForTesting());
+ 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(BeginFrameArgs::CreateForTesting());
+ 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(BeginFrameArgs::CreateForTesting());
+ 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.
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(BeginFrameArgs::CreateForTesting());
+ 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(BeginFrameArgs::CreateForTesting());
+ 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(BeginFrameArgs::CreateForTesting());
+ 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 {
virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
NOTREACHED();
- bool did_swap = false;
+ bool did_request_swap = false;
bool did_readback = false;
return DrawSwapReadbackResult(
- DrawSwapReadbackResult::DRAW_SUCCESS, did_swap, did_readback);
+ DrawSwapReadbackResult::DRAW_SUCCESS, did_request_swap, did_readback);
}
virtual void ScheduledActionCommit() OVERRIDE {}
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(BeginFrameArgs::CreateForTesting());
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());
+ EXPECT_TRUE(client.needs_begin_frame());
scheduler->NotifyBeginMainFrameStarted();
scheduler->NotifyReadyToCommit();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- scheduler->OnBeginImplFrameDeadline();
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ 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(BeginFrameArgs::CreateForTesting());
+ 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.
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(BeginFrameArgs::CreateForTesting());
+ 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(BeginFrameArgs::CreateForTesting());
+
+ 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(BeginFrameArgs::CreateForTesting());
+ 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) {
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(BeginFrameArgs::CreateForTesting());
+ 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(BeginFrameArgs::CreateForTesting());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_EQ(2, client.num_draws());
}
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.
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"));
// We have no immediate actions to perform, so the BeginImplFrame should post
// the deadline task.
client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_EQ(client.num_actions_(), 0);
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ 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"));
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_EQ(client.num_actions_(), 0);
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ 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"));
// We need a BeginImplFrame where we don't swap to go idle.
client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_EQ(client.num_actions_(), 0);
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ 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_EQ(client.num_actions_(), 0);
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ 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"));
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_EQ(client.num_actions_(), 0);
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
EXPECT_TRUE(scheduler->ManageTilesPending());
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"));
scheduler->SetNeedsManageTiles();
scheduler->SetNeedsRedraw();
client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_EQ(client.num_actions_(), 0);
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ 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"));
scheduler->SetNeedsManageTiles();
scheduler->SetNeedsRedraw();
client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_EQ(client.num_actions_(), 0);
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
EXPECT_TRUE(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"));
scheduler->SetNeedsManageTiles();
scheduler->SetNeedsRedraw();
client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_EQ(client.num_actions_(), 0);
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
EXPECT_TRUE(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"));
scheduler->SetNeedsManageTiles();
scheduler->SetNeedsRedraw();
client.Reset();
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
- EXPECT_EQ(client.num_actions_(), 0);
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
+ 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"));
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
- InitializeOutputSurfaceAndFirstCommit(scheduler);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
client.Reset();
- BeginFrameArgs impl_frame_args = BeginFrameArgs::CreateForTesting();
scheduler->SetNeedsRedraw();
- scheduler->BeginImplFrame(impl_frame_args);
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
// The deadline should be zero since there is no work other than drawing
// pending.
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
scheduler->SetSmoothnessTakesPriority(smoothness_takes_priority);
- InitializeOutputSurfaceAndFirstCommit(scheduler);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
// Impl thread hits deadline before commit finishes.
client.Reset();
scheduler->SetNeedsCommit();
EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode());
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode());
- scheduler->OnBeginImplFrameDeadline();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
scheduler->NotifyBeginMainFrameStarted();
scheduler->NotifyReadyToCommit();
client.Reset();
scheduler->SetNeedsCommit();
EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
- scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
+ scheduler->BeginFrame(BeginFrameArgs::CreateForTesting());
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"),
MainFrameInHighLatencyMode(1, 1, true, 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, PollForCommitCompletion) {
// 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.
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;
+ Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanDraw(true);
scheduler->SetCanStart();
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
+ BeginFrameArgs frame_args = BeginFrameArgs::CreateForTesting();
+ 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->StateAsValue();
+ 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->StateAsValue();
+ 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;
+ Scheduler* 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 = BeginFrameArgs::CreateForTesting();
+ 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_EQ(0, client.num_actions_());
+ 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;
+ Scheduler* 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 = BeginFrameArgs::CreateForTesting();
+ 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_EQ(0, client.num_actions_());
+ 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_EQ(0, client.num_actions_());
+ 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;
+ Scheduler* 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_EQ(0, client.num_actions_());
+ 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_EQ(0, client.num_actions_());
+ 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_EQ(0, client.num_actions_());
+ 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;
+ Scheduler* 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_EQ(0, client.num_actions_());
+ 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);
}
} // namespace