| Index: cc/scheduler/scheduler_unittest.cc
|
| diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc
|
| index 636beb0494b722c2485d94089e6133414a7499ef..2992dbc11c7f8da2cf3a485a5bcaa85b52c61b9b 100644
|
| --- a/cc/scheduler/scheduler_unittest.cc
|
| +++ b/cc/scheduler/scheduler_unittest.cc
|
| @@ -168,19 +168,32 @@ class FakeSchedulerClient : public SchedulerClient {
|
| void AdvanceFrame() {
|
| TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
|
| "FakeSchedulerClient::AdvanceFrame");
|
| + bool previous_deadline_pending =
|
| + scheduler_->BeginImplFrameDeadlinePending();
|
| if (ExternalBeginFrame()) {
|
| - // Creep the time forward so that any BeginFrameArgs is not equal to the
|
| - // last one otherwise we violate the BeginFrameSource contract.
|
| - now_src_->AdvanceNowMicroseconds(1);
|
| - fake_external_begin_frame_source_->TestOnBeginFrame(
|
| - CreateBeginFrameArgsForTesting(now_src_));
|
| + SendNextBeginFrame();
|
| + // This could be the previous deadline or a new one.
|
| EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
|
| }
|
| -
|
| + // Consume previous deadline first. It is important that we check for the
|
| + // existence of a previous deadline so that we do not consume the new one.
|
| + if (previous_deadline_pending) {
|
| + EXPECT_TRUE(task_runner().RunTasksWhile(ImplFrameDeadlinePending(true)));
|
| + }
|
| + // Then run tasks until new deadline is scheduled.
|
| EXPECT_TRUE(task_runner().RunTasksWhile(ImplFrameDeadlinePending(false)));
|
| EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
|
| }
|
|
|
| + void SendNextBeginFrame() {
|
| + DCHECK(ExternalBeginFrame());
|
| + // Creep the time forward so that any BeginFrameArgs is not equal to the
|
| + // last one otherwise we violate the BeginFrameSource contract.
|
| + now_src_->AdvanceNow(BeginFrameArgs::DefaultInterval());
|
| + fake_external_begin_frame_source_->TestOnBeginFrame(
|
| + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src_));
|
| + }
|
| +
|
| OrderedSimpleTaskRunner& task_runner() { return *task_runner_; }
|
| TestNowSource* now_src() { return now_src_.get(); }
|
|
|
| @@ -1167,7 +1180,8 @@ TEST(SchedulerTest, PollForCommitCompletion) {
|
| scheduler->NotifyReadyToCommit();
|
| scheduler->SetNeedsRedraw();
|
|
|
| - BeginFrameArgs frame_args = CreateBeginFrameArgsForTesting(client.now_src());
|
| + BeginFrameArgs frame_args =
|
| + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, client.now_src());
|
| frame_args.interval = base::TimeDelta::FromMilliseconds(1000);
|
| client.fake_external_begin_frame_source()->TestOnBeginFrame(frame_args);
|
|
|
| @@ -1240,7 +1254,8 @@ TEST(SchedulerTest, BeginRetroFrame) {
|
|
|
| // Create a BeginFrame with a long deadline to avoid race conditions.
|
| // This is the first BeginFrame, which will be handled immediately.
|
| - BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src());
|
| + BeginFrameArgs args =
|
| + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, client.now_src());
|
| args.deadline += base::TimeDelta::FromHours(1);
|
| client.fake_external_begin_frame_source()->TestOnBeginFrame(args);
|
| EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
|
| @@ -1318,7 +1333,8 @@ TEST(SchedulerTest, BeginRetroFrame_SwapThrottled) {
|
|
|
| // Create a BeginFrame with a long deadline to avoid race conditions.
|
| // This is the first BeginFrame, which will be handled immediately.
|
| - BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src());
|
| + BeginFrameArgs args =
|
| + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, client.now_src());
|
| args.deadline += base::TimeDelta::FromHours(1);
|
| client.fake_external_begin_frame_source()->TestOnBeginFrame(args);
|
| EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
|
| @@ -1387,6 +1403,131 @@ TEST(SchedulerTest, BeginRetroFrame_SwapThrottled) {
|
| client.Reset();
|
| }
|
|
|
| +TEST(SchedulerTest, RetroFrameDoesNotExpireTooEarly) {
|
| + FakeSchedulerClient client;
|
| + SchedulerSettings scheduler_settings;
|
| + scheduler_settings.use_external_begin_frame_source = true;
|
| + TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
|
| + scheduler->SetCanStart();
|
| + scheduler->SetVisible(true);
|
| + scheduler->SetCanDraw(true);
|
| + InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
|
| +
|
| + client.Reset();
|
| + scheduler->SetNeedsCommit();
|
| + EXPECT_TRUE(client.needs_begin_frames());
|
| + EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
|
| +
|
| + client.Reset();
|
| + client.AdvanceFrame();
|
| + EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
|
| + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
|
| + EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
|
| +
|
| + client.Reset();
|
| + scheduler->NotifyBeginMainFrameStarted();
|
| +
|
| + client.Reset();
|
| + client.SendNextBeginFrame();
|
| + // This BeginFrame is queued up as a retro frame.
|
| + EXPECT_NO_ACTION(client);
|
| + // The previous deadline is still pending.
|
| + EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
|
| +
|
| + client.Reset();
|
| + // This commit should schedule the (previous) deadline to trigger immediately.
|
| + scheduler->NotifyReadyToCommit();
|
| + EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
|
| +
|
| + client.Reset();
|
| + // The deadline task should trigger causing a draw.
|
| + EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
|
| + client.task_runner().RunTasksWhile(client.ImplFrameDeadlinePending(true));
|
| + EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
|
| + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
|
| +
|
| + // Keep animating.
|
| + client.Reset();
|
| + scheduler->SetNeedsAnimate();
|
| + scheduler->SetNeedsRedraw();
|
| + EXPECT_NO_ACTION(client);
|
| +
|
| + // Let's advance sufficiently past the next frame's deadline.
|
| + client.now_src()->AdvanceNow(
|
| + BeginFrameArgs::DefaultInterval() -
|
| + BeginFrameArgs::DefaultEstimatedParentDrawTime() +
|
| + base::TimeDelta::FromMicroseconds(1));
|
| +
|
| + // The retro frame hasn't expired yet.
|
| + client.task_runner().RunTasksWhile(client.ImplFrameDeadlinePending(false));
|
| + EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
|
| + EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
|
| + EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
|
| +
|
| + // This is an immediate deadline case.
|
| + client.Reset();
|
| + client.task_runner().RunPendingTasks();
|
| + EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
|
| + EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client);
|
| +}
|
| +
|
| +TEST(SchedulerTest, RetroFrameDoesNotExpireTooLate) {
|
| + FakeSchedulerClient client;
|
| + SchedulerSettings scheduler_settings;
|
| + scheduler_settings.use_external_begin_frame_source = true;
|
| + TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
|
| + scheduler->SetCanStart();
|
| + scheduler->SetVisible(true);
|
| + scheduler->SetCanDraw(true);
|
| + InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
|
| +
|
| + client.Reset();
|
| + scheduler->SetNeedsCommit();
|
| + EXPECT_TRUE(client.needs_begin_frames());
|
| + EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
|
| +
|
| + client.Reset();
|
| + client.AdvanceFrame();
|
| + EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
|
| + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
|
| + EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
|
| +
|
| + client.Reset();
|
| + scheduler->NotifyBeginMainFrameStarted();
|
| +
|
| + client.Reset();
|
| + client.SendNextBeginFrame();
|
| + // This BeginFrame is queued up as a retro frame.
|
| + EXPECT_NO_ACTION(client);
|
| + // The previous deadline is still pending.
|
| + EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
|
| +
|
| + client.Reset();
|
| + // This commit should schedule the (previous) deadline to trigger immediately.
|
| + scheduler->NotifyReadyToCommit();
|
| + EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
|
| +
|
| + client.Reset();
|
| + // The deadline task should trigger causing a draw.
|
| + EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
|
| + client.task_runner().RunTasksWhile(client.ImplFrameDeadlinePending(true));
|
| + EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
|
| + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
|
| +
|
| + // Keep animating.
|
| + client.Reset();
|
| + scheduler->SetNeedsAnimate();
|
| + scheduler->SetNeedsRedraw();
|
| + EXPECT_NO_ACTION(client);
|
| +
|
| + // Let's advance sufficiently past the next frame's deadline.
|
| + client.now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() +
|
| + base::TimeDelta::FromMicroseconds(1));
|
| +
|
| + // The retro frame should've expired.
|
| + EXPECT_NO_ACTION(client);
|
| +}
|
| +
|
| void BeginFramesNotFromClient(bool use_external_begin_frame_source,
|
| bool throttle_frame_production) {
|
| FakeSchedulerClient client;
|
| @@ -1793,7 +1934,8 @@ TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) {
|
| // 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(client.now_src());
|
| + BeginFrameArgs args =
|
| + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, client.now_src());
|
| args.deadline += base::TimeDelta::FromHours(1);
|
| client.fake_external_begin_frame_source()->TestOnBeginFrame(args);
|
| EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
|
| @@ -1852,7 +1994,8 @@ TEST(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) {
|
| // 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(client.now_src());
|
| + BeginFrameArgs args =
|
| + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, client.now_src());
|
| args.deadline += base::TimeDelta::FromHours(1);
|
| client.fake_external_begin_frame_source()->TestOnBeginFrame(args);
|
| EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
|
|
|