Index: cc/scheduler/scheduler_unittest.cc |
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc |
index 68dc0d1a49ee9e1ed8de92a1982c282438c318a3..21e20ea9880c2eb3504157b3b5ec32a9cf962e16 100644 |
--- a/cc/scheduler/scheduler_unittest.cc |
+++ b/cc/scheduler/scheduler_unittest.cc |
@@ -40,7 +40,7 @@ void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler, |
class FakeSchedulerClient : public SchedulerClient { |
public: |
FakeSchedulerClient() |
- : needs_begin_impl_frame_(false) { |
+ : needs_begin_impl_frame_(false), automatic_swap_ack_(true) { |
Reset(); |
} |
@@ -92,6 +92,9 @@ 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; |
+ } |
// SchedulerClient implementation. |
virtual void SetNeedsBeginFrame(bool enable) OVERRIDE { |
@@ -117,6 +120,13 @@ class FakeSchedulerClient : public SchedulerClient { |
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_, |
@@ -125,18 +135,18 @@ class FakeSchedulerClient : public SchedulerClient { |
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"); |
@@ -178,6 +188,7 @@ class FakeSchedulerClient : public SchedulerClient { |
bool needs_begin_impl_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_; |
@@ -381,10 +392,10 @@ class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient { |
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 {} |
@@ -497,10 +508,10 @@ 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 {} |
@@ -1058,6 +1069,9 @@ TEST(SchedulerTest, PollForCommitCompletion) { |
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()); |
@@ -1065,6 +1079,13 @@ TEST(SchedulerTest, PollForCommitCompletion) { |
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_(); |
@@ -1095,7 +1116,7 @@ TEST(SchedulerTest, PollForCommitCompletion) { |
} |
} |
-TEST(SchedulerTest, BeginRetroFrame) { |
+TEST(SchedulerTest, BeginRetroFrameBasic) { |
FakeSchedulerClient client; |
SchedulerSettings scheduler_settings; |
Scheduler* scheduler = client.CreateScheduler(scheduler_settings); |
@@ -1116,7 +1137,6 @@ TEST(SchedulerTest, BeginRetroFrame) { |
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()); |
@@ -1172,5 +1192,93 @@ TEST(SchedulerTest, BeginRetroFrame) { |
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_impl_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_impl_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_impl_frame()); |
+ client.Reset(); |
+ |
+ // Swapping will put us into a swap throttled state. |
+ client.task_runner().RunPendingTasks(); // Run posted deadline. |
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2); |
+ EXPECT_ACTION("SetNeedsBeginFrame", client, 1, 2); |
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); |
+ EXPECT_TRUE(client.needs_begin_impl_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_impl_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_impl_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_impl_frame()); |
+ client.Reset(); |
+ |
+ // BeginImplFrame deadline should draw. |
+ scheduler->SetNeedsRedraw(); |
+ client.task_runner().RunPendingTasks(); // Run posted deadline. |
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2); |
+ EXPECT_ACTION("SetNeedsBeginFrame", client, 1, 2); |
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); |
+ EXPECT_TRUE(client.needs_begin_impl_frame()); |
+ client.Reset(); |
+} |
+ |
} // namespace |
} // namespace cc |