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 DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{
145 if (log_anticipated_draw_time_change_
)
146 PushAction("DidAnticipatedDrawTimeChange");
148 base::TimeDelta
DrawDurationEstimate() override
{ return base::TimeDelta(); }
149 base::TimeDelta
BeginMainFrameToCommitDurationEstimate() override
{
150 return base::TimeDelta();
152 base::TimeDelta
CommitToActivateDurationEstimate() override
{
153 return base::TimeDelta();
156 void DidBeginImplFrameDeadline() override
{}
158 void SendBeginFramesToChildren(const BeginFrameArgs
& args
) override
{
159 begin_frame_is_sent_to_children_
= true;
162 void SendBeginMainFrameNotExpectedSoon() override
{
163 PushAction("SendBeginMainFrameNotExpectedSoon");
166 base::Callback
<bool(void)> ImplFrameDeadlinePending(bool state
) {
167 return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback
,
168 base::Unretained(this),
172 bool begin_frame_is_sent_to_children() const {
173 return begin_frame_is_sent_to_children_
;
176 void PushAction(const char* description
) {
177 actions_
.push_back(description
);
178 states_
.push_back(scheduler_
->AsValue());
182 bool ImplFrameDeadlinePendingCallback(bool state
) {
183 return scheduler_
->BeginImplFrameDeadlinePending() == state
;
186 bool draw_will_happen_
;
187 bool swap_will_happen_if_draw_happens_
;
188 bool automatic_swap_ack_
;
190 bool log_anticipated_draw_time_change_
;
191 bool begin_frame_is_sent_to_children_
;
192 base::TimeTicks posted_begin_impl_frame_deadline_
;
193 std::vector
<const char*> actions_
;
194 std::vector
<scoped_refptr
<base::trace_event::ConvertableToTraceFormat
>>
196 TestScheduler
* scheduler_
;
199 class FakeExternalBeginFrameSource
: public BeginFrameSourceMixIn
{
201 explicit FakeExternalBeginFrameSource(FakeSchedulerClient
* client
)
203 ~FakeExternalBeginFrameSource() override
{}
205 void OnNeedsBeginFramesChange(bool needs_begin_frames
) override
{
206 if (needs_begin_frames
) {
207 client_
->PushAction("SetNeedsBeginFrames(true)");
209 client_
->PushAction("SetNeedsBeginFrames(false)");
213 void TestOnBeginFrame(const BeginFrameArgs
& args
) {
214 return CallOnBeginFrame(args
);
218 FakeSchedulerClient
* client_
;
221 class SchedulerTest
: public testing::Test
{
224 : now_src_(TestNowSource::Create()),
225 task_runner_(new OrderedSimpleTaskRunner(now_src_
, true)),
226 fake_external_begin_frame_source_(nullptr) {
227 // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval()
228 now_src_
->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
229 // Fail if we need to run 100 tasks in a row.
230 task_runner_
->SetRunTaskLimit(100);
233 ~SchedulerTest() override
{}
236 TestScheduler
* CreateScheduler() {
237 scoped_ptr
<FakeExternalBeginFrameSource
> fake_external_begin_frame_source
;
238 if (scheduler_settings_
.use_external_begin_frame_source
) {
239 fake_external_begin_frame_source
.reset(
240 new FakeExternalBeginFrameSource(client_
.get()));
241 fake_external_begin_frame_source_
=
242 fake_external_begin_frame_source
.get();
244 scheduler_
= TestScheduler::Create(now_src_
, client_
.get(),
245 scheduler_settings_
, 0, task_runner_
,
246 fake_external_begin_frame_source
.Pass());
248 client_
->set_scheduler(scheduler_
.get());
249 return scheduler_
.get();
252 void CreateSchedulerAndInitSurface() {
254 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit());
257 void SetUpScheduler(bool initSurface
) {
258 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient
), initSurface
);
261 void SetUpScheduler(scoped_ptr
<FakeSchedulerClient
> client
,
263 client_
= client
.Pass();
265 CreateSchedulerAndInitSurface();
270 OrderedSimpleTaskRunner
& task_runner() { return *task_runner_
; }
271 TestNowSource
* now_src() { return now_src_
.get(); }
273 // As this function contains EXPECT macros, to allow debugging it should be
274 // called inside EXPECT_SCOPED like so;
275 // EXPECT_SCOPED(client.InitializeOutputSurfaceAndFirstCommit(scheduler));
276 void InitializeOutputSurfaceAndFirstCommit() {
278 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit");
281 // Check the client doesn't have any actions queued when calling this
283 EXPECT_NO_ACTION(client_
);
284 EXPECT_FALSE(client_
->needs_begin_frames());
286 // Start the initial output surface creation.
287 EXPECT_FALSE(scheduler_
->CanStart());
288 scheduler_
->SetCanStart();
289 scheduler_
->SetVisible(true);
290 scheduler_
->SetCanDraw(true);
291 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
295 // We don't see anything happening until the first impl frame.
296 scheduler_
->DidCreateAndInitializeOutputSurface();
297 scheduler_
->SetNeedsCommit();
298 EXPECT_TRUE(client_
->needs_begin_frames());
299 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
303 SCOPED_TRACE("Do first frame to commit after initialize.");
306 scheduler_
->NotifyBeginMainFrameStarted();
307 scheduler_
->NotifyReadyToCommitThenActivateIfNeeded();
309 // Run the posted deadline task.
310 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
311 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
312 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
314 EXPECT_FALSE(scheduler_
->CommitPending());
321 "Run second frame so Scheduler calls SetNeedsBeginFrame(false).");
324 // Run the posted deadline task.
325 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
326 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
327 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
330 EXPECT_FALSE(client_
->needs_begin_frames());
334 // As this function contains EXPECT macros, to allow debugging it should be
335 // called inside EXPECT_SCOPED like so;
336 // EXPECT_SCOPED(client.AdvanceFrame());
337 void AdvanceFrame() {
338 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
339 "FakeSchedulerClient::AdvanceFrame");
340 // Consume any previous deadline first, if no deadline is currently
341 // pending, ImplFrameDeadlinePending will return false straight away and we
342 // will run no tasks.
343 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
344 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
346 // Send the next BeginFrame message if using an external source, otherwise
347 // it will be already in the task queue.
348 if (scheduler_
->settings().use_external_begin_frame_source
&&
349 scheduler_
->FrameProductionThrottled()) {
350 SendNextBeginFrame();
351 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
354 // Then run tasks until new deadline is scheduled.
356 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(false)));
357 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
360 void SendNextBeginFrame() {
361 DCHECK(scheduler_
->settings().use_external_begin_frame_source
);
362 // Creep the time forward so that any BeginFrameArgs is not equal to the
363 // last one otherwise we violate the BeginFrameSource contract.
364 now_src_
->AdvanceNow(BeginFrameArgs::DefaultInterval());
365 fake_external_begin_frame_source_
->TestOnBeginFrame(
366 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src()));
369 FakeExternalBeginFrameSource
* fake_external_begin_frame_source() const {
370 return fake_external_begin_frame_source_
;
373 void MainFrameInHighLatencyMode(
374 int64 begin_main_frame_to_commit_estimate_in_ms
,
375 int64 commit_to_activate_estimate_in_ms
,
376 bool impl_latency_takes_priority
,
377 bool should_send_begin_main_frame
);
378 void BeginFramesNotFromClient(bool use_external_begin_frame_source
,
379 bool throttle_frame_production
);
380 void BeginFramesNotFromClient_SwapThrottled(
381 bool use_external_begin_frame_source
,
382 bool throttle_frame_production
);
383 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
384 bool impl_side_painting
);
385 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting
);
387 scoped_refptr
<TestNowSource
> now_src_
;
388 scoped_refptr
<OrderedSimpleTaskRunner
> task_runner_
;
389 FakeExternalBeginFrameSource
* fake_external_begin_frame_source_
;
390 SchedulerSettings scheduler_settings_
;
391 scoped_ptr
<FakeSchedulerClient
> client_
;
392 scoped_ptr
<TestScheduler
> scheduler_
;
395 TEST_F(SchedulerTest
, InitializeOutputSurfaceDoesNotBeginImplFrame
) {
396 scheduler_settings_
.use_external_begin_frame_source
= true;
397 SetUpScheduler(false);
398 scheduler_
->SetCanStart();
399 scheduler_
->SetVisible(true);
400 scheduler_
->SetCanDraw(true);
402 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
404 scheduler_
->DidCreateAndInitializeOutputSurface();
405 EXPECT_NO_ACTION(client_
);
408 TEST_F(SchedulerTest
, SendBeginFramesToChildren
) {
409 scheduler_settings_
.use_external_begin_frame_source
= true;
410 SetUpScheduler(true);
412 EXPECT_FALSE(client_
->begin_frame_is_sent_to_children());
413 scheduler_
->SetNeedsCommit();
414 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
415 EXPECT_TRUE(client_
->needs_begin_frames());
417 scheduler_
->SetChildrenNeedBeginFrames(true);
420 EXPECT_SCOPED(AdvanceFrame());
421 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
422 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
423 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
424 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
425 EXPECT_TRUE(client_
->needs_begin_frames());
428 TEST_F(SchedulerTest
, SendBeginFramesToChildrenWithoutCommit
) {
429 scheduler_settings_
.use_external_begin_frame_source
= true;
430 SetUpScheduler(true);
432 EXPECT_FALSE(client_
->needs_begin_frames());
433 scheduler_
->SetChildrenNeedBeginFrames(true);
434 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
435 EXPECT_TRUE(client_
->needs_begin_frames());
438 EXPECT_SCOPED(AdvanceFrame());
439 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
442 TEST_F(SchedulerTest
, RequestCommit
) {
443 scheduler_settings_
.use_external_begin_frame_source
= true;
444 SetUpScheduler(true);
446 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
447 scheduler_
->SetNeedsCommit();
448 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
451 EXPECT_SCOPED(AdvanceFrame());
452 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
453 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
454 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
455 EXPECT_TRUE(client_
->needs_begin_frames());
458 // If we don't swap on the deadline, we wait for the next BeginFrame.
459 task_runner().RunPendingTasks(); // Run posted deadline.
460 EXPECT_NO_ACTION(client_
);
461 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
462 EXPECT_TRUE(client_
->needs_begin_frames());
465 // NotifyReadyToCommit should trigger the commit.
466 scheduler_
->NotifyBeginMainFrameStarted();
467 scheduler_
->NotifyReadyToCommit();
468 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
469 EXPECT_TRUE(client_
->needs_begin_frames());
472 // BeginImplFrame should prepare the draw.
473 EXPECT_SCOPED(AdvanceFrame());
474 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
475 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
476 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
477 EXPECT_TRUE(client_
->needs_begin_frames());
480 // BeginImplFrame deadline should draw.
481 task_runner().RunPendingTasks(); // Run posted deadline.
482 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
483 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
484 EXPECT_TRUE(client_
->needs_begin_frames());
487 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
488 // to avoid excessive toggles.
489 EXPECT_SCOPED(AdvanceFrame());
490 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
491 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
494 task_runner().RunPendingTasks(); // Run posted deadline.
495 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
496 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
500 TEST_F(SchedulerTest
, RequestCommitAfterSetDeferCommit
) {
501 scheduler_settings_
.use_external_begin_frame_source
= true;
502 SetUpScheduler(true);
504 scheduler_
->SetDeferCommits(true);
506 scheduler_
->SetNeedsCommit();
507 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
511 // BeginMainFrame is not sent during the defer commit is on.
512 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
515 task_runner().RunPendingTasks(); // Run posted deadline.
516 // There is no posted deadline.
517 EXPECT_NO_ACTION(client_
);
518 EXPECT_TRUE(client_
->needs_begin_frames());
521 scheduler_
->SetDeferCommits(false);
522 EXPECT_NO_ACTION(client_
);
524 // Start new BeginMainFrame after defer commit is off.
527 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
528 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
529 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
532 TEST_F(SchedulerTest
, DeferCommitWithRedraw
) {
533 scheduler_settings_
.use_external_begin_frame_source
= true;
534 SetUpScheduler(true);
536 scheduler_
->SetDeferCommits(true);
538 scheduler_
->SetNeedsCommit();
539 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
542 scheduler_
->SetNeedsRedraw();
543 EXPECT_NO_ACTION(client_
);
547 // BeginMainFrame is not sent during the defer commit is on.
548 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
549 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
552 task_runner().RunPendingTasks(); // Run posted deadline.
553 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
554 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
555 EXPECT_TRUE(client_
->needs_begin_frames());
559 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
562 TEST_F(SchedulerTest
, RequestCommitAfterBeginMainFrameSent
) {
563 scheduler_settings_
.use_external_begin_frame_source
= true;
564 SetUpScheduler(true);
566 // SetNeedsCommit should begin the frame.
567 scheduler_
->SetNeedsCommit();
568 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
571 EXPECT_SCOPED(AdvanceFrame());
572 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
573 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
574 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
576 EXPECT_TRUE(client_
->needs_begin_frames());
579 // Now SetNeedsCommit again. Calling here means we need a second commit.
580 scheduler_
->SetNeedsCommit();
581 EXPECT_EQ(client_
->num_actions_(), 0);
584 // Finish the first commit.
585 scheduler_
->NotifyBeginMainFrameStarted();
586 scheduler_
->NotifyReadyToCommit();
587 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
588 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
590 task_runner().RunPendingTasks(); // Run posted deadline.
591 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
592 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
593 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
595 // Because we just swapped, the Scheduler should also request the next
596 // BeginImplFrame from the OutputSurface.
597 EXPECT_TRUE(client_
->needs_begin_frames());
599 // Since another commit is needed, the next BeginImplFrame should initiate
600 // the second commit.
601 EXPECT_SCOPED(AdvanceFrame());
602 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
603 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
604 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
607 // Finishing the commit before the deadline should post a new deadline task
608 // to trigger the deadline early.
609 scheduler_
->NotifyBeginMainFrameStarted();
610 scheduler_
->NotifyReadyToCommit();
611 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
612 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
614 task_runner().RunPendingTasks(); // Run posted deadline.
615 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
616 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
617 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
618 EXPECT_TRUE(client_
->needs_begin_frames());
621 // On the next BeginImplFrame, verify we go back to a quiescent state and
622 // no longer request BeginImplFrames.
623 EXPECT_SCOPED(AdvanceFrame());
624 task_runner().RunPendingTasks(); // Run posted deadline.
625 EXPECT_FALSE(client_
->needs_begin_frames());
629 class SchedulerClientThatsetNeedsDrawInsideDraw
: public FakeSchedulerClient
{
631 SchedulerClientThatsetNeedsDrawInsideDraw()
632 : FakeSchedulerClient(), request_redraws_(false) {}
634 void ScheduledActionSendBeginMainFrame() override
{}
636 void SetRequestRedrawsInsideDraw(bool enable
) { request_redraws_
= enable
; }
638 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
639 // Only SetNeedsRedraw the first time this is called
640 if (request_redraws_
) {
641 scheduler_
->SetNeedsRedraw();
643 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
646 DrawResult
ScheduledActionDrawAndSwapForced() override
{
651 void ScheduledActionCommit() override
{}
652 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{}
655 bool request_redraws_
;
658 // Tests for two different situations:
659 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
660 // a ScheduledActionDrawAndSwap
661 // 2. the scheduler drawing twice inside a single tick
662 TEST_F(SchedulerTest
, RequestRedrawInsideDraw
) {
663 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
664 new SchedulerClientThatsetNeedsDrawInsideDraw
;
665 scheduler_settings_
.use_external_begin_frame_source
= true;
666 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
667 client
->SetRequestRedrawsInsideDraw(true);
669 scheduler_
->SetNeedsRedraw();
670 EXPECT_TRUE(scheduler_
->RedrawPending());
671 EXPECT_TRUE(client
->needs_begin_frames());
672 EXPECT_EQ(0, client
->num_draws());
674 EXPECT_SCOPED(AdvanceFrame());
675 task_runner().RunPendingTasks(); // Run posted deadline.
676 EXPECT_EQ(1, client
->num_draws());
677 EXPECT_TRUE(scheduler_
->RedrawPending());
678 EXPECT_TRUE(client
->needs_begin_frames());
680 client
->SetRequestRedrawsInsideDraw(false);
682 EXPECT_SCOPED(AdvanceFrame());
683 task_runner().RunPendingTasks(); // Run posted deadline.
684 EXPECT_EQ(2, client_
->num_draws());
685 EXPECT_FALSE(scheduler_
->RedrawPending());
686 EXPECT_TRUE(client
->needs_begin_frames());
688 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
690 EXPECT_SCOPED(AdvanceFrame());
691 task_runner().RunPendingTasks(); // Run posted deadline.
692 EXPECT_EQ(2, client
->num_draws());
693 EXPECT_FALSE(scheduler_
->RedrawPending());
694 EXPECT_FALSE(client
->needs_begin_frames());
697 // Test that requesting redraw inside a failed draw doesn't lose the request.
698 TEST_F(SchedulerTest
, RequestRedrawInsideFailedDraw
) {
699 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
700 new SchedulerClientThatsetNeedsDrawInsideDraw
;
701 scheduler_settings_
.use_external_begin_frame_source
= true;
702 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
704 client
->SetRequestRedrawsInsideDraw(true);
705 client
->SetDrawWillHappen(false);
707 scheduler_
->SetNeedsRedraw();
708 EXPECT_TRUE(scheduler_
->RedrawPending());
709 EXPECT_TRUE(client
->needs_begin_frames());
710 EXPECT_EQ(0, client
->num_draws());
713 EXPECT_SCOPED(AdvanceFrame());
714 task_runner().RunPendingTasks(); // Run posted deadline.
715 EXPECT_EQ(1, client
->num_draws());
717 // We have a commit pending and the draw failed, and we didn't lose the redraw
719 EXPECT_TRUE(scheduler_
->CommitPending());
720 EXPECT_TRUE(scheduler_
->RedrawPending());
721 EXPECT_TRUE(client
->needs_begin_frames());
723 client
->SetRequestRedrawsInsideDraw(false);
725 // Fail the draw again.
726 EXPECT_SCOPED(AdvanceFrame());
727 task_runner().RunPendingTasks(); // Run posted deadline.
728 EXPECT_EQ(2, client
->num_draws());
729 EXPECT_TRUE(scheduler_
->CommitPending());
730 EXPECT_TRUE(scheduler_
->RedrawPending());
731 EXPECT_TRUE(client
->needs_begin_frames());
733 // Draw successfully.
734 client
->SetDrawWillHappen(true);
735 EXPECT_SCOPED(AdvanceFrame());
736 task_runner().RunPendingTasks(); // Run posted deadline.
737 EXPECT_EQ(3, client
->num_draws());
738 EXPECT_TRUE(scheduler_
->CommitPending());
739 EXPECT_FALSE(scheduler_
->RedrawPending());
740 EXPECT_TRUE(client
->needs_begin_frames());
743 class SchedulerClientThatSetNeedsCommitInsideDraw
: public FakeSchedulerClient
{
745 SchedulerClientThatSetNeedsCommitInsideDraw()
746 : set_needs_commit_on_next_draw_(false) {}
748 void ScheduledActionSendBeginMainFrame() override
{}
749 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
750 // Only SetNeedsCommit the first time this is called
751 if (set_needs_commit_on_next_draw_
) {
752 scheduler_
->SetNeedsCommit();
753 set_needs_commit_on_next_draw_
= false;
755 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
758 DrawResult
ScheduledActionDrawAndSwapForced() override
{
763 void ScheduledActionCommit() override
{}
764 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{}
766 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_
= true; }
769 bool set_needs_commit_on_next_draw_
;
772 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
773 // happen inside a ScheduledActionDrawAndSwap
774 TEST_F(SchedulerTest
, RequestCommitInsideDraw
) {
775 SchedulerClientThatSetNeedsCommitInsideDraw
* client
=
776 new SchedulerClientThatSetNeedsCommitInsideDraw
;
778 scheduler_settings_
.use_external_begin_frame_source
= true;
779 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
781 EXPECT_FALSE(client
->needs_begin_frames());
782 scheduler_
->SetNeedsRedraw();
783 EXPECT_TRUE(scheduler_
->RedrawPending());
784 EXPECT_EQ(0, client
->num_draws());
785 EXPECT_TRUE(client
->needs_begin_frames());
787 client
->SetNeedsCommitOnNextDraw();
788 EXPECT_SCOPED(AdvanceFrame());
789 client
->SetNeedsCommitOnNextDraw();
790 task_runner().RunPendingTasks(); // Run posted deadline.
791 EXPECT_EQ(1, client
->num_draws());
792 EXPECT_TRUE(scheduler_
->CommitPending());
793 EXPECT_TRUE(client
->needs_begin_frames());
794 scheduler_
->NotifyBeginMainFrameStarted();
795 scheduler_
->NotifyReadyToCommit();
797 EXPECT_SCOPED(AdvanceFrame());
798 task_runner().RunPendingTasks(); // Run posted deadline.
799 EXPECT_EQ(2, client
->num_draws());
801 EXPECT_FALSE(scheduler_
->RedrawPending());
802 EXPECT_FALSE(scheduler_
->CommitPending());
803 EXPECT_TRUE(client
->needs_begin_frames());
805 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
807 EXPECT_SCOPED(AdvanceFrame());
808 task_runner().RunPendingTasks(); // Run posted deadline.
809 EXPECT_EQ(2, client
->num_draws());
810 EXPECT_FALSE(scheduler_
->RedrawPending());
811 EXPECT_FALSE(scheduler_
->CommitPending());
812 EXPECT_FALSE(client
->needs_begin_frames());
815 // Tests that when a draw fails then the pending commit should not be dropped.
816 TEST_F(SchedulerTest
, RequestCommitInsideFailedDraw
) {
817 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
818 new SchedulerClientThatsetNeedsDrawInsideDraw
;
819 scheduler_settings_
.use_external_begin_frame_source
= true;
820 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
822 client
->SetDrawWillHappen(false);
824 scheduler_
->SetNeedsRedraw();
825 EXPECT_TRUE(scheduler_
->RedrawPending());
826 EXPECT_TRUE(client
->needs_begin_frames());
827 EXPECT_EQ(0, client
->num_draws());
830 EXPECT_SCOPED(AdvanceFrame());
831 task_runner().RunPendingTasks(); // Run posted deadline.
832 EXPECT_EQ(1, client
->num_draws());
834 // We have a commit pending and the draw failed, and we didn't lose the commit
836 EXPECT_TRUE(scheduler_
->CommitPending());
837 EXPECT_TRUE(scheduler_
->RedrawPending());
838 EXPECT_TRUE(client
->needs_begin_frames());
840 // Fail the draw again.
841 EXPECT_SCOPED(AdvanceFrame());
843 task_runner().RunPendingTasks(); // Run posted deadline.
844 EXPECT_EQ(2, client
->num_draws());
845 EXPECT_TRUE(scheduler_
->CommitPending());
846 EXPECT_TRUE(scheduler_
->RedrawPending());
847 EXPECT_TRUE(client
->needs_begin_frames());
849 // Draw successfully.
850 client
->SetDrawWillHappen(true);
851 EXPECT_SCOPED(AdvanceFrame());
852 task_runner().RunPendingTasks(); // Run posted deadline.
853 EXPECT_EQ(3, client
->num_draws());
854 EXPECT_TRUE(scheduler_
->CommitPending());
855 EXPECT_FALSE(scheduler_
->RedrawPending());
856 EXPECT_TRUE(client
->needs_begin_frames());
859 TEST_F(SchedulerTest
, NoSwapWhenDrawFails
) {
860 SchedulerClientThatSetNeedsCommitInsideDraw
* client
=
861 new SchedulerClientThatSetNeedsCommitInsideDraw
;
862 scheduler_settings_
.use_external_begin_frame_source
= true;
863 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
865 scheduler_
->SetNeedsRedraw();
866 EXPECT_TRUE(scheduler_
->RedrawPending());
867 EXPECT_TRUE(client
->needs_begin_frames());
868 EXPECT_EQ(0, client
->num_draws());
870 // Draw successfully, this starts a new frame.
871 client
->SetNeedsCommitOnNextDraw();
872 EXPECT_SCOPED(AdvanceFrame());
873 task_runner().RunPendingTasks(); // Run posted deadline.
874 EXPECT_EQ(1, client
->num_draws());
876 scheduler_
->SetNeedsRedraw();
877 EXPECT_TRUE(scheduler_
->RedrawPending());
878 EXPECT_TRUE(client
->needs_begin_frames());
880 // Fail to draw, this should not start a frame.
881 client
->SetDrawWillHappen(false);
882 client
->SetNeedsCommitOnNextDraw();
883 EXPECT_SCOPED(AdvanceFrame());
884 task_runner().RunPendingTasks(); // Run posted deadline.
885 EXPECT_EQ(2, client
->num_draws());
888 class SchedulerClientNeedsPrepareTilesInDraw
: public FakeSchedulerClient
{
890 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
891 scheduler_
->SetNeedsPrepareTiles();
892 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
896 // Test prepare tiles is independant of draws.
897 TEST_F(SchedulerTest
, PrepareTiles
) {
898 SchedulerClientNeedsPrepareTilesInDraw
* client
=
899 new SchedulerClientNeedsPrepareTilesInDraw
;
900 scheduler_settings_
.use_external_begin_frame_source
= true;
901 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
903 // Request both draw and prepare tiles. PrepareTiles shouldn't
904 // be trigged until BeginImplFrame.
906 scheduler_
->SetNeedsPrepareTiles();
907 scheduler_
->SetNeedsRedraw();
908 EXPECT_TRUE(scheduler_
->RedrawPending());
909 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
910 EXPECT_TRUE(client
->needs_begin_frames());
911 EXPECT_EQ(0, client
->num_draws());
912 EXPECT_FALSE(client
->HasAction("ScheduledActionPrepareTiles"));
913 EXPECT_FALSE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
915 // We have no immediate actions to perform, so the BeginImplFrame should post
916 // the deadline task.
918 EXPECT_SCOPED(AdvanceFrame());
919 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
920 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
921 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
923 // On the deadline, he actions should have occured in the right order.
925 task_runner().RunPendingTasks(); // Run posted deadline.
926 EXPECT_EQ(1, client
->num_draws());
927 EXPECT_TRUE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
928 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
929 EXPECT_LT(client
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
930 client
->ActionIndex("ScheduledActionPrepareTiles"));
931 EXPECT_FALSE(scheduler_
->RedrawPending());
932 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
933 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
935 // Request a draw. We don't need a PrepareTiles yet.
937 scheduler_
->SetNeedsRedraw();
938 EXPECT_TRUE(scheduler_
->RedrawPending());
939 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
940 EXPECT_TRUE(client
->needs_begin_frames());
941 EXPECT_EQ(0, client
->num_draws());
943 // We have no immediate actions to perform, so the BeginImplFrame should post
944 // the deadline task.
946 EXPECT_SCOPED(AdvanceFrame());
947 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
948 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
949 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
951 // Draw. The draw will trigger SetNeedsPrepareTiles, and
952 // then the PrepareTiles action will be triggered after the Draw.
953 // Afterwards, neither a draw nor PrepareTiles are pending.
955 task_runner().RunPendingTasks(); // Run posted deadline.
956 EXPECT_EQ(1, client
->num_draws());
957 EXPECT_TRUE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
958 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
959 EXPECT_LT(client
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
960 client
->ActionIndex("ScheduledActionPrepareTiles"));
961 EXPECT_FALSE(scheduler_
->RedrawPending());
962 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
963 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
965 // We need a BeginImplFrame where we don't swap to go idle.
967 EXPECT_SCOPED(AdvanceFrame());
968 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
969 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
971 task_runner().RunPendingTasks(); // Run posted deadline.
972 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
973 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
974 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
975 EXPECT_EQ(0, client
->num_draws());
977 // Now trigger a PrepareTiles outside of a draw. We will then need
978 // a begin-frame for the PrepareTiles, but we don't need a draw.
980 EXPECT_FALSE(client
->needs_begin_frames());
981 scheduler_
->SetNeedsPrepareTiles();
982 EXPECT_TRUE(client
->needs_begin_frames());
983 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
984 EXPECT_FALSE(scheduler_
->RedrawPending());
986 // BeginImplFrame. There will be no draw, only PrepareTiles.
988 EXPECT_SCOPED(AdvanceFrame());
989 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
990 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
992 task_runner().RunPendingTasks(); // Run posted deadline.
993 EXPECT_EQ(0, client
->num_draws());
994 EXPECT_FALSE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
995 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
996 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
999 // Test that PrepareTiles only happens once per frame. If an external caller
1000 // initiates it, then the state machine should not PrepareTiles on that frame.
1001 TEST_F(SchedulerTest
, PrepareTilesOncePerFrame
) {
1002 scheduler_settings_
.use_external_begin_frame_source
= true;
1003 SetUpScheduler(true);
1005 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
1007 scheduler_
->SetNeedsPrepareTiles();
1008 scheduler_
->SetNeedsRedraw();
1010 EXPECT_SCOPED(AdvanceFrame());
1011 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1012 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1013 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1015 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1016 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1017 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1020 task_runner().RunPendingTasks(); // Run posted deadline.
1021 EXPECT_EQ(1, client_
->num_draws());
1022 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1023 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1024 EXPECT_FALSE(scheduler_
->RedrawPending());
1025 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1026 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1028 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1029 scheduler_
->SetNeedsPrepareTiles();
1030 scheduler_
->SetNeedsRedraw();
1032 EXPECT_SCOPED(AdvanceFrame());
1033 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1034 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1035 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1038 task_runner().RunPendingTasks(); // Run posted deadline.
1039 EXPECT_EQ(1, client_
->num_draws());
1040 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1041 EXPECT_TRUE(client_
->HasAction("ScheduledActionPrepareTiles"));
1042 EXPECT_LT(client_
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1043 client_
->ActionIndex("ScheduledActionPrepareTiles"));
1044 EXPECT_FALSE(scheduler_
->RedrawPending());
1045 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1046 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1047 scheduler_
->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1049 // If we get another DidPrepareTiles within the same frame, we should
1050 // not PrepareTiles on the next frame.
1051 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1052 scheduler_
->SetNeedsPrepareTiles();
1053 scheduler_
->SetNeedsRedraw();
1055 EXPECT_SCOPED(AdvanceFrame());
1056 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1057 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1058 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1060 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1063 task_runner().RunPendingTasks(); // Run posted deadline.
1064 EXPECT_EQ(1, client_
->num_draws());
1065 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1066 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1067 EXPECT_FALSE(scheduler_
->RedrawPending());
1068 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1070 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1071 // frame. This verifies we don't alternate calling PrepareTiles once and
1073 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1074 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1075 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1076 scheduler_
->SetNeedsPrepareTiles();
1077 scheduler_
->SetNeedsRedraw();
1079 EXPECT_SCOPED(AdvanceFrame());
1080 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1081 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1082 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1084 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1087 task_runner().RunPendingTasks(); // Run posted deadline.
1088 EXPECT_EQ(1, client_
->num_draws());
1089 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1090 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1091 EXPECT_FALSE(scheduler_
->RedrawPending());
1092 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1094 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1095 scheduler_
->SetNeedsPrepareTiles();
1096 scheduler_
->SetNeedsRedraw();
1098 EXPECT_SCOPED(AdvanceFrame());
1099 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1100 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1101 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1104 task_runner().RunPendingTasks(); // Run posted deadline.
1105 EXPECT_EQ(1, client_
->num_draws());
1106 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1107 EXPECT_TRUE(client_
->HasAction("ScheduledActionPrepareTiles"));
1108 EXPECT_LT(client_
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1109 client_
->ActionIndex("ScheduledActionPrepareTiles"));
1110 EXPECT_FALSE(scheduler_
->RedrawPending());
1111 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1112 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1113 scheduler_
->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1116 TEST_F(SchedulerTest
, TriggerBeginFrameDeadlineEarly
) {
1117 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1118 new SchedulerClientNeedsPrepareTilesInDraw
;
1119 scheduler_settings_
.use_external_begin_frame_source
= true;
1120 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1122 scheduler_
->SetNeedsRedraw();
1123 EXPECT_SCOPED(AdvanceFrame());
1125 // The deadline should be zero since there is no work other than drawing
1127 EXPECT_EQ(base::TimeTicks(), client
->posted_begin_impl_frame_deadline());
1130 class SchedulerClientWithFixedEstimates
: public FakeSchedulerClient
{
1132 SchedulerClientWithFixedEstimates(
1133 base::TimeDelta draw_duration
,
1134 base::TimeDelta begin_main_frame_to_commit_duration
,
1135 base::TimeDelta commit_to_activate_duration
)
1136 : draw_duration_(draw_duration
),
1137 begin_main_frame_to_commit_duration_(
1138 begin_main_frame_to_commit_duration
),
1139 commit_to_activate_duration_(commit_to_activate_duration
) {}
1141 base::TimeDelta
DrawDurationEstimate() override
{ return draw_duration_
; }
1142 base::TimeDelta
BeginMainFrameToCommitDurationEstimate() override
{
1143 return begin_main_frame_to_commit_duration_
;
1145 base::TimeDelta
CommitToActivateDurationEstimate() override
{
1146 return commit_to_activate_duration_
;
1150 base::TimeDelta draw_duration_
;
1151 base::TimeDelta begin_main_frame_to_commit_duration_
;
1152 base::TimeDelta commit_to_activate_duration_
;
1155 void SchedulerTest::MainFrameInHighLatencyMode(
1156 int64 begin_main_frame_to_commit_estimate_in_ms
,
1157 int64 commit_to_activate_estimate_in_ms
,
1158 bool impl_latency_takes_priority
,
1159 bool should_send_begin_main_frame
) {
1160 // Set up client with specified estimates (draw duration is set to 1).
1161 SchedulerClientWithFixedEstimates
* client
=
1162 new SchedulerClientWithFixedEstimates(
1163 base::TimeDelta::FromMilliseconds(1),
1164 base::TimeDelta::FromMilliseconds(
1165 begin_main_frame_to_commit_estimate_in_ms
),
1166 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms
));
1168 scheduler_settings_
.use_external_begin_frame_source
= true;
1169 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1171 scheduler_
->SetImplLatencyTakesPriority(impl_latency_takes_priority
);
1173 // Impl thread hits deadline before commit finishes.
1174 scheduler_
->SetNeedsCommit();
1175 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1176 EXPECT_SCOPED(AdvanceFrame());
1177 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1178 task_runner().RunPendingTasks(); // Run posted deadline.
1179 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1180 scheduler_
->NotifyBeginMainFrameStarted();
1181 scheduler_
->NotifyReadyToCommit();
1182 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1183 EXPECT_TRUE(client
->HasAction("ScheduledActionSendBeginMainFrame"));
1186 scheduler_
->SetNeedsCommit();
1187 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1188 EXPECT_SCOPED(AdvanceFrame());
1189 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1190 task_runner().RunPendingTasks(); // Run posted deadline.
1191 EXPECT_EQ(scheduler_
->MainThreadIsInHighLatencyMode(),
1192 should_send_begin_main_frame
);
1193 EXPECT_EQ(client
->HasAction("ScheduledActionSendBeginMainFrame"),
1194 should_send_begin_main_frame
);
1197 TEST_F(SchedulerTest
,
1198 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline
) {
1199 // Set up client so that estimates indicate that we can commit and activate
1200 // before the deadline (~8ms by default).
1201 MainFrameInHighLatencyMode(1, 1, false, false);
1204 TEST_F(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong
) {
1205 // Set up client so that estimates indicate that the commit cannot finish
1206 // before the deadline (~8ms by default).
1207 MainFrameInHighLatencyMode(10, 1, false, true);
1210 TEST_F(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong
) {
1211 // Set up client so that estimates indicate that the activate cannot finish
1212 // before the deadline (~8ms by default).
1213 MainFrameInHighLatencyMode(1, 10, false, true);
1216 TEST_F(SchedulerTest
, NotSkipMainFrameInPreferImplLatencyMode
) {
1217 // Set up client so that estimates indicate that we can commit and activate
1218 // before the deadline (~8ms by default), but also enable impl latency takes
1220 MainFrameInHighLatencyMode(1, 1, true, true);
1223 TEST_F(SchedulerTest
, PollForCommitCompletion
) {
1224 // Since we are simulating a long commit, set up a client with draw duration
1225 // estimates that prevent skipping main frames to get to low latency mode.
1226 SchedulerClientWithFixedEstimates
* client
=
1227 new SchedulerClientWithFixedEstimates(
1228 base::TimeDelta::FromMilliseconds(1),
1229 base::TimeDelta::FromMilliseconds(32),
1230 base::TimeDelta::FromMilliseconds(32));
1231 scheduler_settings_
.use_external_begin_frame_source
= true;
1232 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1234 client
->set_log_anticipated_draw_time_change(true);
1236 BeginFrameArgs frame_args
=
1237 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1238 frame_args
.interval
= base::TimeDelta::FromMilliseconds(1000);
1240 // At this point, we've drawn a frame. Start another commit, but hold off on
1241 // the NotifyReadyToCommit for now.
1242 EXPECT_FALSE(scheduler_
->CommitPending());
1243 scheduler_
->SetNeedsCommit();
1244 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args
);
1245 EXPECT_TRUE(scheduler_
->CommitPending());
1247 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1248 // blocking on the renderer.
1249 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1250 task_runner().RunPendingTasks(); // Run posted deadline.
1251 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1252 scheduler_
->DidSwapBuffers();
1254 // Spin the event loop a few times and make sure we get more
1255 // DidAnticipateDrawTimeChange calls every time.
1256 int actions_so_far
= client
->num_actions_();
1258 // Does three iterations to make sure that the timer is properly repeating.
1259 for (int i
= 0; i
< 3; ++i
) {
1260 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1261 task_runner().DelayToNextTaskTime().InMicroseconds())
1262 << scheduler_
->AsValue()->ToString();
1263 task_runner().RunPendingTasks();
1264 EXPECT_GT(client
->num_actions_(), actions_so_far
);
1265 EXPECT_STREQ(client
->Action(client
->num_actions_() - 1),
1266 "DidAnticipatedDrawTimeChange");
1267 actions_so_far
= client
->num_actions_();
1270 // Do the same thing after BeginMainFrame starts but still before activation.
1271 scheduler_
->NotifyBeginMainFrameStarted();
1272 for (int i
= 0; i
< 3; ++i
) {
1273 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1274 task_runner().DelayToNextTaskTime().InMicroseconds())
1275 << scheduler_
->AsValue()->ToString();
1276 task_runner().RunPendingTasks();
1277 EXPECT_GT(client
->num_actions_(), actions_so_far
);
1278 EXPECT_STREQ(client
->Action(client
->num_actions_() - 1),
1279 "DidAnticipatedDrawTimeChange");
1280 actions_so_far
= client
->num_actions_();
1284 TEST_F(SchedulerTest
, BeginRetroFrame
) {
1285 scheduler_settings_
.use_external_begin_frame_source
= true;
1286 SetUpScheduler(true);
1288 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1289 scheduler_
->SetNeedsCommit();
1290 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1293 // Create a BeginFrame with a long deadline to avoid race conditions.
1294 // This is the first BeginFrame, which will be handled immediately.
1295 BeginFrameArgs args
=
1296 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1297 args
.deadline
+= base::TimeDelta::FromHours(1);
1298 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1299 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1300 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1301 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1302 EXPECT_TRUE(client_
->needs_begin_frames());
1305 // Queue BeginFrames while we are still handling the previous BeginFrame.
1306 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1307 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1308 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1309 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1311 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1312 task_runner().RunPendingTasks(); // Run posted deadline.
1313 EXPECT_NO_ACTION(client_
);
1314 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1315 EXPECT_TRUE(client_
->needs_begin_frames());
1318 // NotifyReadyToCommit should trigger the commit.
1319 scheduler_
->NotifyBeginMainFrameStarted();
1320 scheduler_
->NotifyReadyToCommit();
1321 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1322 EXPECT_TRUE(client_
->needs_begin_frames());
1325 // BeginImplFrame should prepare the draw.
1326 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1327 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1328 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1329 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1330 EXPECT_TRUE(client_
->needs_begin_frames());
1333 // BeginImplFrame deadline should draw.
1334 task_runner().RunPendingTasks(); // Run posted deadline.
1335 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
1336 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1337 EXPECT_TRUE(client_
->needs_begin_frames());
1340 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1341 // to avoid excessive toggles.
1342 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1343 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
1344 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1347 task_runner().RunPendingTasks(); // Run posted deadline.
1348 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
1349 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
1353 TEST_F(SchedulerTest
, BeginRetroFrame_SwapThrottled
) {
1354 scheduler_settings_
.use_external_begin_frame_source
= true;
1355 SetUpScheduler(true);
1357 scheduler_
->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1359 // To test swap ack throttling, this test disables automatic swap acks.
1360 scheduler_
->SetMaxSwapsPending(1);
1361 client_
->SetAutomaticSwapAck(false);
1363 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1365 scheduler_
->SetNeedsCommit();
1366 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1369 EXPECT_SCOPED(AdvanceFrame());
1370 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1371 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1372 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1373 EXPECT_TRUE(client_
->needs_begin_frames());
1376 // Queue BeginFrame while we are still handling the previous BeginFrame.
1377 SendNextBeginFrame();
1378 EXPECT_NO_ACTION(client_
);
1379 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1380 EXPECT_TRUE(client_
->needs_begin_frames());
1383 // NotifyReadyToCommit should trigger the pending commit and draw.
1384 scheduler_
->NotifyBeginMainFrameStarted();
1385 scheduler_
->NotifyReadyToCommit();
1386 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1387 EXPECT_TRUE(client_
->needs_begin_frames());
1390 // Swapping will put us into a swap throttled state.
1391 // Run posted deadline.
1392 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1393 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1394 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1395 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1396 EXPECT_TRUE(client_
->needs_begin_frames());
1399 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1400 // but not a BeginMainFrame or draw.
1401 scheduler_
->SetNeedsCommit();
1402 scheduler_
->SetNeedsRedraw();
1403 // Run posted BeginRetroFrame.
1404 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false));
1405 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1406 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1407 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1408 EXPECT_TRUE(client_
->needs_begin_frames());
1411 // Let time pass sufficiently beyond the regular deadline but not beyond the
1413 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1414 base::TimeDelta::FromMicroseconds(1));
1415 task_runner().RunUntilTime(now_src()->Now());
1416 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1418 // Take us out of a swap throttled state.
1419 scheduler_
->DidSwapBuffersComplete();
1420 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_
);
1421 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1422 EXPECT_TRUE(client_
->needs_begin_frames());
1425 // Verify that the deadline was rescheduled.
1426 task_runner().RunUntilTime(now_src()->Now());
1427 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
1428 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1429 EXPECT_TRUE(client_
->needs_begin_frames());
1433 TEST_F(SchedulerTest
, RetroFrameDoesNotExpireTooEarly
) {
1434 scheduler_settings_
.use_external_begin_frame_source
= true;
1435 SetUpScheduler(true);
1437 scheduler_
->SetNeedsCommit();
1438 EXPECT_TRUE(client_
->needs_begin_frames());
1439 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1442 EXPECT_SCOPED(AdvanceFrame());
1443 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1444 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1445 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1448 scheduler_
->NotifyBeginMainFrameStarted();
1451 SendNextBeginFrame();
1452 // This BeginFrame is queued up as a retro frame.
1453 EXPECT_NO_ACTION(client_
);
1454 // The previous deadline is still pending.
1455 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1458 // This commit should schedule the (previous) deadline to trigger immediately.
1459 scheduler_
->NotifyReadyToCommit();
1460 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1463 // The deadline task should trigger causing a draw.
1464 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1465 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1466 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1467 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1471 scheduler_
->SetNeedsAnimate();
1472 scheduler_
->SetNeedsRedraw();
1473 EXPECT_NO_ACTION(client_
);
1475 // Let's advance sufficiently past the next frame's deadline.
1476 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1477 BeginFrameArgs::DefaultEstimatedParentDrawTime() +
1478 base::TimeDelta::FromMicroseconds(1));
1480 // The retro frame hasn't expired yet.
1481 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false));
1482 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1483 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1484 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1486 // This is an immediate deadline case.
1488 task_runner().RunPendingTasks();
1489 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1490 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
1493 TEST_F(SchedulerTest
, RetroFrameDoesNotExpireTooLate
) {
1494 scheduler_settings_
.use_external_begin_frame_source
= true;
1495 SetUpScheduler(true);
1497 scheduler_
->SetNeedsCommit();
1498 EXPECT_TRUE(client_
->needs_begin_frames());
1499 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1502 EXPECT_SCOPED(AdvanceFrame());
1503 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1504 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1505 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1508 scheduler_
->NotifyBeginMainFrameStarted();
1511 SendNextBeginFrame();
1512 // This BeginFrame is queued up as a retro frame.
1513 EXPECT_NO_ACTION(client_
);
1514 // The previous deadline is still pending.
1515 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1518 // This commit should schedule the (previous) deadline to trigger immediately.
1519 scheduler_
->NotifyReadyToCommit();
1520 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1523 // The deadline task should trigger causing a draw.
1524 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1525 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1526 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1527 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1531 scheduler_
->SetNeedsAnimate();
1532 scheduler_
->SetNeedsRedraw();
1533 EXPECT_NO_ACTION(client_
);
1535 // Let's advance sufficiently past the next frame's deadline.
1536 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() +
1537 base::TimeDelta::FromMicroseconds(1));
1539 // The retro frame should've expired.
1540 EXPECT_NO_ACTION(client_
);
1543 void SchedulerTest::BeginFramesNotFromClient(
1544 bool use_external_begin_frame_source
,
1545 bool throttle_frame_production
) {
1546 scheduler_settings_
.use_external_begin_frame_source
=
1547 use_external_begin_frame_source
;
1548 scheduler_settings_
.throttle_frame_production
= throttle_frame_production
;
1549 SetUpScheduler(true);
1551 // SetNeedsCommit should begin the frame on the next BeginImplFrame
1552 // without calling SetNeedsBeginFrame.
1553 scheduler_
->SetNeedsCommit();
1554 EXPECT_NO_ACTION(client_
);
1557 // When the client-driven BeginFrame are disabled, the scheduler posts it's
1558 // own BeginFrame tasks.
1559 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1560 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1561 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1562 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1565 // If we don't swap on the deadline, we wait for the next BeginFrame.
1566 task_runner().RunPendingTasks(); // Run posted deadline.
1567 EXPECT_NO_ACTION(client_
);
1568 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1571 // NotifyReadyToCommit should trigger the commit.
1572 scheduler_
->NotifyBeginMainFrameStarted();
1573 scheduler_
->NotifyReadyToCommit();
1574 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1577 // BeginImplFrame should prepare the draw.
1578 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1579 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1580 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1581 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1584 // BeginImplFrame deadline should draw.
1585 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1586 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
1587 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1590 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1591 // to avoid excessive toggles.
1592 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1593 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
1594 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1597 // Make sure SetNeedsBeginFrame isn't called on the client
1598 // when the BeginFrame is no longer needed.
1599 task_runner().RunPendingTasks(); // Run posted deadline.
1600 EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_
);
1604 TEST_F(SchedulerTest
, SyntheticBeginFrames
) {
1605 bool use_external_begin_frame_source
= false;
1606 bool throttle_frame_production
= true;
1607 BeginFramesNotFromClient(use_external_begin_frame_source
,
1608 throttle_frame_production
);
1611 TEST_F(SchedulerTest
, VSyncThrottlingDisabled
) {
1612 bool use_external_begin_frame_source
= true;
1613 bool throttle_frame_production
= false;
1614 BeginFramesNotFromClient(use_external_begin_frame_source
,
1615 throttle_frame_production
);
1618 TEST_F(SchedulerTest
, SyntheticBeginFrames_And_VSyncThrottlingDisabled
) {
1619 bool use_external_begin_frame_source
= false;
1620 bool throttle_frame_production
= false;
1621 BeginFramesNotFromClient(use_external_begin_frame_source
,
1622 throttle_frame_production
);
1625 void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
1626 bool use_external_begin_frame_source
,
1627 bool throttle_frame_production
) {
1628 scheduler_settings_
.use_external_begin_frame_source
=
1629 use_external_begin_frame_source
;
1630 scheduler_settings_
.throttle_frame_production
= throttle_frame_production
;
1631 SetUpScheduler(true);
1633 scheduler_
->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1635 // To test swap ack throttling, this test disables automatic swap acks.
1636 scheduler_
->SetMaxSwapsPending(1);
1637 client_
->SetAutomaticSwapAck(false);
1639 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1641 scheduler_
->SetNeedsCommit();
1642 EXPECT_NO_ACTION(client_
);
1645 // Trigger the first BeginImplFrame and BeginMainFrame
1646 EXPECT_SCOPED(AdvanceFrame());
1647 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1648 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1649 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1652 // NotifyReadyToCommit should trigger the pending commit and draw.
1653 scheduler_
->NotifyBeginMainFrameStarted();
1654 scheduler_
->NotifyReadyToCommit();
1655 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1658 // Swapping will put us into a swap throttled state.
1659 // Run posted deadline.
1660 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1661 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1662 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1663 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1666 // While swap throttled, BeginFrames should trigger BeginImplFrames,
1667 // but not a BeginMainFrame or draw.
1668 scheduler_
->SetNeedsCommit();
1669 scheduler_
->SetNeedsRedraw();
1670 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
1671 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1672 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1673 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1676 // Let time pass sufficiently beyond the regular deadline but not beyond the
1678 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1679 base::TimeDelta::FromMicroseconds(1));
1680 task_runner().RunUntilTime(now_src()->Now());
1681 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1683 // Take us out of a swap throttled state.
1684 scheduler_
->DidSwapBuffersComplete();
1685 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_
);
1686 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1689 // Verify that the deadline was rescheduled.
1690 // We can't use RunUntilTime(now) here because the next frame is also
1691 // scheduled if throttle_frame_production = false.
1692 base::TimeTicks before_deadline
= now_src()->Now();
1693 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1694 base::TimeTicks after_deadline
= now_src()->Now();
1695 EXPECT_EQ(after_deadline
, before_deadline
);
1696 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1700 TEST_F(SchedulerTest
, SyntheticBeginFrames_SwapThrottled
) {
1701 bool use_external_begin_frame_source
= false;
1702 bool throttle_frame_production
= true;
1703 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1704 throttle_frame_production
);
1707 TEST_F(SchedulerTest
, VSyncThrottlingDisabled_SwapThrottled
) {
1708 bool use_external_begin_frame_source
= true;
1709 bool throttle_frame_production
= false;
1710 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1711 throttle_frame_production
);
1714 TEST_F(SchedulerTest
,
1715 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled
) {
1716 bool use_external_begin_frame_source
= false;
1717 bool throttle_frame_production
= false;
1718 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1719 throttle_frame_production
);
1722 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized
) {
1723 scheduler_settings_
.use_external_begin_frame_source
= true;
1724 SetUpScheduler(false);
1726 scheduler_
->SetCanStart();
1727 scheduler_
->SetVisible(true);
1728 scheduler_
->SetCanDraw(true);
1730 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
1732 scheduler_
->DidCreateAndInitializeOutputSurface();
1733 EXPECT_NO_ACTION(client_
);
1735 scheduler_
->DidLoseOutputSurface();
1736 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
1739 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterBeginFrameStarted
) {
1740 scheduler_settings_
.use_external_begin_frame_source
= true;
1741 SetUpScheduler(true);
1743 // SetNeedsCommit should begin the frame.
1744 scheduler_
->SetNeedsCommit();
1745 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1748 EXPECT_SCOPED(AdvanceFrame());
1749 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1750 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1751 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1754 scheduler_
->DidLoseOutputSurface();
1755 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1756 EXPECT_NO_ACTION(client_
);
1759 scheduler_
->NotifyBeginMainFrameStarted();
1760 scheduler_
->NotifyReadyToCommit();
1761 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 1);
1764 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1765 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
1766 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
1767 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
1770 void SchedulerTest::DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
1771 bool impl_side_painting
) {
1772 scheduler_settings_
.impl_side_painting
= impl_side_painting
;
1773 scheduler_settings_
.use_external_begin_frame_source
= true;
1774 SetUpScheduler(true);
1776 // SetNeedsCommit should begin the frame.
1777 scheduler_
->SetNeedsCommit();
1778 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1781 EXPECT_SCOPED(AdvanceFrame());
1782 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1783 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1784 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1787 scheduler_
->DidLoseOutputSurface();
1788 // Do nothing when impl frame is in deadine pending state.
1789 EXPECT_NO_ACTION(client_
);
1792 // Run posted deadline.
1793 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1794 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1795 // OnBeginImplFrameDeadline didn't schedule output surface creation because
1796 // main frame is not yet completed.
1797 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
1798 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
1799 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1801 // BeginImplFrame is not started.
1803 task_runner().RunUntilTime(now_src()->Now() +
1804 base::TimeDelta::FromMilliseconds(10));
1805 EXPECT_NO_ACTION(client_
);
1806 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1809 scheduler_
->NotifyBeginMainFrameStarted();
1810 scheduler_
->NotifyReadyToCommit();
1811 if (impl_side_painting
) {
1812 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 3);
1813 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 1, 3);
1814 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 2, 3);
1816 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 2);
1817 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 1, 2);
1821 TEST_F(SchedulerTest
,
1822 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency
) {
1823 bool impl_side_painting
= false;
1824 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
1827 TEST_F(SchedulerTest
,
1828 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint
) {
1829 bool impl_side_painting
= true;
1830 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
1833 void SchedulerTest::DidLoseOutputSurfaceAfterReadyToCommit(
1834 bool impl_side_painting
) {
1835 scheduler_settings_
.impl_side_painting
= impl_side_painting
;
1836 scheduler_settings_
.use_external_begin_frame_source
= true;
1837 SetUpScheduler(true);
1839 // SetNeedsCommit should begin the frame.
1840 scheduler_
->SetNeedsCommit();
1841 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1844 EXPECT_SCOPED(AdvanceFrame());
1845 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1846 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1847 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1850 scheduler_
->NotifyBeginMainFrameStarted();
1851 scheduler_
->NotifyReadyToCommit();
1852 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1855 scheduler_
->DidLoseOutputSurface();
1856 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1857 if (impl_side_painting
) {
1858 // Sync tree should be forced to activate.
1859 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
1861 EXPECT_NO_ACTION(client_
);
1865 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1866 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
1867 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
1868 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
1871 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommit
) {
1872 DidLoseOutputSurfaceAfterReadyToCommit(false);
1875 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting
) {
1876 DidLoseOutputSurfaceAfterReadyToCommit(true);
1879 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles
) {
1880 scheduler_settings_
.use_external_begin_frame_source
= true;
1881 SetUpScheduler(true);
1883 scheduler_
->SetNeedsPrepareTiles();
1884 scheduler_
->SetNeedsRedraw();
1885 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1888 EXPECT_SCOPED(AdvanceFrame());
1889 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1890 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1891 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1894 scheduler_
->DidLoseOutputSurface();
1895 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1896 EXPECT_NO_ACTION(client_
);
1899 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1900 EXPECT_ACTION("ScheduledActionPrepareTiles", client_
, 0, 4);
1901 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 1, 4);
1902 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 2, 4);
1903 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 3, 4);
1906 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterBeginRetroFramePosted
) {
1907 scheduler_settings_
.use_external_begin_frame_source
= true;
1908 SetUpScheduler(true);
1910 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1911 scheduler_
->SetNeedsCommit();
1912 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1914 // Create a BeginFrame with a long deadline to avoid race conditions.
1915 // This is the first BeginFrame, which will be handled immediately.
1917 BeginFrameArgs args
=
1918 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1919 args
.deadline
+= base::TimeDelta::FromHours(1);
1920 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1921 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1922 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1923 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1924 EXPECT_TRUE(client_
->needs_begin_frames());
1926 // Queue BeginFrames while we are still handling the previous BeginFrame.
1927 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1928 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1929 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1930 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1932 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1934 task_runner().RunPendingTasks(); // Run posted deadline.
1935 EXPECT_NO_ACTION(client_
);
1936 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1937 EXPECT_TRUE(client_
->needs_begin_frames());
1939 // NotifyReadyToCommit should trigger the commit.
1941 scheduler_
->NotifyBeginMainFrameStarted();
1942 scheduler_
->NotifyReadyToCommit();
1943 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1944 EXPECT_TRUE(client_
->needs_begin_frames());
1947 EXPECT_FALSE(scheduler_
->IsBeginRetroFrameArgsEmpty());
1948 scheduler_
->DidLoseOutputSurface();
1949 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
1950 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
1951 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
1952 EXPECT_TRUE(scheduler_
->IsBeginRetroFrameArgsEmpty());
1954 // Posted BeginRetroFrame is aborted.
1956 task_runner().RunPendingTasks();
1957 EXPECT_NO_ACTION(client_
);
1960 TEST_F(SchedulerTest
, DidLoseOutputSurfaceDuringBeginRetroFrameRunning
) {
1961 scheduler_settings_
.use_external_begin_frame_source
= true;
1962 SetUpScheduler(true);
1964 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1965 scheduler_
->SetNeedsCommit();
1966 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1968 // Create a BeginFrame with a long deadline to avoid race conditions.
1969 // This is the first BeginFrame, which will be handled immediately.
1971 BeginFrameArgs args
=
1972 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1973 args
.deadline
+= base::TimeDelta::FromHours(1);
1974 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1975 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1976 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1977 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1978 EXPECT_TRUE(client_
->needs_begin_frames());
1980 // Queue BeginFrames while we are still handling the previous BeginFrame.
1981 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1982 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1983 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1984 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1986 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1988 task_runner().RunPendingTasks(); // Run posted deadline.
1989 EXPECT_NO_ACTION(client_
);
1990 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1991 EXPECT_TRUE(client_
->needs_begin_frames());
1993 // NotifyReadyToCommit should trigger the commit.
1995 scheduler_
->NotifyBeginMainFrameStarted();
1996 scheduler_
->NotifyReadyToCommit();
1997 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1998 EXPECT_TRUE(client_
->needs_begin_frames());
2000 // BeginImplFrame should prepare the draw.
2002 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2003 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2004 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2005 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2006 EXPECT_TRUE(client_
->needs_begin_frames());
2009 EXPECT_FALSE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2010 scheduler_
->DidLoseOutputSurface();
2011 EXPECT_NO_ACTION(client_
);
2012 EXPECT_TRUE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2014 // BeginImplFrame deadline should abort drawing.
2016 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2017 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2018 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2019 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2020 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2021 EXPECT_FALSE(client_
->needs_begin_frames());
2023 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
2025 task_runner().RunPendingTasks();
2026 EXPECT_NO_ACTION(client_
);
2029 TEST_F(SchedulerTest
, DidLoseOutputSurfaceWithSyntheticBeginFrameSource
) {
2030 SetUpScheduler(true);
2032 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2033 EXPECT_FALSE(scheduler_
->frame_source().NeedsBeginFrames());
2034 scheduler_
->SetNeedsCommit();
2035 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2039 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2040 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2041 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2042 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2044 // NotifyReadyToCommit should trigger the commit.
2046 scheduler_
->NotifyBeginMainFrameStarted();
2047 scheduler_
->NotifyReadyToCommit();
2048 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2049 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2052 scheduler_
->DidLoseOutputSurface();
2053 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2054 EXPECT_NO_ACTION(client_
);
2055 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2058 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2059 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 2);
2060 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
2061 EXPECT_FALSE(scheduler_
->frame_source().NeedsBeginFrames());
2064 TEST_F(SchedulerTest
, DidLoseOutputSurfaceWhenIdle
) {
2065 scheduler_settings_
.use_external_begin_frame_source
= true;
2066 SetUpScheduler(true);
2068 // SetNeedsCommit should begin the frame.
2069 scheduler_
->SetNeedsCommit();
2070 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2073 EXPECT_SCOPED(AdvanceFrame());
2074 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2075 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2076 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2079 scheduler_
->NotifyBeginMainFrameStarted();
2080 scheduler_
->NotifyReadyToCommit();
2081 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2084 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2085 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2086 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2088 // Idle time between BeginFrames.
2090 scheduler_
->DidLoseOutputSurface();
2091 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2092 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2093 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2096 TEST_F(SchedulerTest
, ScheduledActionActivateAfterBecomingInvisible
) {
2097 scheduler_settings_
.impl_side_painting
= true;
2098 scheduler_settings_
.use_external_begin_frame_source
= true;
2099 SetUpScheduler(true);
2101 // SetNeedsCommit should begin the frame.
2102 scheduler_
->SetNeedsCommit();
2103 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2106 EXPECT_SCOPED(AdvanceFrame());
2107 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2108 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2109 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2112 scheduler_
->NotifyBeginMainFrameStarted();
2113 scheduler_
->NotifyReadyToCommit();
2114 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2117 scheduler_
->SetVisible(false);
2118 // Sync tree should be forced to activate.
2119 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
2120 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 1, 2);
2123 // Tests to ensure frame sources can be successfully changed while drawing.
2124 TEST_F(SchedulerTest
, SwitchFrameSourceToUnthrottled
) {
2125 scheduler_settings_
.use_external_begin_frame_source
= true;
2126 SetUpScheduler(true);
2128 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2129 scheduler_
->SetNeedsRedraw();
2130 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2133 EXPECT_SCOPED(AdvanceFrame());
2134 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2135 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2136 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2137 EXPECT_TRUE(client_
->needs_begin_frames());
2139 task_runner().RunPendingTasks(); // Run posted deadline.
2140 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2141 scheduler_
->SetNeedsRedraw();
2143 // Switch to an unthrottled frame source.
2144 scheduler_
->SetThrottleFrameProduction(false);
2147 // Unthrottled frame source will immediately begin a new frame.
2148 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2149 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2150 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2151 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2154 // If we don't swap on the deadline, we wait for the next BeginFrame.
2155 task_runner().RunPendingTasks(); // Run posted deadline.
2156 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2157 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2161 // Tests to ensure frame sources can be successfully changed while a frame
2162 // deadline is pending.
2163 TEST_F(SchedulerTest
, SwitchFrameSourceToUnthrottledBeforeDeadline
) {
2164 scheduler_settings_
.use_external_begin_frame_source
= true;
2165 SetUpScheduler(true);
2167 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2168 scheduler_
->SetNeedsRedraw();
2169 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2172 EXPECT_SCOPED(AdvanceFrame());
2173 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2174 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2176 // Switch to an unthrottled frame source before the frame deadline is hit.
2177 scheduler_
->SetThrottleFrameProduction(false);
2180 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2181 EXPECT_TRUE(client_
->needs_begin_frames());
2184 task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame.
2185 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 2);
2186 // Unthrottled frame source will immediately begin a new frame.
2187 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 2);
2188 scheduler_
->SetNeedsRedraw();
2191 task_runner().RunPendingTasks(); // Run posted deadline.
2192 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2193 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2194 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2198 // Tests to ensure that the active frame source can successfully be changed from
2199 // unthrottled to throttled.
2200 TEST_F(SchedulerTest
, SwitchFrameSourceToThrottled
) {
2201 scheduler_settings_
.throttle_frame_production
= false;
2202 scheduler_settings_
.use_external_begin_frame_source
= true;
2203 SetUpScheduler(true);
2205 scheduler_
->SetNeedsRedraw();
2206 EXPECT_NO_ACTION(client_
);
2209 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2210 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2211 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2212 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2215 task_runner().RunPendingTasks(); // Run posted deadline.
2216 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2217 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2220 // Switch to a throttled frame source.
2221 scheduler_
->SetThrottleFrameProduction(true);
2224 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2225 scheduler_
->SetNeedsRedraw();
2226 task_runner().RunPendingTasks();
2227 EXPECT_NO_ACTION(client_
);
2230 EXPECT_SCOPED(AdvanceFrame());
2231 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2232 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2233 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2234 EXPECT_TRUE(client_
->needs_begin_frames());
2236 task_runner().RunPendingTasks(); // Run posted deadline.
2237 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2240 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
2241 TEST_F(SchedulerTest
, SendBeginMainFrameNotExpectedSoon
) {
2242 scheduler_settings_
.use_external_begin_frame_source
= true;
2243 SetUpScheduler(true);
2245 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2246 scheduler_
->SetNeedsCommit();
2247 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2250 // Trigger a frame draw.
2251 EXPECT_SCOPED(AdvanceFrame());
2252 scheduler_
->NotifyBeginMainFrameStarted();
2253 scheduler_
->NotifyReadyToCommit();
2254 task_runner().RunPendingTasks();
2255 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 5);
2256 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 5);
2257 EXPECT_ACTION("ScheduledActionCommit", client_
, 2, 5);
2258 EXPECT_ACTION("ScheduledActionAnimate", client_
, 3, 5);
2259 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 4, 5);
2262 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2263 // and send a SendBeginMainFrameNotExpectedSoon.
2264 EXPECT_SCOPED(AdvanceFrame());
2265 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
2266 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2269 task_runner().RunPendingTasks(); // Run posted deadline.
2270 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
2271 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
2275 TEST_F(SchedulerTest
, AuthoritativeVSyncInterval
) {
2276 SetUpScheduler(true);
2278 base::TimeDelta initial_interval
=
2279 scheduler_
->begin_impl_frame_args().interval
;
2280 base::TimeDelta authoritative_interval
=
2281 base::TimeDelta::FromMilliseconds(33);
2283 scheduler_
->SetNeedsCommit();
2284 EXPECT_SCOPED(AdvanceFrame());
2286 EXPECT_EQ(initial_interval
, scheduler_
->begin_impl_frame_args().interval
);
2288 scheduler_
->NotifyBeginMainFrameStarted();
2289 scheduler_
->NotifyReadyToCommit();
2290 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2292 scheduler_
->SetAuthoritativeVSyncInterval(authoritative_interval
);
2294 EXPECT_SCOPED(AdvanceFrame());
2296 // At the next BeginFrame, authoritative interval is used instead of previous
2298 EXPECT_NE(initial_interval
, scheduler_
->begin_impl_frame_args().interval
);
2299 EXPECT_EQ(authoritative_interval
,
2300 scheduler_
->begin_impl_frame_args().interval
);