1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/scheduler/scheduler.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_vector.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "base/time/time.h"
15 #include "base/trace_event/trace_event.h"
16 #include "cc/test/begin_frame_args_test.h"
17 #include "cc/test/ordered_simple_task_runner.h"
18 #include "cc/test/scheduler_test_common.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
24 EXPECT_EQ(expected_num_actions, client->num_actions_()); \
25 if (action_index >= 0) { \
26 ASSERT_LT(action_index, client->num_actions_()) << scheduler_.get(); \
27 EXPECT_STREQ(action, client->Action(action_index)); \
29 for (int i = expected_num_actions; i < client->num_actions_(); ++i) \
30 ADD_FAILURE() << "Unexpected action: " << client->Action(i) \
31 << " with state:\n" << client->StateForAction(i); \
34 #define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0)
36 #define EXPECT_SINGLE_ACTION(action, client) \
37 EXPECT_ACTION(action, client, 0, 1)
39 #define EXPECT_SCOPED(statements) \
48 class FakeSchedulerClient
: public SchedulerClient
{
51 : automatic_swap_ack_(true),
52 begin_frame_is_sent_to_children_(false),
60 draw_will_happen_
= true;
61 swap_will_happen_if_draw_happens_
= true;
63 log_anticipated_draw_time_change_
= false;
64 begin_frame_is_sent_to_children_
= false;
67 void set_scheduler(TestScheduler
* scheduler
) { scheduler_
= scheduler
; }
69 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
71 void set_log_anticipated_draw_time_change(bool log
) {
72 log_anticipated_draw_time_change_
= log
;
74 bool needs_begin_frames() {
75 return scheduler_
->frame_source().NeedsBeginFrames();
77 int num_draws() const { return num_draws_
; }
78 int num_actions_() const { return static_cast<int>(actions_
.size()); }
79 const char* Action(int i
) const { return actions_
[i
]; }
80 std::string
StateForAction(int i
) const { return states_
[i
]->ToString(); }
81 base::TimeTicks
posted_begin_impl_frame_deadline() const {
82 return posted_begin_impl_frame_deadline_
;
85 int ActionIndex(const char* action
) const {
86 for (size_t i
= 0; i
< actions_
.size(); i
++)
87 if (!strcmp(actions_
[i
], action
))
92 bool HasAction(const char* action
) const {
93 return ActionIndex(action
) >= 0;
96 void SetDrawWillHappen(bool draw_will_happen
) {
97 draw_will_happen_
= draw_will_happen
;
99 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens
) {
100 swap_will_happen_if_draw_happens_
= swap_will_happen_if_draw_happens
;
102 void SetAutomaticSwapAck(bool automatic_swap_ack
) {
103 automatic_swap_ack_
= automatic_swap_ack
;
105 // SchedulerClient implementation.
106 void WillBeginImplFrame(const BeginFrameArgs
& args
) override
{
107 PushAction("WillBeginImplFrame");
109 void ScheduledActionSendBeginMainFrame() override
{
110 PushAction("ScheduledActionSendBeginMainFrame");
112 void ScheduledActionAnimate() override
{
113 PushAction("ScheduledActionAnimate");
115 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
116 PushAction("ScheduledActionDrawAndSwapIfPossible");
119 draw_will_happen_
? DRAW_SUCCESS
: DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
;
120 bool swap_will_happen
=
121 draw_will_happen_
&& swap_will_happen_if_draw_happens_
;
122 if (swap_will_happen
) {
123 scheduler_
->DidSwapBuffers();
125 if (automatic_swap_ack_
)
126 scheduler_
->DidSwapBuffersComplete();
130 DrawResult
ScheduledActionDrawAndSwapForced() override
{
131 PushAction("ScheduledActionDrawAndSwapForced");
134 void ScheduledActionCommit() override
{ PushAction("ScheduledActionCommit"); }
135 void ScheduledActionActivateSyncTree() override
{
136 PushAction("ScheduledActionActivateSyncTree");
138 void ScheduledActionBeginOutputSurfaceCreation() override
{
139 PushAction("ScheduledActionBeginOutputSurfaceCreation");
141 void ScheduledActionPrepareTiles() override
{
142 PushAction("ScheduledActionPrepareTiles");
144 void ScheduledActionInvalidateOutputSurface() override
{
145 actions_
.push_back("ScheduledActionInvalidateOutputSurface");
146 states_
.push_back(scheduler_
->AsValue());
148 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{
149 if (log_anticipated_draw_time_change_
)
150 PushAction("DidAnticipatedDrawTimeChange");
152 base::TimeDelta
DrawDurationEstimate() override
{ return base::TimeDelta(); }
153 base::TimeDelta
BeginMainFrameToCommitDurationEstimate() override
{
154 return base::TimeDelta();
156 base::TimeDelta
CommitToActivateDurationEstimate() override
{
157 return base::TimeDelta();
160 void DidBeginImplFrameDeadline() override
{}
162 void SendBeginFramesToChildren(const BeginFrameArgs
& args
) override
{
163 begin_frame_is_sent_to_children_
= true;
166 void SendBeginMainFrameNotExpectedSoon() override
{
167 PushAction("SendBeginMainFrameNotExpectedSoon");
170 base::Callback
<bool(void)> ImplFrameDeadlinePending(bool state
) {
171 return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback
,
172 base::Unretained(this),
176 bool begin_frame_is_sent_to_children() const {
177 return begin_frame_is_sent_to_children_
;
180 void PushAction(const char* description
) {
181 actions_
.push_back(description
);
182 states_
.push_back(scheduler_
->AsValue());
186 bool ImplFrameDeadlinePendingCallback(bool state
) {
187 return scheduler_
->BeginImplFrameDeadlinePending() == state
;
190 bool draw_will_happen_
;
191 bool swap_will_happen_if_draw_happens_
;
192 bool automatic_swap_ack_
;
194 bool log_anticipated_draw_time_change_
;
195 bool begin_frame_is_sent_to_children_
;
196 base::TimeTicks posted_begin_impl_frame_deadline_
;
197 std::vector
<const char*> actions_
;
198 std::vector
<scoped_refptr
<base::trace_event::ConvertableToTraceFormat
>>
200 TestScheduler
* scheduler_
;
203 class FakeExternalBeginFrameSource
: public BeginFrameSourceMixIn
{
205 explicit FakeExternalBeginFrameSource(FakeSchedulerClient
* client
)
207 ~FakeExternalBeginFrameSource() override
{}
209 void OnNeedsBeginFramesChange(bool needs_begin_frames
) override
{
210 if (needs_begin_frames
) {
211 client_
->PushAction("SetNeedsBeginFrames(true)");
213 client_
->PushAction("SetNeedsBeginFrames(false)");
217 void TestOnBeginFrame(const BeginFrameArgs
& args
) {
218 return CallOnBeginFrame(args
);
222 FakeSchedulerClient
* client_
;
225 class SchedulerTest
: public testing::Test
{
228 : now_src_(TestNowSource::Create()),
229 task_runner_(new OrderedSimpleTaskRunner(now_src_
, true)),
230 fake_external_begin_frame_source_(nullptr) {
231 // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval()
232 now_src_
->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
233 // Fail if we need to run 100 tasks in a row.
234 task_runner_
->SetRunTaskLimit(100);
237 ~SchedulerTest() override
{}
240 TestScheduler
* CreateScheduler() {
241 scoped_ptr
<FakeExternalBeginFrameSource
> fake_external_begin_frame_source
;
242 if (scheduler_settings_
.use_external_begin_frame_source
) {
243 fake_external_begin_frame_source
.reset(
244 new FakeExternalBeginFrameSource(client_
.get()));
245 fake_external_begin_frame_source_
=
246 fake_external_begin_frame_source
.get();
248 scheduler_
= TestScheduler::Create(now_src_
, client_
.get(),
249 scheduler_settings_
, 0, task_runner_
,
250 fake_external_begin_frame_source
.Pass());
252 client_
->set_scheduler(scheduler_
.get());
253 return scheduler_
.get();
256 void CreateSchedulerAndInitSurface() {
258 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit());
261 void SetUpScheduler(bool initSurface
) {
262 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient
), initSurface
);
265 void SetUpScheduler(scoped_ptr
<FakeSchedulerClient
> client
,
267 client_
= client
.Pass();
269 CreateSchedulerAndInitSurface();
274 OrderedSimpleTaskRunner
& task_runner() { return *task_runner_
; }
275 TestNowSource
* now_src() { return now_src_
.get(); }
277 // As this function contains EXPECT macros, to allow debugging it should be
278 // called inside EXPECT_SCOPED like so;
279 // EXPECT_SCOPED(client.InitializeOutputSurfaceAndFirstCommit(scheduler));
280 void InitializeOutputSurfaceAndFirstCommit() {
282 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit");
285 // Check the client doesn't have any actions queued when calling this
287 EXPECT_NO_ACTION(client_
);
288 EXPECT_FALSE(client_
->needs_begin_frames());
290 // Start the initial output surface creation.
291 EXPECT_FALSE(scheduler_
->CanStart());
292 scheduler_
->SetCanStart();
293 scheduler_
->SetVisible(true);
294 scheduler_
->SetCanDraw(true);
295 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
299 // We don't see anything happening until the first impl frame.
300 scheduler_
->DidCreateAndInitializeOutputSurface();
301 scheduler_
->SetNeedsCommit();
302 EXPECT_TRUE(client_
->needs_begin_frames());
303 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
307 SCOPED_TRACE("Do first frame to commit after initialize.");
310 scheduler_
->NotifyBeginMainFrameStarted();
311 scheduler_
->NotifyReadyToCommitThenActivateIfNeeded();
313 EXPECT_FALSE(scheduler_
->CommitPending());
315 if (scheduler_settings_
.using_synchronous_renderer_compositor
) {
316 scheduler_
->SetNeedsRedraw();
317 scheduler_
->OnDrawForOutputSurface();
319 // Run the posted deadline task.
320 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
321 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
324 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
331 "Run second frame so Scheduler calls SetNeedsBeginFrame(false).");
334 if (!scheduler_settings_
.using_synchronous_renderer_compositor
) {
335 // Run the posted deadline task.
336 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
337 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
340 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
343 EXPECT_FALSE(client_
->needs_begin_frames());
347 // As this function contains EXPECT macros, to allow debugging it should be
348 // called inside EXPECT_SCOPED like so;
349 // EXPECT_SCOPED(client.AdvanceFrame());
350 void AdvanceFrame() {
351 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
352 "FakeSchedulerClient::AdvanceFrame");
353 // Consume any previous deadline first, if no deadline is currently
354 // pending, ImplFrameDeadlinePending will return false straight away and we
355 // will run no tasks.
356 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
357 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
359 // Send the next BeginFrame message if using an external source, otherwise
360 // it will be already in the task queue.
361 if (scheduler_
->settings().use_external_begin_frame_source
&&
362 scheduler_
->FrameProductionThrottled()) {
363 EXPECT_TRUE(client_
->needs_begin_frames());
364 SendNextBeginFrame();
367 if (!scheduler_
->settings().using_synchronous_renderer_compositor
) {
368 // Then run tasks until new deadline is scheduled.
369 EXPECT_TRUE(task_runner_
->RunTasksWhile(
370 client_
->ImplFrameDeadlinePending(false)));
371 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
375 void SendNextBeginFrame() {
376 DCHECK(scheduler_
->settings().use_external_begin_frame_source
);
377 // Creep the time forward so that any BeginFrameArgs is not equal to the
378 // last one otherwise we violate the BeginFrameSource contract.
379 now_src_
->AdvanceNow(BeginFrameArgs::DefaultInterval());
380 fake_external_begin_frame_source_
->TestOnBeginFrame(
381 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src()));
384 FakeExternalBeginFrameSource
* fake_external_begin_frame_source() const {
385 return fake_external_begin_frame_source_
;
388 void MainFrameInHighLatencyMode(
389 int64 begin_main_frame_to_commit_estimate_in_ms
,
390 int64 commit_to_activate_estimate_in_ms
,
391 bool impl_latency_takes_priority
,
392 bool should_send_begin_main_frame
);
393 void BeginFramesNotFromClient(bool use_external_begin_frame_source
,
394 bool throttle_frame_production
);
395 void BeginFramesNotFromClient_SwapThrottled(
396 bool use_external_begin_frame_source
,
397 bool throttle_frame_production
);
398 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
399 bool impl_side_painting
);
400 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting
);
402 scoped_refptr
<TestNowSource
> now_src_
;
403 scoped_refptr
<OrderedSimpleTaskRunner
> task_runner_
;
404 FakeExternalBeginFrameSource
* fake_external_begin_frame_source_
;
405 SchedulerSettings scheduler_settings_
;
406 scoped_ptr
<FakeSchedulerClient
> client_
;
407 scoped_ptr
<TestScheduler
> scheduler_
;
410 TEST_F(SchedulerTest
, InitializeOutputSurfaceDoesNotBeginImplFrame
) {
411 scheduler_settings_
.use_external_begin_frame_source
= true;
412 SetUpScheduler(false);
413 scheduler_
->SetCanStart();
414 scheduler_
->SetVisible(true);
415 scheduler_
->SetCanDraw(true);
417 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
419 scheduler_
->DidCreateAndInitializeOutputSurface();
420 EXPECT_NO_ACTION(client_
);
423 TEST_F(SchedulerTest
, SendBeginFramesToChildren
) {
424 scheduler_settings_
.use_external_begin_frame_source
= true;
425 SetUpScheduler(true);
427 EXPECT_FALSE(client_
->begin_frame_is_sent_to_children());
428 scheduler_
->SetNeedsCommit();
429 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
430 EXPECT_TRUE(client_
->needs_begin_frames());
432 scheduler_
->SetChildrenNeedBeginFrames(true);
435 EXPECT_SCOPED(AdvanceFrame());
436 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
437 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
438 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
439 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
440 EXPECT_TRUE(client_
->needs_begin_frames());
443 TEST_F(SchedulerTest
, SendBeginFramesToChildrenWithoutCommit
) {
444 scheduler_settings_
.use_external_begin_frame_source
= true;
445 SetUpScheduler(true);
447 EXPECT_FALSE(client_
->needs_begin_frames());
448 scheduler_
->SetChildrenNeedBeginFrames(true);
449 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
450 EXPECT_TRUE(client_
->needs_begin_frames());
453 EXPECT_SCOPED(AdvanceFrame());
454 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
457 TEST_F(SchedulerTest
, RequestCommit
) {
458 scheduler_settings_
.use_external_begin_frame_source
= true;
459 SetUpScheduler(true);
461 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
462 scheduler_
->SetNeedsCommit();
463 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
466 EXPECT_SCOPED(AdvanceFrame());
467 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
468 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
469 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
470 EXPECT_TRUE(client_
->needs_begin_frames());
473 // If we don't swap on the deadline, we wait for the next BeginFrame.
474 task_runner().RunPendingTasks(); // Run posted deadline.
475 EXPECT_NO_ACTION(client_
);
476 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
477 EXPECT_TRUE(client_
->needs_begin_frames());
480 // NotifyReadyToCommit should trigger the commit.
481 scheduler_
->NotifyBeginMainFrameStarted();
482 scheduler_
->NotifyReadyToCommit();
483 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
484 EXPECT_TRUE(client_
->needs_begin_frames());
487 // BeginImplFrame should prepare the draw.
488 EXPECT_SCOPED(AdvanceFrame());
489 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
490 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
491 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
492 EXPECT_TRUE(client_
->needs_begin_frames());
495 // BeginImplFrame deadline should draw.
496 task_runner().RunPendingTasks(); // Run posted deadline.
497 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
498 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
499 EXPECT_TRUE(client_
->needs_begin_frames());
502 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
503 // to avoid excessive toggles.
504 EXPECT_SCOPED(AdvanceFrame());
505 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
506 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
509 task_runner().RunPendingTasks(); // Run posted deadline.
510 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
511 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
515 TEST_F(SchedulerTest
, RequestCommitAfterSetDeferCommit
) {
516 scheduler_settings_
.use_external_begin_frame_source
= true;
517 SetUpScheduler(true);
519 scheduler_
->SetDeferCommits(true);
521 scheduler_
->SetNeedsCommit();
522 EXPECT_NO_ACTION(client_
);
525 task_runner().RunPendingTasks();
526 // There are no pending tasks or actions.
527 EXPECT_NO_ACTION(client_
);
528 EXPECT_FALSE(client_
->needs_begin_frames());
531 scheduler_
->SetDeferCommits(false);
532 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
534 // Start new BeginMainFrame after defer commit is off.
536 EXPECT_SCOPED(AdvanceFrame());
537 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
538 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
539 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
542 TEST_F(SchedulerTest
, DeferCommitWithRedraw
) {
543 scheduler_settings_
.use_external_begin_frame_source
= true;
544 SetUpScheduler(true);
546 scheduler_
->SetDeferCommits(true);
548 scheduler_
->SetNeedsCommit();
549 EXPECT_NO_ACTION(client_
);
551 // The SetNeedsRedraw will override the SetDeferCommits(true), to allow a
552 // begin frame to be needed.
554 scheduler_
->SetNeedsRedraw();
555 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
559 // BeginMainFrame is not sent during the defer commit is on.
560 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
561 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
564 task_runner().RunPendingTasks(); // Run posted deadline.
565 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
566 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
567 EXPECT_TRUE(client_
->needs_begin_frames());
571 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
574 TEST_F(SchedulerTest
, RequestCommitAfterBeginMainFrameSent
) {
575 scheduler_settings_
.use_external_begin_frame_source
= true;
576 SetUpScheduler(true);
578 // SetNeedsCommit should begin the frame.
579 scheduler_
->SetNeedsCommit();
580 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
583 EXPECT_SCOPED(AdvanceFrame());
584 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
585 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
586 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
588 EXPECT_TRUE(client_
->needs_begin_frames());
591 // Now SetNeedsCommit again. Calling here means we need a second commit.
592 scheduler_
->SetNeedsCommit();
593 EXPECT_EQ(client_
->num_actions_(), 0);
596 // Finish the first commit.
597 scheduler_
->NotifyBeginMainFrameStarted();
598 scheduler_
->NotifyReadyToCommit();
599 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
600 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
602 task_runner().RunPendingTasks(); // Run posted deadline.
603 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
604 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
605 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
607 // Because we just swapped, the Scheduler should also request the next
608 // BeginImplFrame from the OutputSurface.
609 EXPECT_TRUE(client_
->needs_begin_frames());
611 // Since another commit is needed, the next BeginImplFrame should initiate
612 // the second commit.
613 EXPECT_SCOPED(AdvanceFrame());
614 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
615 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
616 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
619 // Finishing the commit before the deadline should post a new deadline task
620 // to trigger the deadline early.
621 scheduler_
->NotifyBeginMainFrameStarted();
622 scheduler_
->NotifyReadyToCommit();
623 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
624 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
626 task_runner().RunPendingTasks(); // Run posted deadline.
627 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
628 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
629 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
630 EXPECT_TRUE(client_
->needs_begin_frames());
633 // On the next BeginImplFrame, verify we go back to a quiescent state and
634 // no longer request BeginImplFrames.
635 EXPECT_SCOPED(AdvanceFrame());
636 task_runner().RunPendingTasks(); // Run posted deadline.
637 EXPECT_FALSE(client_
->needs_begin_frames());
641 class SchedulerClientThatsetNeedsDrawInsideDraw
: public FakeSchedulerClient
{
643 SchedulerClientThatsetNeedsDrawInsideDraw()
644 : FakeSchedulerClient(), request_redraws_(false) {}
646 void ScheduledActionSendBeginMainFrame() override
{}
648 void SetRequestRedrawsInsideDraw(bool enable
) { request_redraws_
= enable
; }
650 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
651 // Only SetNeedsRedraw the first time this is called
652 if (request_redraws_
) {
653 scheduler_
->SetNeedsRedraw();
655 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
658 DrawResult
ScheduledActionDrawAndSwapForced() override
{
663 void ScheduledActionCommit() override
{}
664 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{}
667 bool request_redraws_
;
670 // Tests for two different situations:
671 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
672 // a ScheduledActionDrawAndSwap
673 // 2. the scheduler drawing twice inside a single tick
674 TEST_F(SchedulerTest
, RequestRedrawInsideDraw
) {
675 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
676 new SchedulerClientThatsetNeedsDrawInsideDraw
;
677 scheduler_settings_
.use_external_begin_frame_source
= true;
678 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
679 client
->SetRequestRedrawsInsideDraw(true);
681 scheduler_
->SetNeedsRedraw();
682 EXPECT_TRUE(scheduler_
->RedrawPending());
683 EXPECT_TRUE(client
->needs_begin_frames());
684 EXPECT_EQ(0, client
->num_draws());
686 EXPECT_SCOPED(AdvanceFrame());
687 task_runner().RunPendingTasks(); // Run posted deadline.
688 EXPECT_EQ(1, client
->num_draws());
689 EXPECT_TRUE(scheduler_
->RedrawPending());
690 EXPECT_TRUE(client
->needs_begin_frames());
692 client
->SetRequestRedrawsInsideDraw(false);
694 EXPECT_SCOPED(AdvanceFrame());
695 task_runner().RunPendingTasks(); // Run posted deadline.
696 EXPECT_EQ(2, client_
->num_draws());
697 EXPECT_FALSE(scheduler_
->RedrawPending());
698 EXPECT_TRUE(client
->needs_begin_frames());
700 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
702 EXPECT_SCOPED(AdvanceFrame());
703 task_runner().RunPendingTasks(); // Run posted deadline.
704 EXPECT_EQ(2, client
->num_draws());
705 EXPECT_FALSE(scheduler_
->RedrawPending());
706 EXPECT_FALSE(client
->needs_begin_frames());
709 // Test that requesting redraw inside a failed draw doesn't lose the request.
710 TEST_F(SchedulerTest
, RequestRedrawInsideFailedDraw
) {
711 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
712 new SchedulerClientThatsetNeedsDrawInsideDraw
;
713 scheduler_settings_
.use_external_begin_frame_source
= true;
714 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
716 client
->SetRequestRedrawsInsideDraw(true);
717 client
->SetDrawWillHappen(false);
719 scheduler_
->SetNeedsRedraw();
720 EXPECT_TRUE(scheduler_
->RedrawPending());
721 EXPECT_TRUE(client
->needs_begin_frames());
722 EXPECT_EQ(0, client
->num_draws());
725 EXPECT_SCOPED(AdvanceFrame());
726 task_runner().RunPendingTasks(); // Run posted deadline.
727 EXPECT_EQ(1, client
->num_draws());
729 // We have a commit pending and the draw failed, and we didn't lose the redraw
731 EXPECT_TRUE(scheduler_
->CommitPending());
732 EXPECT_TRUE(scheduler_
->RedrawPending());
733 EXPECT_TRUE(client
->needs_begin_frames());
735 client
->SetRequestRedrawsInsideDraw(false);
737 // Fail the draw again.
738 EXPECT_SCOPED(AdvanceFrame());
739 task_runner().RunPendingTasks(); // Run posted deadline.
740 EXPECT_EQ(2, client
->num_draws());
741 EXPECT_TRUE(scheduler_
->CommitPending());
742 EXPECT_TRUE(scheduler_
->RedrawPending());
743 EXPECT_TRUE(client
->needs_begin_frames());
745 // Draw successfully.
746 client
->SetDrawWillHappen(true);
747 EXPECT_SCOPED(AdvanceFrame());
748 task_runner().RunPendingTasks(); // Run posted deadline.
749 EXPECT_EQ(3, client
->num_draws());
750 EXPECT_TRUE(scheduler_
->CommitPending());
751 EXPECT_FALSE(scheduler_
->RedrawPending());
752 EXPECT_TRUE(client
->needs_begin_frames());
755 class SchedulerClientThatSetNeedsCommitInsideDraw
: public FakeSchedulerClient
{
757 SchedulerClientThatSetNeedsCommitInsideDraw()
758 : set_needs_commit_on_next_draw_(false) {}
760 void ScheduledActionSendBeginMainFrame() override
{}
761 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
762 // Only SetNeedsCommit the first time this is called
763 if (set_needs_commit_on_next_draw_
) {
764 scheduler_
->SetNeedsCommit();
765 set_needs_commit_on_next_draw_
= false;
767 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
770 DrawResult
ScheduledActionDrawAndSwapForced() override
{
775 void ScheduledActionCommit() override
{}
776 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{}
778 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_
= true; }
781 bool set_needs_commit_on_next_draw_
;
784 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
785 // happen inside a ScheduledActionDrawAndSwap
786 TEST_F(SchedulerTest
, RequestCommitInsideDraw
) {
787 SchedulerClientThatSetNeedsCommitInsideDraw
* client
=
788 new SchedulerClientThatSetNeedsCommitInsideDraw
;
790 scheduler_settings_
.use_external_begin_frame_source
= true;
791 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
793 EXPECT_FALSE(client
->needs_begin_frames());
794 scheduler_
->SetNeedsRedraw();
795 EXPECT_TRUE(scheduler_
->RedrawPending());
796 EXPECT_EQ(0, client
->num_draws());
797 EXPECT_TRUE(client
->needs_begin_frames());
799 client
->SetNeedsCommitOnNextDraw();
800 EXPECT_SCOPED(AdvanceFrame());
801 client
->SetNeedsCommitOnNextDraw();
802 task_runner().RunPendingTasks(); // Run posted deadline.
803 EXPECT_EQ(1, client
->num_draws());
804 EXPECT_TRUE(scheduler_
->CommitPending());
805 EXPECT_TRUE(client
->needs_begin_frames());
806 scheduler_
->NotifyBeginMainFrameStarted();
807 scheduler_
->NotifyReadyToCommit();
809 EXPECT_SCOPED(AdvanceFrame());
810 task_runner().RunPendingTasks(); // Run posted deadline.
811 EXPECT_EQ(2, client
->num_draws());
813 EXPECT_FALSE(scheduler_
->RedrawPending());
814 EXPECT_FALSE(scheduler_
->CommitPending());
815 EXPECT_TRUE(client
->needs_begin_frames());
817 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
819 EXPECT_SCOPED(AdvanceFrame());
820 task_runner().RunPendingTasks(); // Run posted deadline.
821 EXPECT_EQ(2, client
->num_draws());
822 EXPECT_FALSE(scheduler_
->RedrawPending());
823 EXPECT_FALSE(scheduler_
->CommitPending());
824 EXPECT_FALSE(client
->needs_begin_frames());
827 // Tests that when a draw fails then the pending commit should not be dropped.
828 TEST_F(SchedulerTest
, RequestCommitInsideFailedDraw
) {
829 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
830 new SchedulerClientThatsetNeedsDrawInsideDraw
;
831 scheduler_settings_
.use_external_begin_frame_source
= true;
832 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
834 client
->SetDrawWillHappen(false);
836 scheduler_
->SetNeedsRedraw();
837 EXPECT_TRUE(scheduler_
->RedrawPending());
838 EXPECT_TRUE(client
->needs_begin_frames());
839 EXPECT_EQ(0, client
->num_draws());
842 EXPECT_SCOPED(AdvanceFrame());
843 task_runner().RunPendingTasks(); // Run posted deadline.
844 EXPECT_EQ(1, client
->num_draws());
846 // We have a commit pending and the draw failed, and we didn't lose the commit
848 EXPECT_TRUE(scheduler_
->CommitPending());
849 EXPECT_TRUE(scheduler_
->RedrawPending());
850 EXPECT_TRUE(client
->needs_begin_frames());
852 // Fail the draw again.
853 EXPECT_SCOPED(AdvanceFrame());
855 task_runner().RunPendingTasks(); // Run posted deadline.
856 EXPECT_EQ(2, client
->num_draws());
857 EXPECT_TRUE(scheduler_
->CommitPending());
858 EXPECT_TRUE(scheduler_
->RedrawPending());
859 EXPECT_TRUE(client
->needs_begin_frames());
861 // Draw successfully.
862 client
->SetDrawWillHappen(true);
863 EXPECT_SCOPED(AdvanceFrame());
864 task_runner().RunPendingTasks(); // Run posted deadline.
865 EXPECT_EQ(3, client
->num_draws());
866 EXPECT_TRUE(scheduler_
->CommitPending());
867 EXPECT_FALSE(scheduler_
->RedrawPending());
868 EXPECT_TRUE(client
->needs_begin_frames());
871 TEST_F(SchedulerTest
, NoSwapWhenDrawFails
) {
872 SchedulerClientThatSetNeedsCommitInsideDraw
* client
=
873 new SchedulerClientThatSetNeedsCommitInsideDraw
;
874 scheduler_settings_
.use_external_begin_frame_source
= true;
875 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
877 scheduler_
->SetNeedsRedraw();
878 EXPECT_TRUE(scheduler_
->RedrawPending());
879 EXPECT_TRUE(client
->needs_begin_frames());
880 EXPECT_EQ(0, client
->num_draws());
882 // Draw successfully, this starts a new frame.
883 client
->SetNeedsCommitOnNextDraw();
884 EXPECT_SCOPED(AdvanceFrame());
885 task_runner().RunPendingTasks(); // Run posted deadline.
886 EXPECT_EQ(1, client
->num_draws());
888 scheduler_
->SetNeedsRedraw();
889 EXPECT_TRUE(scheduler_
->RedrawPending());
890 EXPECT_TRUE(client
->needs_begin_frames());
892 // Fail to draw, this should not start a frame.
893 client
->SetDrawWillHappen(false);
894 client
->SetNeedsCommitOnNextDraw();
895 EXPECT_SCOPED(AdvanceFrame());
896 task_runner().RunPendingTasks(); // Run posted deadline.
897 EXPECT_EQ(2, client
->num_draws());
900 class SchedulerClientNeedsPrepareTilesInDraw
: public FakeSchedulerClient
{
902 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
903 scheduler_
->SetNeedsPrepareTiles();
904 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
908 // Test prepare tiles is independant of draws.
909 TEST_F(SchedulerTest
, PrepareTiles
) {
910 SchedulerClientNeedsPrepareTilesInDraw
* client
=
911 new SchedulerClientNeedsPrepareTilesInDraw
;
912 scheduler_settings_
.use_external_begin_frame_source
= true;
913 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
915 // Request both draw and prepare tiles. PrepareTiles shouldn't
916 // be trigged until BeginImplFrame.
918 scheduler_
->SetNeedsPrepareTiles();
919 scheduler_
->SetNeedsRedraw();
920 EXPECT_TRUE(scheduler_
->RedrawPending());
921 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
922 EXPECT_TRUE(client
->needs_begin_frames());
923 EXPECT_EQ(0, client
->num_draws());
924 EXPECT_FALSE(client
->HasAction("ScheduledActionPrepareTiles"));
925 EXPECT_FALSE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
927 // We have no immediate actions to perform, so the BeginImplFrame should post
928 // the deadline task.
930 EXPECT_SCOPED(AdvanceFrame());
931 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
932 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
933 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
935 // On the deadline, he actions should have occured in the right order.
937 task_runner().RunPendingTasks(); // Run posted deadline.
938 EXPECT_EQ(1, client
->num_draws());
939 EXPECT_TRUE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
940 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
941 EXPECT_LT(client
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
942 client
->ActionIndex("ScheduledActionPrepareTiles"));
943 EXPECT_FALSE(scheduler_
->RedrawPending());
944 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
945 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
947 // Request a draw. We don't need a PrepareTiles yet.
949 scheduler_
->SetNeedsRedraw();
950 EXPECT_TRUE(scheduler_
->RedrawPending());
951 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
952 EXPECT_TRUE(client
->needs_begin_frames());
953 EXPECT_EQ(0, client
->num_draws());
955 // We have no immediate actions to perform, so the BeginImplFrame should post
956 // the deadline task.
958 EXPECT_SCOPED(AdvanceFrame());
959 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
960 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
961 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
963 // Draw. The draw will trigger SetNeedsPrepareTiles, and
964 // then the PrepareTiles action will be triggered after the Draw.
965 // Afterwards, neither a draw nor PrepareTiles are pending.
967 task_runner().RunPendingTasks(); // Run posted deadline.
968 EXPECT_EQ(1, client
->num_draws());
969 EXPECT_TRUE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
970 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
971 EXPECT_LT(client
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
972 client
->ActionIndex("ScheduledActionPrepareTiles"));
973 EXPECT_FALSE(scheduler_
->RedrawPending());
974 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
975 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
977 // We need a BeginImplFrame where we don't swap to go idle.
979 EXPECT_SCOPED(AdvanceFrame());
980 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
981 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
983 task_runner().RunPendingTasks(); // Run posted deadline.
984 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
985 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
986 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
987 EXPECT_EQ(0, client
->num_draws());
989 // Now trigger a PrepareTiles outside of a draw. We will then need
990 // a begin-frame for the PrepareTiles, but we don't need a draw.
992 EXPECT_FALSE(client
->needs_begin_frames());
993 scheduler_
->SetNeedsPrepareTiles();
994 EXPECT_TRUE(client
->needs_begin_frames());
995 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
996 EXPECT_FALSE(scheduler_
->RedrawPending());
998 // BeginImplFrame. There will be no draw, only PrepareTiles.
1000 EXPECT_SCOPED(AdvanceFrame());
1001 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
1002 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1004 task_runner().RunPendingTasks(); // Run posted deadline.
1005 EXPECT_EQ(0, client
->num_draws());
1006 EXPECT_FALSE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1007 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
1008 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1011 // Test that PrepareTiles only happens once per frame. If an external caller
1012 // initiates it, then the state machine should not PrepareTiles on that frame.
1013 TEST_F(SchedulerTest
, PrepareTilesOncePerFrame
) {
1014 scheduler_settings_
.use_external_begin_frame_source
= true;
1015 SetUpScheduler(true);
1017 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
1019 scheduler_
->SetNeedsPrepareTiles();
1020 scheduler_
->SetNeedsRedraw();
1022 EXPECT_SCOPED(AdvanceFrame());
1023 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1024 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1025 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1027 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1028 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1029 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1032 task_runner().RunPendingTasks(); // Run posted deadline.
1033 EXPECT_EQ(1, client_
->num_draws());
1034 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1035 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1036 EXPECT_FALSE(scheduler_
->RedrawPending());
1037 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1038 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1040 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1041 scheduler_
->SetNeedsPrepareTiles();
1042 scheduler_
->SetNeedsRedraw();
1044 EXPECT_SCOPED(AdvanceFrame());
1045 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1046 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1047 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1050 task_runner().RunPendingTasks(); // Run posted deadline.
1051 EXPECT_EQ(1, client_
->num_draws());
1052 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1053 EXPECT_TRUE(client_
->HasAction("ScheduledActionPrepareTiles"));
1054 EXPECT_LT(client_
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1055 client_
->ActionIndex("ScheduledActionPrepareTiles"));
1056 EXPECT_FALSE(scheduler_
->RedrawPending());
1057 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1058 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1059 scheduler_
->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1061 // If we get another DidPrepareTiles within the same frame, we should
1062 // not PrepareTiles on the next frame.
1063 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1064 scheduler_
->SetNeedsPrepareTiles();
1065 scheduler_
->SetNeedsRedraw();
1067 EXPECT_SCOPED(AdvanceFrame());
1068 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1069 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1070 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1072 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1075 task_runner().RunPendingTasks(); // Run posted deadline.
1076 EXPECT_EQ(1, client_
->num_draws());
1077 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1078 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1079 EXPECT_FALSE(scheduler_
->RedrawPending());
1080 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1082 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1083 // frame. This verifies we don't alternate calling PrepareTiles once and
1085 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1086 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1087 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1088 scheduler_
->SetNeedsPrepareTiles();
1089 scheduler_
->SetNeedsRedraw();
1091 EXPECT_SCOPED(AdvanceFrame());
1092 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1093 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1094 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1096 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1099 task_runner().RunPendingTasks(); // Run posted deadline.
1100 EXPECT_EQ(1, client_
->num_draws());
1101 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1102 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1103 EXPECT_FALSE(scheduler_
->RedrawPending());
1104 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1106 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1107 scheduler_
->SetNeedsPrepareTiles();
1108 scheduler_
->SetNeedsRedraw();
1110 EXPECT_SCOPED(AdvanceFrame());
1111 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1112 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1113 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1116 task_runner().RunPendingTasks(); // Run posted deadline.
1117 EXPECT_EQ(1, client_
->num_draws());
1118 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1119 EXPECT_TRUE(client_
->HasAction("ScheduledActionPrepareTiles"));
1120 EXPECT_LT(client_
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1121 client_
->ActionIndex("ScheduledActionPrepareTiles"));
1122 EXPECT_FALSE(scheduler_
->RedrawPending());
1123 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1124 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1125 scheduler_
->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1128 TEST_F(SchedulerTest
, TriggerBeginFrameDeadlineEarly
) {
1129 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1130 new SchedulerClientNeedsPrepareTilesInDraw
;
1131 scheduler_settings_
.use_external_begin_frame_source
= true;
1132 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1134 scheduler_
->SetNeedsRedraw();
1135 EXPECT_SCOPED(AdvanceFrame());
1137 // The deadline should be zero since there is no work other than drawing
1139 EXPECT_EQ(base::TimeTicks(), client
->posted_begin_impl_frame_deadline());
1142 TEST_F(SchedulerTest
, WaitForReadyToDrawDoNotPostDeadline
) {
1143 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1144 new SchedulerClientNeedsPrepareTilesInDraw
;
1145 scheduler_settings_
.use_external_begin_frame_source
= true;
1146 scheduler_settings_
.impl_side_painting
= true;
1147 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1149 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1150 scheduler_
->SetNeedsCommit();
1151 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1155 EXPECT_SCOPED(AdvanceFrame());
1156 scheduler_
->NotifyBeginMainFrameStarted();
1157 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1158 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1161 scheduler_
->NotifyReadyToCommit();
1162 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1165 scheduler_
->NotifyReadyToActivate();
1166 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
1168 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1170 scheduler_
->SetWaitForReadyToDraw();
1172 task_runner().RunPendingTasks(); // Try to run posted deadline.
1173 // There is no posted deadline.
1174 EXPECT_NO_ACTION(client_
);
1176 // Scheduler received ready to draw signal, and posted deadline.
1177 scheduler_
->NotifyReadyToDraw();
1179 task_runner().RunPendingTasks(); // Run posted deadline.
1180 EXPECT_EQ(1, client_
->num_draws());
1181 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1184 TEST_F(SchedulerTest
, WaitForReadyToDrawCancelledWhenLostOutputSurface
) {
1185 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1186 new SchedulerClientNeedsPrepareTilesInDraw
;
1187 scheduler_settings_
.use_external_begin_frame_source
= true;
1188 scheduler_settings_
.impl_side_painting
= true;
1189 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1191 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1192 scheduler_
->SetNeedsCommit();
1193 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1197 EXPECT_SCOPED(AdvanceFrame());
1198 scheduler_
->NotifyBeginMainFrameStarted();
1199 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1200 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1203 scheduler_
->NotifyReadyToCommit();
1204 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1207 scheduler_
->NotifyReadyToActivate();
1208 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
1210 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1212 scheduler_
->SetWaitForReadyToDraw();
1214 task_runner().RunPendingTasks(); // Try to run posted deadline.
1215 // There is no posted deadline.
1216 EXPECT_NO_ACTION(client_
);
1218 // Scheduler loses output surface, and stops waiting for ready to draw signal.
1220 scheduler_
->DidLoseOutputSurface();
1221 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1222 task_runner().RunPendingTasks(); // Run posted deadline.
1223 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
1224 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
1225 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
1228 class SchedulerClientWithFixedEstimates
: public FakeSchedulerClient
{
1230 SchedulerClientWithFixedEstimates(
1231 base::TimeDelta draw_duration
,
1232 base::TimeDelta begin_main_frame_to_commit_duration
,
1233 base::TimeDelta commit_to_activate_duration
)
1234 : draw_duration_(draw_duration
),
1235 begin_main_frame_to_commit_duration_(
1236 begin_main_frame_to_commit_duration
),
1237 commit_to_activate_duration_(commit_to_activate_duration
) {}
1239 base::TimeDelta
DrawDurationEstimate() override
{ return draw_duration_
; }
1240 base::TimeDelta
BeginMainFrameToCommitDurationEstimate() override
{
1241 return begin_main_frame_to_commit_duration_
;
1243 base::TimeDelta
CommitToActivateDurationEstimate() override
{
1244 return commit_to_activate_duration_
;
1248 base::TimeDelta draw_duration_
;
1249 base::TimeDelta begin_main_frame_to_commit_duration_
;
1250 base::TimeDelta commit_to_activate_duration_
;
1253 void SchedulerTest::MainFrameInHighLatencyMode(
1254 int64 begin_main_frame_to_commit_estimate_in_ms
,
1255 int64 commit_to_activate_estimate_in_ms
,
1256 bool impl_latency_takes_priority
,
1257 bool should_send_begin_main_frame
) {
1258 // Set up client with specified estimates (draw duration is set to 1).
1259 SchedulerClientWithFixedEstimates
* client
=
1260 new SchedulerClientWithFixedEstimates(
1261 base::TimeDelta::FromMilliseconds(1),
1262 base::TimeDelta::FromMilliseconds(
1263 begin_main_frame_to_commit_estimate_in_ms
),
1264 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms
));
1266 scheduler_settings_
.use_external_begin_frame_source
= true;
1267 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1269 scheduler_
->SetImplLatencyTakesPriority(impl_latency_takes_priority
);
1271 // Impl thread hits deadline before commit finishes.
1272 scheduler_
->SetNeedsCommit();
1273 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1274 EXPECT_SCOPED(AdvanceFrame());
1275 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1276 task_runner().RunPendingTasks(); // Run posted deadline.
1277 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1278 scheduler_
->NotifyBeginMainFrameStarted();
1279 scheduler_
->NotifyReadyToCommit();
1280 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1281 EXPECT_TRUE(client
->HasAction("ScheduledActionSendBeginMainFrame"));
1284 scheduler_
->SetNeedsCommit();
1285 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1286 EXPECT_SCOPED(AdvanceFrame());
1287 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1288 task_runner().RunPendingTasks(); // Run posted deadline.
1289 EXPECT_EQ(scheduler_
->MainThreadIsInHighLatencyMode(),
1290 should_send_begin_main_frame
);
1291 EXPECT_EQ(client
->HasAction("ScheduledActionSendBeginMainFrame"),
1292 should_send_begin_main_frame
);
1295 TEST_F(SchedulerTest
,
1296 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline
) {
1297 // Set up client so that estimates indicate that we can commit and activate
1298 // before the deadline (~8ms by default).
1299 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, false, false));
1302 TEST_F(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong
) {
1303 // Set up client so that estimates indicate that the commit cannot finish
1304 // before the deadline (~8ms by default).
1305 EXPECT_SCOPED(MainFrameInHighLatencyMode(10, 1, false, true));
1308 TEST_F(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong
) {
1309 // Set up client so that estimates indicate that the activate cannot finish
1310 // before the deadline (~8ms by default).
1311 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true));
1314 TEST_F(SchedulerTest
, NotSkipMainFrameInPreferImplLatencyMode
) {
1315 // Set up client so that estimates indicate that we can commit and activate
1316 // before the deadline (~8ms by default), but also enable impl latency takes
1318 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true));
1321 TEST_F(SchedulerTest
, PollForCommitCompletion
) {
1322 // Since we are simulating a long commit, set up a client with draw duration
1323 // estimates that prevent skipping main frames to get to low latency mode.
1324 SchedulerClientWithFixedEstimates
* client
=
1325 new SchedulerClientWithFixedEstimates(
1326 base::TimeDelta::FromMilliseconds(1),
1327 base::TimeDelta::FromMilliseconds(32),
1328 base::TimeDelta::FromMilliseconds(32));
1329 scheduler_settings_
.use_external_begin_frame_source
= true;
1330 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1332 client
->set_log_anticipated_draw_time_change(true);
1334 BeginFrameArgs frame_args
=
1335 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1336 frame_args
.interval
= base::TimeDelta::FromMilliseconds(1000);
1338 // At this point, we've drawn a frame. Start another commit, but hold off on
1339 // the NotifyReadyToCommit for now.
1340 EXPECT_FALSE(scheduler_
->CommitPending());
1341 scheduler_
->SetNeedsCommit();
1342 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args
);
1343 EXPECT_TRUE(scheduler_
->CommitPending());
1345 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1346 // blocking on the renderer.
1347 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1348 task_runner().RunPendingTasks(); // Run posted deadline.
1349 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1350 scheduler_
->DidSwapBuffers();
1352 // Spin the event loop a few times and make sure we get more
1353 // DidAnticipateDrawTimeChange calls every time.
1354 int actions_so_far
= client
->num_actions_();
1356 // Does three iterations to make sure that the timer is properly repeating.
1357 for (int i
= 0; i
< 3; ++i
) {
1358 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1359 task_runner().DelayToNextTaskTime().InMicroseconds())
1360 << scheduler_
->AsValue()->ToString();
1361 task_runner().RunPendingTasks();
1362 EXPECT_GT(client
->num_actions_(), actions_so_far
);
1363 EXPECT_STREQ(client
->Action(client
->num_actions_() - 1),
1364 "DidAnticipatedDrawTimeChange");
1365 actions_so_far
= client
->num_actions_();
1368 // Do the same thing after BeginMainFrame starts but still before activation.
1369 scheduler_
->NotifyBeginMainFrameStarted();
1370 for (int i
= 0; i
< 3; ++i
) {
1371 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1372 task_runner().DelayToNextTaskTime().InMicroseconds())
1373 << scheduler_
->AsValue()->ToString();
1374 task_runner().RunPendingTasks();
1375 EXPECT_GT(client
->num_actions_(), actions_so_far
);
1376 EXPECT_STREQ(client
->Action(client
->num_actions_() - 1),
1377 "DidAnticipatedDrawTimeChange");
1378 actions_so_far
= client
->num_actions_();
1382 TEST_F(SchedulerTest
, BeginRetroFrame
) {
1383 scheduler_settings_
.use_external_begin_frame_source
= true;
1384 SetUpScheduler(true);
1386 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1387 scheduler_
->SetNeedsCommit();
1388 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1391 // Create a BeginFrame with a long deadline to avoid race conditions.
1392 // This is the first BeginFrame, which will be handled immediately.
1393 BeginFrameArgs args
=
1394 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1395 args
.deadline
+= base::TimeDelta::FromHours(1);
1396 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1397 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1398 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1399 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1400 EXPECT_TRUE(client_
->needs_begin_frames());
1403 // Queue BeginFrames while we are still handling the previous BeginFrame.
1404 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1405 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1406 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1407 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1409 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1410 task_runner().RunPendingTasks(); // Run posted deadline.
1411 EXPECT_NO_ACTION(client_
);
1412 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1413 EXPECT_TRUE(client_
->needs_begin_frames());
1416 // NotifyReadyToCommit should trigger the commit.
1417 scheduler_
->NotifyBeginMainFrameStarted();
1418 scheduler_
->NotifyReadyToCommit();
1419 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1420 EXPECT_TRUE(client_
->needs_begin_frames());
1423 // BeginImplFrame should prepare the draw.
1424 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1425 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1426 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1427 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1428 EXPECT_TRUE(client_
->needs_begin_frames());
1431 // BeginImplFrame deadline should draw.
1432 task_runner().RunPendingTasks(); // Run posted deadline.
1433 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
1434 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1435 EXPECT_TRUE(client_
->needs_begin_frames());
1438 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1439 // to avoid excessive toggles.
1440 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1441 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
1442 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1445 task_runner().RunPendingTasks(); // Run posted deadline.
1446 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
1447 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
1451 TEST_F(SchedulerTest
, BeginRetroFrame_SwapThrottled
) {
1452 scheduler_settings_
.use_external_begin_frame_source
= true;
1453 SetUpScheduler(true);
1455 scheduler_
->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1457 // To test swap ack throttling, this test disables automatic swap acks.
1458 scheduler_
->SetMaxSwapsPending(1);
1459 client_
->SetAutomaticSwapAck(false);
1461 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1463 scheduler_
->SetNeedsCommit();
1464 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1467 EXPECT_SCOPED(AdvanceFrame());
1468 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1469 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1470 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1471 EXPECT_TRUE(client_
->needs_begin_frames());
1474 // Queue BeginFrame while we are still handling the previous BeginFrame.
1475 SendNextBeginFrame();
1476 EXPECT_NO_ACTION(client_
);
1477 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1478 EXPECT_TRUE(client_
->needs_begin_frames());
1481 // NotifyReadyToCommit should trigger the pending commit and draw.
1482 scheduler_
->NotifyBeginMainFrameStarted();
1483 scheduler_
->NotifyReadyToCommit();
1484 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1485 EXPECT_TRUE(client_
->needs_begin_frames());
1488 // Swapping will put us into a swap throttled state.
1489 // Run posted deadline.
1490 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1491 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1492 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1493 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1494 EXPECT_TRUE(client_
->needs_begin_frames());
1497 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1498 // and BeginMainFrame.
1499 scheduler_
->SetNeedsCommit();
1500 scheduler_
->SetNeedsRedraw();
1501 // Run posted BeginRetroFrame.
1502 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false));
1503 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
1504 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
1505 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 2, 3);
1506 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1507 EXPECT_TRUE(client_
->needs_begin_frames());
1510 // Let time pass sufficiently beyond the regular deadline but not beyond the
1512 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1513 base::TimeDelta::FromMicroseconds(1));
1514 task_runner().RunUntilTime(now_src()->Now());
1515 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1517 // Take us out of a swap throttled state.
1518 scheduler_
->DidSwapBuffersComplete();
1519 EXPECT_NO_ACTION(client_
);
1520 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1521 EXPECT_TRUE(client_
->needs_begin_frames());
1524 // Verify that the deadline was rescheduled.
1525 task_runner().RunUntilTime(now_src()->Now());
1526 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
1527 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1528 EXPECT_TRUE(client_
->needs_begin_frames());
1532 TEST_F(SchedulerTest
, RetroFrameDoesNotExpireTooEarly
) {
1533 scheduler_settings_
.use_external_begin_frame_source
= true;
1534 SetUpScheduler(true);
1536 scheduler_
->SetNeedsCommit();
1537 EXPECT_TRUE(client_
->needs_begin_frames());
1538 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1541 EXPECT_SCOPED(AdvanceFrame());
1542 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1543 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1544 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1547 scheduler_
->NotifyBeginMainFrameStarted();
1550 SendNextBeginFrame();
1551 // This BeginFrame is queued up as a retro frame.
1552 EXPECT_NO_ACTION(client_
);
1553 // The previous deadline is still pending.
1554 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1557 // This commit should schedule the (previous) deadline to trigger immediately.
1558 scheduler_
->NotifyReadyToCommit();
1559 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1562 // The deadline task should trigger causing a draw.
1563 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1564 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1565 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1566 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1570 scheduler_
->SetNeedsAnimate();
1571 scheduler_
->SetNeedsRedraw();
1572 EXPECT_NO_ACTION(client_
);
1574 // Let's advance sufficiently past the next frame's deadline.
1575 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1576 BeginFrameArgs::DefaultEstimatedParentDrawTime() +
1577 base::TimeDelta::FromMicroseconds(1));
1579 // The retro frame hasn't expired yet.
1580 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false));
1581 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1582 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1583 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1585 // This is an immediate deadline case.
1587 task_runner().RunPendingTasks();
1588 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1589 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
1592 TEST_F(SchedulerTest
, RetroFrameDoesNotExpireTooLate
) {
1593 scheduler_settings_
.use_external_begin_frame_source
= true;
1594 SetUpScheduler(true);
1596 scheduler_
->SetNeedsCommit();
1597 EXPECT_TRUE(client_
->needs_begin_frames());
1598 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1601 EXPECT_SCOPED(AdvanceFrame());
1602 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1603 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1604 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1607 scheduler_
->NotifyBeginMainFrameStarted();
1610 SendNextBeginFrame();
1611 // This BeginFrame is queued up as a retro frame.
1612 EXPECT_NO_ACTION(client_
);
1613 // The previous deadline is still pending.
1614 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1617 // This commit should schedule the (previous) deadline to trigger immediately.
1618 scheduler_
->NotifyReadyToCommit();
1619 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1622 // The deadline task should trigger causing a draw.
1623 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1624 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1625 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1626 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1630 scheduler_
->SetNeedsAnimate();
1631 scheduler_
->SetNeedsRedraw();
1632 EXPECT_NO_ACTION(client_
);
1634 // Let's advance sufficiently past the next frame's deadline.
1635 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() +
1636 base::TimeDelta::FromMicroseconds(1));
1638 // The retro frame should've expired.
1639 EXPECT_NO_ACTION(client_
);
1642 void SchedulerTest::BeginFramesNotFromClient(
1643 bool use_external_begin_frame_source
,
1644 bool throttle_frame_production
) {
1645 scheduler_settings_
.use_external_begin_frame_source
=
1646 use_external_begin_frame_source
;
1647 scheduler_settings_
.throttle_frame_production
= throttle_frame_production
;
1648 SetUpScheduler(true);
1650 // SetNeedsCommit should begin the frame on the next BeginImplFrame
1651 // without calling SetNeedsBeginFrame.
1652 scheduler_
->SetNeedsCommit();
1653 EXPECT_NO_ACTION(client_
);
1656 // When the client-driven BeginFrame are disabled, the scheduler posts it's
1657 // own BeginFrame tasks.
1658 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1659 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1660 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1661 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1664 // If we don't swap on the deadline, we wait for the next BeginFrame.
1665 task_runner().RunPendingTasks(); // Run posted deadline.
1666 EXPECT_NO_ACTION(client_
);
1667 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1670 // NotifyReadyToCommit should trigger the commit.
1671 scheduler_
->NotifyBeginMainFrameStarted();
1672 scheduler_
->NotifyReadyToCommit();
1673 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1676 // BeginImplFrame should prepare the draw.
1677 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1678 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1679 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1680 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1683 // BeginImplFrame deadline should draw.
1684 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1685 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
1686 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1689 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1690 // to avoid excessive toggles.
1691 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1692 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
1693 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1696 // Make sure SetNeedsBeginFrame isn't called on the client
1697 // when the BeginFrame is no longer needed.
1698 task_runner().RunPendingTasks(); // Run posted deadline.
1699 EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_
);
1703 TEST_F(SchedulerTest
, SyntheticBeginFrames
) {
1704 bool use_external_begin_frame_source
= false;
1705 bool throttle_frame_production
= true;
1706 BeginFramesNotFromClient(use_external_begin_frame_source
,
1707 throttle_frame_production
);
1710 TEST_F(SchedulerTest
, VSyncThrottlingDisabled
) {
1711 bool use_external_begin_frame_source
= true;
1712 bool throttle_frame_production
= false;
1713 BeginFramesNotFromClient(use_external_begin_frame_source
,
1714 throttle_frame_production
);
1717 TEST_F(SchedulerTest
, SyntheticBeginFrames_And_VSyncThrottlingDisabled
) {
1718 bool use_external_begin_frame_source
= false;
1719 bool throttle_frame_production
= false;
1720 BeginFramesNotFromClient(use_external_begin_frame_source
,
1721 throttle_frame_production
);
1724 void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
1725 bool use_external_begin_frame_source
,
1726 bool throttle_frame_production
) {
1727 scheduler_settings_
.use_external_begin_frame_source
=
1728 use_external_begin_frame_source
;
1729 scheduler_settings_
.throttle_frame_production
= throttle_frame_production
;
1730 SetUpScheduler(true);
1732 scheduler_
->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1734 // To test swap ack throttling, this test disables automatic swap acks.
1735 scheduler_
->SetMaxSwapsPending(1);
1736 client_
->SetAutomaticSwapAck(false);
1738 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1740 scheduler_
->SetNeedsCommit();
1741 EXPECT_NO_ACTION(client_
);
1744 // Trigger the first BeginImplFrame and BeginMainFrame
1745 EXPECT_SCOPED(AdvanceFrame());
1746 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1747 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1748 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1751 // NotifyReadyToCommit should trigger the pending commit and draw.
1752 scheduler_
->NotifyBeginMainFrameStarted();
1753 scheduler_
->NotifyReadyToCommit();
1754 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1757 // Swapping will put us into a swap throttled state.
1758 // Run posted deadline.
1759 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1760 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1761 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1762 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1765 // While swap throttled, BeginFrames should trigger BeginImplFrames
1766 // and BeginMainFrame.
1767 scheduler_
->SetNeedsCommit();
1768 scheduler_
->SetNeedsRedraw();
1769 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
1770 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
1771 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
1772 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 2, 3);
1773 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1776 // Let time pass sufficiently beyond the regular deadline but not beyond the
1778 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1779 base::TimeDelta::FromMicroseconds(1));
1780 task_runner().RunUntilTime(now_src()->Now());
1781 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1783 // Take us out of a swap throttled state.
1784 scheduler_
->DidSwapBuffersComplete();
1785 EXPECT_NO_ACTION(client_
);
1786 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1789 // Verify that the deadline was rescheduled.
1790 // We can't use RunUntilTime(now) here because the next frame is also
1791 // scheduled if throttle_frame_production = false.
1792 base::TimeTicks before_deadline
= now_src()->Now();
1793 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1794 base::TimeTicks after_deadline
= now_src()->Now();
1795 EXPECT_EQ(after_deadline
, before_deadline
);
1796 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1800 TEST_F(SchedulerTest
, SyntheticBeginFrames_SwapThrottled
) {
1801 bool use_external_begin_frame_source
= false;
1802 bool throttle_frame_production
= true;
1803 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1804 throttle_frame_production
);
1807 TEST_F(SchedulerTest
, VSyncThrottlingDisabled_SwapThrottled
) {
1808 bool use_external_begin_frame_source
= true;
1809 bool throttle_frame_production
= false;
1810 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1811 throttle_frame_production
);
1814 TEST_F(SchedulerTest
,
1815 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled
) {
1816 bool use_external_begin_frame_source
= false;
1817 bool throttle_frame_production
= false;
1818 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1819 throttle_frame_production
);
1822 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized
) {
1823 scheduler_settings_
.use_external_begin_frame_source
= true;
1824 SetUpScheduler(false);
1826 scheduler_
->SetCanStart();
1827 scheduler_
->SetVisible(true);
1828 scheduler_
->SetCanDraw(true);
1830 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
1832 scheduler_
->DidCreateAndInitializeOutputSurface();
1833 EXPECT_NO_ACTION(client_
);
1835 scheduler_
->DidLoseOutputSurface();
1836 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
1839 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterBeginFrameStarted
) {
1840 scheduler_settings_
.use_external_begin_frame_source
= true;
1841 SetUpScheduler(true);
1843 // SetNeedsCommit should begin the frame.
1844 scheduler_
->SetNeedsCommit();
1845 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1848 EXPECT_SCOPED(AdvanceFrame());
1849 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1850 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1851 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1854 scheduler_
->DidLoseOutputSurface();
1855 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1856 EXPECT_NO_ACTION(client_
);
1859 scheduler_
->NotifyBeginMainFrameStarted();
1860 scheduler_
->NotifyReadyToCommit();
1861 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 1);
1864 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1865 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
1866 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
1867 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
1870 void SchedulerTest::DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
1871 bool impl_side_painting
) {
1872 scheduler_settings_
.impl_side_painting
= impl_side_painting
;
1873 scheduler_settings_
.use_external_begin_frame_source
= true;
1874 SetUpScheduler(true);
1876 // SetNeedsCommit should begin the frame.
1877 scheduler_
->SetNeedsCommit();
1878 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1881 EXPECT_SCOPED(AdvanceFrame());
1882 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1883 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1884 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1887 scheduler_
->DidLoseOutputSurface();
1888 // Do nothing when impl frame is in deadine pending state.
1889 EXPECT_NO_ACTION(client_
);
1892 // Run posted deadline.
1893 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1894 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1895 // OnBeginImplFrameDeadline didn't schedule output surface creation because
1896 // main frame is not yet completed.
1897 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
1898 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
1899 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1901 // BeginImplFrame is not started.
1903 task_runner().RunUntilTime(now_src()->Now() +
1904 base::TimeDelta::FromMilliseconds(10));
1905 EXPECT_NO_ACTION(client_
);
1906 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1909 scheduler_
->NotifyBeginMainFrameStarted();
1910 scheduler_
->NotifyReadyToCommit();
1911 if (impl_side_painting
) {
1912 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 3);
1913 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 1, 3);
1914 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 2, 3);
1916 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 2);
1917 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 1, 2);
1921 TEST_F(SchedulerTest
,
1922 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency
) {
1923 bool impl_side_painting
= false;
1924 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
1927 TEST_F(SchedulerTest
,
1928 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint
) {
1929 bool impl_side_painting
= true;
1930 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
1933 void SchedulerTest::DidLoseOutputSurfaceAfterReadyToCommit(
1934 bool impl_side_painting
) {
1935 scheduler_settings_
.impl_side_painting
= impl_side_painting
;
1936 scheduler_settings_
.use_external_begin_frame_source
= true;
1937 SetUpScheduler(true);
1939 // SetNeedsCommit should begin the frame.
1940 scheduler_
->SetNeedsCommit();
1941 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1944 EXPECT_SCOPED(AdvanceFrame());
1945 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1946 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1947 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1950 scheduler_
->NotifyBeginMainFrameStarted();
1951 scheduler_
->NotifyReadyToCommit();
1952 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1955 scheduler_
->DidLoseOutputSurface();
1956 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1957 if (impl_side_painting
) {
1958 // Sync tree should be forced to activate.
1959 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
1961 EXPECT_NO_ACTION(client_
);
1965 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1966 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
1967 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
1968 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
1971 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommit
) {
1972 DidLoseOutputSurfaceAfterReadyToCommit(false);
1975 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting
) {
1976 DidLoseOutputSurfaceAfterReadyToCommit(true);
1979 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles
) {
1980 scheduler_settings_
.use_external_begin_frame_source
= true;
1981 SetUpScheduler(true);
1983 scheduler_
->SetNeedsPrepareTiles();
1984 scheduler_
->SetNeedsRedraw();
1985 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1988 EXPECT_SCOPED(AdvanceFrame());
1989 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1990 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1991 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1994 scheduler_
->DidLoseOutputSurface();
1995 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1996 EXPECT_NO_ACTION(client_
);
1999 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2000 EXPECT_ACTION("ScheduledActionPrepareTiles", client_
, 0, 4);
2001 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 1, 4);
2002 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 2, 4);
2003 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 3, 4);
2006 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterBeginRetroFramePosted
) {
2007 scheduler_settings_
.use_external_begin_frame_source
= true;
2008 SetUpScheduler(true);
2010 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2011 scheduler_
->SetNeedsCommit();
2012 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2014 // Create a BeginFrame with a long deadline to avoid race conditions.
2015 // This is the first BeginFrame, which will be handled immediately.
2017 BeginFrameArgs args
=
2018 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
2019 args
.deadline
+= base::TimeDelta::FromHours(1);
2020 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2021 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2022 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2023 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2024 EXPECT_TRUE(client_
->needs_begin_frames());
2026 // Queue BeginFrames while we are still handling the previous BeginFrame.
2027 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2028 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2029 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2030 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2032 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2034 task_runner().RunPendingTasks(); // Run posted deadline.
2035 EXPECT_NO_ACTION(client_
);
2036 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2037 EXPECT_TRUE(client_
->needs_begin_frames());
2039 // NotifyReadyToCommit should trigger the commit.
2041 scheduler_
->NotifyBeginMainFrameStarted();
2042 scheduler_
->NotifyReadyToCommit();
2043 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2044 EXPECT_TRUE(client_
->needs_begin_frames());
2047 EXPECT_FALSE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2048 scheduler_
->DidLoseOutputSurface();
2049 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2050 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2051 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2052 EXPECT_TRUE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2054 // Posted BeginRetroFrame is aborted.
2056 task_runner().RunPendingTasks();
2057 EXPECT_NO_ACTION(client_
);
2060 TEST_F(SchedulerTest
, DidLoseOutputSurfaceDuringBeginRetroFrameRunning
) {
2061 scheduler_settings_
.use_external_begin_frame_source
= true;
2062 SetUpScheduler(true);
2064 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2065 scheduler_
->SetNeedsCommit();
2066 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2068 // Create a BeginFrame with a long deadline to avoid race conditions.
2069 // This is the first BeginFrame, which will be handled immediately.
2071 BeginFrameArgs args
=
2072 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
2073 args
.deadline
+= base::TimeDelta::FromHours(1);
2074 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2075 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2076 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2077 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2078 EXPECT_TRUE(client_
->needs_begin_frames());
2080 // Queue BeginFrames while we are still handling the previous BeginFrame.
2081 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2082 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2083 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2084 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2086 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2088 task_runner().RunPendingTasks(); // Run posted deadline.
2089 EXPECT_NO_ACTION(client_
);
2090 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2091 EXPECT_TRUE(client_
->needs_begin_frames());
2093 // NotifyReadyToCommit should trigger the commit.
2095 scheduler_
->NotifyBeginMainFrameStarted();
2096 scheduler_
->NotifyReadyToCommit();
2097 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2098 EXPECT_TRUE(client_
->needs_begin_frames());
2100 // BeginImplFrame should prepare the draw.
2102 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2103 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2104 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2105 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2106 EXPECT_TRUE(client_
->needs_begin_frames());
2109 EXPECT_FALSE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2110 scheduler_
->DidLoseOutputSurface();
2111 EXPECT_NO_ACTION(client_
);
2112 EXPECT_TRUE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2114 // BeginImplFrame deadline should abort drawing.
2116 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2117 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2118 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2119 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2120 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2121 EXPECT_FALSE(client_
->needs_begin_frames());
2123 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
2125 task_runner().RunPendingTasks();
2126 EXPECT_NO_ACTION(client_
);
2129 TEST_F(SchedulerTest
, DidLoseOutputSurfaceWithSyntheticBeginFrameSource
) {
2130 SetUpScheduler(true);
2132 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2133 EXPECT_FALSE(scheduler_
->frame_source().NeedsBeginFrames());
2134 scheduler_
->SetNeedsCommit();
2135 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2139 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2140 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2141 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2142 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2144 // NotifyReadyToCommit should trigger the commit.
2146 scheduler_
->NotifyBeginMainFrameStarted();
2147 scheduler_
->NotifyReadyToCommit();
2148 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2149 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2152 scheduler_
->DidLoseOutputSurface();
2153 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2154 EXPECT_NO_ACTION(client_
);
2155 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2158 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2159 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 2);
2160 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
2161 EXPECT_FALSE(scheduler_
->frame_source().NeedsBeginFrames());
2164 TEST_F(SchedulerTest
, DidLoseOutputSurfaceWhenIdle
) {
2165 scheduler_settings_
.use_external_begin_frame_source
= true;
2166 SetUpScheduler(true);
2168 // SetNeedsCommit should begin the frame.
2169 scheduler_
->SetNeedsCommit();
2170 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2173 EXPECT_SCOPED(AdvanceFrame());
2174 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2175 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2176 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2179 scheduler_
->NotifyBeginMainFrameStarted();
2180 scheduler_
->NotifyReadyToCommit();
2181 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2184 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2185 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2186 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2188 // Idle time between BeginFrames.
2190 scheduler_
->DidLoseOutputSurface();
2191 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2192 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2193 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2196 TEST_F(SchedulerTest
, ScheduledActionActivateAfterBecomingInvisible
) {
2197 scheduler_settings_
.impl_side_painting
= true;
2198 scheduler_settings_
.use_external_begin_frame_source
= true;
2199 SetUpScheduler(true);
2201 // SetNeedsCommit should begin the frame.
2202 scheduler_
->SetNeedsCommit();
2203 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2206 EXPECT_SCOPED(AdvanceFrame());
2207 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2208 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2209 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2212 scheduler_
->NotifyBeginMainFrameStarted();
2213 scheduler_
->NotifyReadyToCommit();
2214 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2215 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2218 scheduler_
->SetVisible(false);
2219 task_runner().RunPendingTasks(); // Run posted deadline.
2221 // Sync tree should be forced to activate.
2222 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 0, 3);
2223 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2224 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2227 // Tests to ensure frame sources can be successfully changed while drawing.
2228 TEST_F(SchedulerTest
, SwitchFrameSourceToUnthrottled
) {
2229 scheduler_settings_
.use_external_begin_frame_source
= true;
2230 SetUpScheduler(true);
2232 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2233 scheduler_
->SetNeedsRedraw();
2234 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2237 EXPECT_SCOPED(AdvanceFrame());
2238 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2239 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2240 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2241 EXPECT_TRUE(client_
->needs_begin_frames());
2243 task_runner().RunPendingTasks(); // Run posted deadline.
2244 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2245 scheduler_
->SetNeedsRedraw();
2247 // Switch to an unthrottled frame source.
2248 scheduler_
->SetThrottleFrameProduction(false);
2251 // Unthrottled frame source will immediately begin a new frame.
2252 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2253 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2254 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2255 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2258 // If we don't swap on the deadline, we wait for the next BeginFrame.
2259 task_runner().RunPendingTasks(); // Run posted deadline.
2260 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2261 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2265 // Tests to ensure frame sources can be successfully changed while a frame
2266 // deadline is pending.
2267 TEST_F(SchedulerTest
, SwitchFrameSourceToUnthrottledBeforeDeadline
) {
2268 scheduler_settings_
.use_external_begin_frame_source
= true;
2269 SetUpScheduler(true);
2271 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2272 scheduler_
->SetNeedsRedraw();
2273 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2276 EXPECT_SCOPED(AdvanceFrame());
2277 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2278 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2280 // Switch to an unthrottled frame source before the frame deadline is hit.
2281 scheduler_
->SetThrottleFrameProduction(false);
2284 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2285 EXPECT_TRUE(client_
->needs_begin_frames());
2288 task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame.
2289 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 2);
2290 // Unthrottled frame source will immediately begin a new frame.
2291 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 2);
2292 scheduler_
->SetNeedsRedraw();
2295 task_runner().RunPendingTasks(); // Run posted deadline.
2296 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2297 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2298 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2302 // Tests to ensure that the active frame source can successfully be changed from
2303 // unthrottled to throttled.
2304 TEST_F(SchedulerTest
, SwitchFrameSourceToThrottled
) {
2305 scheduler_settings_
.throttle_frame_production
= false;
2306 scheduler_settings_
.use_external_begin_frame_source
= true;
2307 SetUpScheduler(true);
2309 scheduler_
->SetNeedsRedraw();
2310 EXPECT_NO_ACTION(client_
);
2313 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2314 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2315 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2316 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2319 task_runner().RunPendingTasks(); // Run posted deadline.
2320 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2321 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2324 // Switch to a throttled frame source.
2325 scheduler_
->SetThrottleFrameProduction(true);
2328 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2329 scheduler_
->SetNeedsRedraw();
2330 task_runner().RunPendingTasks();
2331 EXPECT_NO_ACTION(client_
);
2334 EXPECT_SCOPED(AdvanceFrame());
2335 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2336 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2337 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2338 EXPECT_TRUE(client_
->needs_begin_frames());
2340 task_runner().RunPendingTasks(); // Run posted deadline.
2341 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2344 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
2345 TEST_F(SchedulerTest
, SendBeginMainFrameNotExpectedSoon
) {
2346 scheduler_settings_
.use_external_begin_frame_source
= true;
2347 SetUpScheduler(true);
2349 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2350 scheduler_
->SetNeedsCommit();
2351 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2354 // Trigger a frame draw.
2355 EXPECT_SCOPED(AdvanceFrame());
2356 scheduler_
->NotifyBeginMainFrameStarted();
2357 scheduler_
->NotifyReadyToCommit();
2358 task_runner().RunPendingTasks();
2359 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 5);
2360 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 5);
2361 EXPECT_ACTION("ScheduledActionCommit", client_
, 2, 5);
2362 EXPECT_ACTION("ScheduledActionAnimate", client_
, 3, 5);
2363 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 4, 5);
2366 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2367 // and send a SendBeginMainFrameNotExpectedSoon.
2368 EXPECT_SCOPED(AdvanceFrame());
2369 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
2370 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2373 task_runner().RunPendingTasks(); // Run posted deadline.
2374 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
2375 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
2379 TEST_F(SchedulerTest
, UsingSynchronousCompositor
) {
2380 scheduler_settings_
.using_synchronous_renderer_compositor
= true;
2381 scheduler_settings_
.use_external_begin_frame_source
= true;
2382 scheduler_settings_
.impl_side_painting
= true;
2383 SetUpScheduler(true);
2385 // Compositor thread initiated input/animation.
2386 // --------------------------------------------
2387 scheduler_
->SetNeedsAnimate();
2388 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2393 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2394 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
2395 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
2396 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2399 // Continue with animation.
2400 scheduler_
->SetNeedsAnimate();
2401 EXPECT_NO_ACTION(client_
);
2404 scheduler_
->SetNeedsRedraw();
2405 scheduler_
->OnDrawForOutputSurface();
2406 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
2407 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2412 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2413 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
2414 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
2415 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2419 scheduler_
->SetNeedsRedraw();
2420 scheduler_
->OnDrawForOutputSurface();
2421 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
2422 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2425 // Idle on next vsync.
2427 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2428 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2429 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2430 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2433 // Android onDraw after idle.
2434 // --------------------------
2435 scheduler_
->SetNeedsRedraw();
2436 scheduler_
->OnDrawForOutputSurface();
2437 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_
, 0, 3);
2438 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
2439 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 2, 3);
2440 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2443 // Idle on next vsync.
2445 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2446 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2447 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2448 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2451 // Main thread initiated activity.
2452 // -------------------------------
2453 scheduler_
->SetNeedsCommit();
2454 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2459 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2460 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2461 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2464 scheduler_
->NotifyBeginMainFrameStarted();
2465 EXPECT_NO_ACTION(client_
);
2469 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
2470 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2473 scheduler_
->NotifyReadyToCommit();
2474 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2477 scheduler_
->NotifyReadyToActivate();
2478 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
2483 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2484 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
2485 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
2486 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2490 scheduler_
->SetNeedsRedraw();
2491 scheduler_
->OnDrawForOutputSurface();
2492 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
2493 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2496 // Idle on next vsync.
2498 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2499 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2500 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2501 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2505 TEST_F(SchedulerTest
, AuthoritativeVSyncInterval
) {
2506 SetUpScheduler(true);
2508 base::TimeDelta initial_interval
=
2509 scheduler_
->begin_impl_frame_args().interval
;
2510 base::TimeDelta authoritative_interval
=
2511 base::TimeDelta::FromMilliseconds(33);
2513 scheduler_
->SetNeedsCommit();
2514 EXPECT_SCOPED(AdvanceFrame());
2516 EXPECT_EQ(initial_interval
, scheduler_
->begin_impl_frame_args().interval
);
2518 scheduler_
->NotifyBeginMainFrameStarted();
2519 scheduler_
->NotifyReadyToCommit();
2520 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2522 scheduler_
->SetAuthoritativeVSyncInterval(authoritative_interval
);
2524 EXPECT_SCOPED(AdvanceFrame());
2526 // At the next BeginFrame, authoritative interval is used instead of previous
2528 EXPECT_NE(initial_interval
, scheduler_
->begin_impl_frame_args().interval
);
2529 EXPECT_EQ(authoritative_interval
,
2530 scheduler_
->begin_impl_frame_args().interval
);