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 SendNextBeginFrame();
366 if (!scheduler_
->settings().using_synchronous_renderer_compositor
) {
367 // Then run tasks until new deadline is scheduled.
368 EXPECT_TRUE(task_runner_
->RunTasksWhile(
369 client_
->ImplFrameDeadlinePending(false)));
370 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
374 void SendNextBeginFrame() {
375 DCHECK(scheduler_
->settings().use_external_begin_frame_source
);
376 // Creep the time forward so that any BeginFrameArgs is not equal to the
377 // last one otherwise we violate the BeginFrameSource contract.
378 now_src_
->AdvanceNow(BeginFrameArgs::DefaultInterval());
379 fake_external_begin_frame_source_
->TestOnBeginFrame(
380 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src()));
383 FakeExternalBeginFrameSource
* fake_external_begin_frame_source() const {
384 return fake_external_begin_frame_source_
;
387 void MainFrameInHighLatencyMode(
388 int64 begin_main_frame_to_commit_estimate_in_ms
,
389 int64 commit_to_activate_estimate_in_ms
,
390 bool impl_latency_takes_priority
,
391 bool should_send_begin_main_frame
);
392 void BeginFramesNotFromClient(bool use_external_begin_frame_source
,
393 bool throttle_frame_production
);
394 void BeginFramesNotFromClient_SwapThrottled(
395 bool use_external_begin_frame_source
,
396 bool throttle_frame_production
);
397 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
398 bool impl_side_painting
);
399 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting
);
401 scoped_refptr
<TestNowSource
> now_src_
;
402 scoped_refptr
<OrderedSimpleTaskRunner
> task_runner_
;
403 FakeExternalBeginFrameSource
* fake_external_begin_frame_source_
;
404 SchedulerSettings scheduler_settings_
;
405 scoped_ptr
<FakeSchedulerClient
> client_
;
406 scoped_ptr
<TestScheduler
> scheduler_
;
409 TEST_F(SchedulerTest
, InitializeOutputSurfaceDoesNotBeginImplFrame
) {
410 scheduler_settings_
.use_external_begin_frame_source
= true;
411 SetUpScheduler(false);
412 scheduler_
->SetCanStart();
413 scheduler_
->SetVisible(true);
414 scheduler_
->SetCanDraw(true);
416 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
418 scheduler_
->DidCreateAndInitializeOutputSurface();
419 EXPECT_NO_ACTION(client_
);
422 TEST_F(SchedulerTest
, SendBeginFramesToChildren
) {
423 scheduler_settings_
.use_external_begin_frame_source
= true;
424 SetUpScheduler(true);
426 EXPECT_FALSE(client_
->begin_frame_is_sent_to_children());
427 scheduler_
->SetNeedsCommit();
428 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
429 EXPECT_TRUE(client_
->needs_begin_frames());
431 scheduler_
->SetChildrenNeedBeginFrames(true);
434 EXPECT_SCOPED(AdvanceFrame());
435 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
436 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
437 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
438 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
439 EXPECT_TRUE(client_
->needs_begin_frames());
442 TEST_F(SchedulerTest
, SendBeginFramesToChildrenWithoutCommit
) {
443 scheduler_settings_
.use_external_begin_frame_source
= true;
444 SetUpScheduler(true);
446 EXPECT_FALSE(client_
->needs_begin_frames());
447 scheduler_
->SetChildrenNeedBeginFrames(true);
448 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
449 EXPECT_TRUE(client_
->needs_begin_frames());
452 EXPECT_SCOPED(AdvanceFrame());
453 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
456 TEST_F(SchedulerTest
, RequestCommit
) {
457 scheduler_settings_
.use_external_begin_frame_source
= true;
458 SetUpScheduler(true);
460 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
461 scheduler_
->SetNeedsCommit();
462 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
465 EXPECT_SCOPED(AdvanceFrame());
466 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
467 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
468 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
469 EXPECT_TRUE(client_
->needs_begin_frames());
472 // If we don't swap on the deadline, we wait for the next BeginFrame.
473 task_runner().RunPendingTasks(); // Run posted deadline.
474 EXPECT_NO_ACTION(client_
);
475 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
476 EXPECT_TRUE(client_
->needs_begin_frames());
479 // NotifyReadyToCommit should trigger the commit.
480 scheduler_
->NotifyBeginMainFrameStarted();
481 scheduler_
->NotifyReadyToCommit();
482 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
483 EXPECT_TRUE(client_
->needs_begin_frames());
486 // BeginImplFrame should prepare the draw.
487 EXPECT_SCOPED(AdvanceFrame());
488 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
489 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
490 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
491 EXPECT_TRUE(client_
->needs_begin_frames());
494 // BeginImplFrame deadline should draw.
495 task_runner().RunPendingTasks(); // Run posted deadline.
496 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
497 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
498 EXPECT_TRUE(client_
->needs_begin_frames());
501 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
502 // to avoid excessive toggles.
503 EXPECT_SCOPED(AdvanceFrame());
504 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
505 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
508 task_runner().RunPendingTasks(); // Run posted deadline.
509 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
510 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
514 TEST_F(SchedulerTest
, RequestCommitAfterSetDeferCommit
) {
515 scheduler_settings_
.use_external_begin_frame_source
= true;
516 SetUpScheduler(true);
518 scheduler_
->SetDeferCommits(true);
520 scheduler_
->SetNeedsCommit();
521 EXPECT_NO_ACTION(client_
);
524 task_runner().RunPendingTasks();
525 // There are no pending tasks or actions.
526 EXPECT_NO_ACTION(client_
);
527 EXPECT_FALSE(client_
->needs_begin_frames());
530 scheduler_
->SetDeferCommits(false);
531 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
533 // Start new BeginMainFrame after defer commit is off.
535 EXPECT_SCOPED(AdvanceFrame());
536 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
537 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
538 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
541 TEST_F(SchedulerTest
, DeferCommitWithRedraw
) {
542 scheduler_settings_
.use_external_begin_frame_source
= true;
543 SetUpScheduler(true);
545 scheduler_
->SetDeferCommits(true);
547 scheduler_
->SetNeedsCommit();
548 EXPECT_NO_ACTION(client_
);
550 // The SetNeedsRedraw will override the SetDeferCommits(true), to allow a
551 // begin frame to be needed.
553 scheduler_
->SetNeedsRedraw();
554 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
558 // BeginMainFrame is not sent during the defer commit is on.
559 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
560 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
563 task_runner().RunPendingTasks(); // Run posted deadline.
564 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
565 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
566 EXPECT_TRUE(client_
->needs_begin_frames());
570 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
573 TEST_F(SchedulerTest
, RequestCommitAfterBeginMainFrameSent
) {
574 scheduler_settings_
.use_external_begin_frame_source
= true;
575 SetUpScheduler(true);
577 // SetNeedsCommit should begin the frame.
578 scheduler_
->SetNeedsCommit();
579 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
582 EXPECT_SCOPED(AdvanceFrame());
583 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
584 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
585 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
587 EXPECT_TRUE(client_
->needs_begin_frames());
590 // Now SetNeedsCommit again. Calling here means we need a second commit.
591 scheduler_
->SetNeedsCommit();
592 EXPECT_EQ(client_
->num_actions_(), 0);
595 // Finish the first commit.
596 scheduler_
->NotifyBeginMainFrameStarted();
597 scheduler_
->NotifyReadyToCommit();
598 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
599 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
601 task_runner().RunPendingTasks(); // Run posted deadline.
602 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
603 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
604 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
606 // Because we just swapped, the Scheduler should also request the next
607 // BeginImplFrame from the OutputSurface.
608 EXPECT_TRUE(client_
->needs_begin_frames());
610 // Since another commit is needed, the next BeginImplFrame should initiate
611 // the second commit.
612 EXPECT_SCOPED(AdvanceFrame());
613 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
614 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
615 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
618 // Finishing the commit before the deadline should post a new deadline task
619 // to trigger the deadline early.
620 scheduler_
->NotifyBeginMainFrameStarted();
621 scheduler_
->NotifyReadyToCommit();
622 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
623 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
625 task_runner().RunPendingTasks(); // Run posted deadline.
626 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
627 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
628 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
629 EXPECT_TRUE(client_
->needs_begin_frames());
632 // On the next BeginImplFrame, verify we go back to a quiescent state and
633 // no longer request BeginImplFrames.
634 EXPECT_SCOPED(AdvanceFrame());
635 task_runner().RunPendingTasks(); // Run posted deadline.
636 EXPECT_FALSE(client_
->needs_begin_frames());
640 class SchedulerClientThatsetNeedsDrawInsideDraw
: public FakeSchedulerClient
{
642 SchedulerClientThatsetNeedsDrawInsideDraw()
643 : FakeSchedulerClient(), request_redraws_(false) {}
645 void ScheduledActionSendBeginMainFrame() override
{}
647 void SetRequestRedrawsInsideDraw(bool enable
) { request_redraws_
= enable
; }
649 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
650 // Only SetNeedsRedraw the first time this is called
651 if (request_redraws_
) {
652 scheduler_
->SetNeedsRedraw();
654 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
657 DrawResult
ScheduledActionDrawAndSwapForced() override
{
662 void ScheduledActionCommit() override
{}
663 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{}
666 bool request_redraws_
;
669 // Tests for two different situations:
670 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
671 // a ScheduledActionDrawAndSwap
672 // 2. the scheduler drawing twice inside a single tick
673 TEST_F(SchedulerTest
, RequestRedrawInsideDraw
) {
674 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
675 new SchedulerClientThatsetNeedsDrawInsideDraw
;
676 scheduler_settings_
.use_external_begin_frame_source
= true;
677 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
678 client
->SetRequestRedrawsInsideDraw(true);
680 scheduler_
->SetNeedsRedraw();
681 EXPECT_TRUE(scheduler_
->RedrawPending());
682 EXPECT_TRUE(client
->needs_begin_frames());
683 EXPECT_EQ(0, client
->num_draws());
685 EXPECT_SCOPED(AdvanceFrame());
686 task_runner().RunPendingTasks(); // Run posted deadline.
687 EXPECT_EQ(1, client
->num_draws());
688 EXPECT_TRUE(scheduler_
->RedrawPending());
689 EXPECT_TRUE(client
->needs_begin_frames());
691 client
->SetRequestRedrawsInsideDraw(false);
693 EXPECT_SCOPED(AdvanceFrame());
694 task_runner().RunPendingTasks(); // Run posted deadline.
695 EXPECT_EQ(2, client_
->num_draws());
696 EXPECT_FALSE(scheduler_
->RedrawPending());
697 EXPECT_TRUE(client
->needs_begin_frames());
699 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
701 EXPECT_SCOPED(AdvanceFrame());
702 task_runner().RunPendingTasks(); // Run posted deadline.
703 EXPECT_EQ(2, client
->num_draws());
704 EXPECT_FALSE(scheduler_
->RedrawPending());
705 EXPECT_FALSE(client
->needs_begin_frames());
708 // Test that requesting redraw inside a failed draw doesn't lose the request.
709 TEST_F(SchedulerTest
, RequestRedrawInsideFailedDraw
) {
710 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
711 new SchedulerClientThatsetNeedsDrawInsideDraw
;
712 scheduler_settings_
.use_external_begin_frame_source
= true;
713 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
715 client
->SetRequestRedrawsInsideDraw(true);
716 client
->SetDrawWillHappen(false);
718 scheduler_
->SetNeedsRedraw();
719 EXPECT_TRUE(scheduler_
->RedrawPending());
720 EXPECT_TRUE(client
->needs_begin_frames());
721 EXPECT_EQ(0, client
->num_draws());
724 EXPECT_SCOPED(AdvanceFrame());
725 task_runner().RunPendingTasks(); // Run posted deadline.
726 EXPECT_EQ(1, client
->num_draws());
728 // We have a commit pending and the draw failed, and we didn't lose the redraw
730 EXPECT_TRUE(scheduler_
->CommitPending());
731 EXPECT_TRUE(scheduler_
->RedrawPending());
732 EXPECT_TRUE(client
->needs_begin_frames());
734 client
->SetRequestRedrawsInsideDraw(false);
736 // Fail the draw again.
737 EXPECT_SCOPED(AdvanceFrame());
738 task_runner().RunPendingTasks(); // Run posted deadline.
739 EXPECT_EQ(2, client
->num_draws());
740 EXPECT_TRUE(scheduler_
->CommitPending());
741 EXPECT_TRUE(scheduler_
->RedrawPending());
742 EXPECT_TRUE(client
->needs_begin_frames());
744 // Draw successfully.
745 client
->SetDrawWillHappen(true);
746 EXPECT_SCOPED(AdvanceFrame());
747 task_runner().RunPendingTasks(); // Run posted deadline.
748 EXPECT_EQ(3, client
->num_draws());
749 EXPECT_TRUE(scheduler_
->CommitPending());
750 EXPECT_FALSE(scheduler_
->RedrawPending());
751 EXPECT_TRUE(client
->needs_begin_frames());
754 class SchedulerClientThatSetNeedsCommitInsideDraw
: public FakeSchedulerClient
{
756 SchedulerClientThatSetNeedsCommitInsideDraw()
757 : set_needs_commit_on_next_draw_(false) {}
759 void ScheduledActionSendBeginMainFrame() override
{}
760 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
761 // Only SetNeedsCommit the first time this is called
762 if (set_needs_commit_on_next_draw_
) {
763 scheduler_
->SetNeedsCommit();
764 set_needs_commit_on_next_draw_
= false;
766 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
769 DrawResult
ScheduledActionDrawAndSwapForced() override
{
774 void ScheduledActionCommit() override
{}
775 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{}
777 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_
= true; }
780 bool set_needs_commit_on_next_draw_
;
783 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
784 // happen inside a ScheduledActionDrawAndSwap
785 TEST_F(SchedulerTest
, RequestCommitInsideDraw
) {
786 SchedulerClientThatSetNeedsCommitInsideDraw
* client
=
787 new SchedulerClientThatSetNeedsCommitInsideDraw
;
789 scheduler_settings_
.use_external_begin_frame_source
= true;
790 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
792 EXPECT_FALSE(client
->needs_begin_frames());
793 scheduler_
->SetNeedsRedraw();
794 EXPECT_TRUE(scheduler_
->RedrawPending());
795 EXPECT_EQ(0, client
->num_draws());
796 EXPECT_TRUE(client
->needs_begin_frames());
798 client
->SetNeedsCommitOnNextDraw();
799 EXPECT_SCOPED(AdvanceFrame());
800 client
->SetNeedsCommitOnNextDraw();
801 task_runner().RunPendingTasks(); // Run posted deadline.
802 EXPECT_EQ(1, client
->num_draws());
803 EXPECT_TRUE(scheduler_
->CommitPending());
804 EXPECT_TRUE(client
->needs_begin_frames());
805 scheduler_
->NotifyBeginMainFrameStarted();
806 scheduler_
->NotifyReadyToCommit();
808 EXPECT_SCOPED(AdvanceFrame());
809 task_runner().RunPendingTasks(); // Run posted deadline.
810 EXPECT_EQ(2, client
->num_draws());
812 EXPECT_FALSE(scheduler_
->RedrawPending());
813 EXPECT_FALSE(scheduler_
->CommitPending());
814 EXPECT_TRUE(client
->needs_begin_frames());
816 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
818 EXPECT_SCOPED(AdvanceFrame());
819 task_runner().RunPendingTasks(); // Run posted deadline.
820 EXPECT_EQ(2, client
->num_draws());
821 EXPECT_FALSE(scheduler_
->RedrawPending());
822 EXPECT_FALSE(scheduler_
->CommitPending());
823 EXPECT_FALSE(client
->needs_begin_frames());
826 // Tests that when a draw fails then the pending commit should not be dropped.
827 TEST_F(SchedulerTest
, RequestCommitInsideFailedDraw
) {
828 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
829 new SchedulerClientThatsetNeedsDrawInsideDraw
;
830 scheduler_settings_
.use_external_begin_frame_source
= true;
831 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
833 client
->SetDrawWillHappen(false);
835 scheduler_
->SetNeedsRedraw();
836 EXPECT_TRUE(scheduler_
->RedrawPending());
837 EXPECT_TRUE(client
->needs_begin_frames());
838 EXPECT_EQ(0, client
->num_draws());
841 EXPECT_SCOPED(AdvanceFrame());
842 task_runner().RunPendingTasks(); // Run posted deadline.
843 EXPECT_EQ(1, client
->num_draws());
845 // We have a commit pending and the draw failed, and we didn't lose the commit
847 EXPECT_TRUE(scheduler_
->CommitPending());
848 EXPECT_TRUE(scheduler_
->RedrawPending());
849 EXPECT_TRUE(client
->needs_begin_frames());
851 // Fail the draw again.
852 EXPECT_SCOPED(AdvanceFrame());
854 task_runner().RunPendingTasks(); // Run posted deadline.
855 EXPECT_EQ(2, client
->num_draws());
856 EXPECT_TRUE(scheduler_
->CommitPending());
857 EXPECT_TRUE(scheduler_
->RedrawPending());
858 EXPECT_TRUE(client
->needs_begin_frames());
860 // Draw successfully.
861 client
->SetDrawWillHappen(true);
862 EXPECT_SCOPED(AdvanceFrame());
863 task_runner().RunPendingTasks(); // Run posted deadline.
864 EXPECT_EQ(3, client
->num_draws());
865 EXPECT_TRUE(scheduler_
->CommitPending());
866 EXPECT_FALSE(scheduler_
->RedrawPending());
867 EXPECT_TRUE(client
->needs_begin_frames());
870 TEST_F(SchedulerTest
, NoSwapWhenDrawFails
) {
871 SchedulerClientThatSetNeedsCommitInsideDraw
* client
=
872 new SchedulerClientThatSetNeedsCommitInsideDraw
;
873 scheduler_settings_
.use_external_begin_frame_source
= true;
874 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
876 scheduler_
->SetNeedsRedraw();
877 EXPECT_TRUE(scheduler_
->RedrawPending());
878 EXPECT_TRUE(client
->needs_begin_frames());
879 EXPECT_EQ(0, client
->num_draws());
881 // Draw successfully, this starts a new frame.
882 client
->SetNeedsCommitOnNextDraw();
883 EXPECT_SCOPED(AdvanceFrame());
884 task_runner().RunPendingTasks(); // Run posted deadline.
885 EXPECT_EQ(1, client
->num_draws());
887 scheduler_
->SetNeedsRedraw();
888 EXPECT_TRUE(scheduler_
->RedrawPending());
889 EXPECT_TRUE(client
->needs_begin_frames());
891 // Fail to draw, this should not start a frame.
892 client
->SetDrawWillHappen(false);
893 client
->SetNeedsCommitOnNextDraw();
894 EXPECT_SCOPED(AdvanceFrame());
895 task_runner().RunPendingTasks(); // Run posted deadline.
896 EXPECT_EQ(2, client
->num_draws());
899 class SchedulerClientNeedsPrepareTilesInDraw
: public FakeSchedulerClient
{
901 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
902 scheduler_
->SetNeedsPrepareTiles();
903 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
907 // Test prepare tiles is independant of draws.
908 TEST_F(SchedulerTest
, PrepareTiles
) {
909 SchedulerClientNeedsPrepareTilesInDraw
* client
=
910 new SchedulerClientNeedsPrepareTilesInDraw
;
911 scheduler_settings_
.use_external_begin_frame_source
= true;
912 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
914 // Request both draw and prepare tiles. PrepareTiles shouldn't
915 // be trigged until BeginImplFrame.
917 scheduler_
->SetNeedsPrepareTiles();
918 scheduler_
->SetNeedsRedraw();
919 EXPECT_TRUE(scheduler_
->RedrawPending());
920 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
921 EXPECT_TRUE(client
->needs_begin_frames());
922 EXPECT_EQ(0, client
->num_draws());
923 EXPECT_FALSE(client
->HasAction("ScheduledActionPrepareTiles"));
924 EXPECT_FALSE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
926 // We have no immediate actions to perform, so the BeginImplFrame should post
927 // the deadline task.
929 EXPECT_SCOPED(AdvanceFrame());
930 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
931 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
932 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
934 // On the deadline, he actions should have occured in the right order.
936 task_runner().RunPendingTasks(); // Run posted deadline.
937 EXPECT_EQ(1, client
->num_draws());
938 EXPECT_TRUE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
939 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
940 EXPECT_LT(client
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
941 client
->ActionIndex("ScheduledActionPrepareTiles"));
942 EXPECT_FALSE(scheduler_
->RedrawPending());
943 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
944 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
946 // Request a draw. We don't need a PrepareTiles yet.
948 scheduler_
->SetNeedsRedraw();
949 EXPECT_TRUE(scheduler_
->RedrawPending());
950 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
951 EXPECT_TRUE(client
->needs_begin_frames());
952 EXPECT_EQ(0, client
->num_draws());
954 // We have no immediate actions to perform, so the BeginImplFrame should post
955 // the deadline task.
957 EXPECT_SCOPED(AdvanceFrame());
958 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
959 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
960 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
962 // Draw. The draw will trigger SetNeedsPrepareTiles, and
963 // then the PrepareTiles action will be triggered after the Draw.
964 // Afterwards, neither a draw nor PrepareTiles are pending.
966 task_runner().RunPendingTasks(); // Run posted deadline.
967 EXPECT_EQ(1, client
->num_draws());
968 EXPECT_TRUE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
969 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
970 EXPECT_LT(client
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
971 client
->ActionIndex("ScheduledActionPrepareTiles"));
972 EXPECT_FALSE(scheduler_
->RedrawPending());
973 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
974 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
976 // We need a BeginImplFrame where we don't swap to go idle.
978 EXPECT_SCOPED(AdvanceFrame());
979 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
980 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
982 task_runner().RunPendingTasks(); // Run posted deadline.
983 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
984 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
985 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
986 EXPECT_EQ(0, client
->num_draws());
988 // Now trigger a PrepareTiles outside of a draw. We will then need
989 // a begin-frame for the PrepareTiles, but we don't need a draw.
991 EXPECT_FALSE(client
->needs_begin_frames());
992 scheduler_
->SetNeedsPrepareTiles();
993 EXPECT_TRUE(client
->needs_begin_frames());
994 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
995 EXPECT_FALSE(scheduler_
->RedrawPending());
997 // BeginImplFrame. There will be no draw, only PrepareTiles.
999 EXPECT_SCOPED(AdvanceFrame());
1000 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
1001 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1003 task_runner().RunPendingTasks(); // Run posted deadline.
1004 EXPECT_EQ(0, client
->num_draws());
1005 EXPECT_FALSE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1006 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
1007 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1010 // Test that PrepareTiles only happens once per frame. If an external caller
1011 // initiates it, then the state machine should not PrepareTiles on that frame.
1012 TEST_F(SchedulerTest
, PrepareTilesOncePerFrame
) {
1013 scheduler_settings_
.use_external_begin_frame_source
= true;
1014 SetUpScheduler(true);
1016 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
1018 scheduler_
->SetNeedsPrepareTiles();
1019 scheduler_
->SetNeedsRedraw();
1021 EXPECT_SCOPED(AdvanceFrame());
1022 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1023 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1024 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1026 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1027 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1028 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1031 task_runner().RunPendingTasks(); // Run posted deadline.
1032 EXPECT_EQ(1, client_
->num_draws());
1033 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1034 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1035 EXPECT_FALSE(scheduler_
->RedrawPending());
1036 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1037 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1039 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1040 scheduler_
->SetNeedsPrepareTiles();
1041 scheduler_
->SetNeedsRedraw();
1043 EXPECT_SCOPED(AdvanceFrame());
1044 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1045 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1046 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1049 task_runner().RunPendingTasks(); // Run posted deadline.
1050 EXPECT_EQ(1, client_
->num_draws());
1051 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1052 EXPECT_TRUE(client_
->HasAction("ScheduledActionPrepareTiles"));
1053 EXPECT_LT(client_
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1054 client_
->ActionIndex("ScheduledActionPrepareTiles"));
1055 EXPECT_FALSE(scheduler_
->RedrawPending());
1056 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1057 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1058 scheduler_
->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1060 // If we get another DidPrepareTiles within the same frame, we should
1061 // not PrepareTiles on the next frame.
1062 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1063 scheduler_
->SetNeedsPrepareTiles();
1064 scheduler_
->SetNeedsRedraw();
1066 EXPECT_SCOPED(AdvanceFrame());
1067 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1068 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1069 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1071 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1074 task_runner().RunPendingTasks(); // Run posted deadline.
1075 EXPECT_EQ(1, client_
->num_draws());
1076 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1077 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1078 EXPECT_FALSE(scheduler_
->RedrawPending());
1079 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1081 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1082 // frame. This verifies we don't alternate calling PrepareTiles once and
1084 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1085 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1086 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1087 scheduler_
->SetNeedsPrepareTiles();
1088 scheduler_
->SetNeedsRedraw();
1090 EXPECT_SCOPED(AdvanceFrame());
1091 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1092 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1093 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1095 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1098 task_runner().RunPendingTasks(); // Run posted deadline.
1099 EXPECT_EQ(1, client_
->num_draws());
1100 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1101 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1102 EXPECT_FALSE(scheduler_
->RedrawPending());
1103 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1105 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1106 scheduler_
->SetNeedsPrepareTiles();
1107 scheduler_
->SetNeedsRedraw();
1109 EXPECT_SCOPED(AdvanceFrame());
1110 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1111 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1112 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1115 task_runner().RunPendingTasks(); // Run posted deadline.
1116 EXPECT_EQ(1, client_
->num_draws());
1117 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1118 EXPECT_TRUE(client_
->HasAction("ScheduledActionPrepareTiles"));
1119 EXPECT_LT(client_
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1120 client_
->ActionIndex("ScheduledActionPrepareTiles"));
1121 EXPECT_FALSE(scheduler_
->RedrawPending());
1122 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1123 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1124 scheduler_
->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1127 TEST_F(SchedulerTest
, TriggerBeginFrameDeadlineEarly
) {
1128 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1129 new SchedulerClientNeedsPrepareTilesInDraw
;
1130 scheduler_settings_
.use_external_begin_frame_source
= true;
1131 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1133 scheduler_
->SetNeedsRedraw();
1134 EXPECT_SCOPED(AdvanceFrame());
1136 // The deadline should be zero since there is no work other than drawing
1138 EXPECT_EQ(base::TimeTicks(), client
->posted_begin_impl_frame_deadline());
1141 TEST_F(SchedulerTest
, WaitForReadyToDrawDoNotPostDeadline
) {
1142 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1143 new SchedulerClientNeedsPrepareTilesInDraw
;
1144 scheduler_settings_
.use_external_begin_frame_source
= true;
1145 scheduler_settings_
.impl_side_painting
= true;
1146 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1148 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1149 scheduler_
->SetNeedsCommit();
1150 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1154 EXPECT_SCOPED(AdvanceFrame());
1155 scheduler_
->NotifyBeginMainFrameStarted();
1156 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1157 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1160 scheduler_
->NotifyReadyToCommit();
1161 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1164 scheduler_
->NotifyReadyToActivate();
1165 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
1167 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1169 scheduler_
->SetWaitForReadyToDraw();
1171 task_runner().RunPendingTasks(); // Try to run posted deadline.
1172 // There is no posted deadline.
1173 EXPECT_NO_ACTION(client_
);
1175 // Scheduler received ready to draw signal, and posted deadline.
1176 scheduler_
->NotifyReadyToDraw();
1178 task_runner().RunPendingTasks(); // Run posted deadline.
1179 EXPECT_EQ(1, client_
->num_draws());
1180 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1183 TEST_F(SchedulerTest
, WaitForReadyToDrawCancelledWhenLostOutputSurface
) {
1184 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1185 new SchedulerClientNeedsPrepareTilesInDraw
;
1186 scheduler_settings_
.use_external_begin_frame_source
= true;
1187 scheduler_settings_
.impl_side_painting
= true;
1188 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1190 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1191 scheduler_
->SetNeedsCommit();
1192 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1196 EXPECT_SCOPED(AdvanceFrame());
1197 scheduler_
->NotifyBeginMainFrameStarted();
1198 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1199 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1202 scheduler_
->NotifyReadyToCommit();
1203 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1206 scheduler_
->NotifyReadyToActivate();
1207 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
1209 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1211 scheduler_
->SetWaitForReadyToDraw();
1213 task_runner().RunPendingTasks(); // Try to run posted deadline.
1214 // There is no posted deadline.
1215 EXPECT_NO_ACTION(client_
);
1217 // Scheduler loses output surface, and stops waiting for ready to draw signal.
1219 scheduler_
->DidLoseOutputSurface();
1220 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1221 task_runner().RunPendingTasks(); // Run posted deadline.
1222 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
1223 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
1224 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
1227 class SchedulerClientWithFixedEstimates
: public FakeSchedulerClient
{
1229 SchedulerClientWithFixedEstimates(
1230 base::TimeDelta draw_duration
,
1231 base::TimeDelta begin_main_frame_to_commit_duration
,
1232 base::TimeDelta commit_to_activate_duration
)
1233 : draw_duration_(draw_duration
),
1234 begin_main_frame_to_commit_duration_(
1235 begin_main_frame_to_commit_duration
),
1236 commit_to_activate_duration_(commit_to_activate_duration
) {}
1238 base::TimeDelta
DrawDurationEstimate() override
{ return draw_duration_
; }
1239 base::TimeDelta
BeginMainFrameToCommitDurationEstimate() override
{
1240 return begin_main_frame_to_commit_duration_
;
1242 base::TimeDelta
CommitToActivateDurationEstimate() override
{
1243 return commit_to_activate_duration_
;
1247 base::TimeDelta draw_duration_
;
1248 base::TimeDelta begin_main_frame_to_commit_duration_
;
1249 base::TimeDelta commit_to_activate_duration_
;
1252 void SchedulerTest::MainFrameInHighLatencyMode(
1253 int64 begin_main_frame_to_commit_estimate_in_ms
,
1254 int64 commit_to_activate_estimate_in_ms
,
1255 bool impl_latency_takes_priority
,
1256 bool should_send_begin_main_frame
) {
1257 // Set up client with specified estimates (draw duration is set to 1).
1258 SchedulerClientWithFixedEstimates
* client
=
1259 new SchedulerClientWithFixedEstimates(
1260 base::TimeDelta::FromMilliseconds(1),
1261 base::TimeDelta::FromMilliseconds(
1262 begin_main_frame_to_commit_estimate_in_ms
),
1263 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms
));
1265 scheduler_settings_
.use_external_begin_frame_source
= true;
1266 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1268 scheduler_
->SetImplLatencyTakesPriority(impl_latency_takes_priority
);
1270 // Impl thread hits deadline before commit finishes.
1271 scheduler_
->SetNeedsCommit();
1272 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1273 EXPECT_SCOPED(AdvanceFrame());
1274 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1275 task_runner().RunPendingTasks(); // Run posted deadline.
1276 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1277 scheduler_
->NotifyBeginMainFrameStarted();
1278 scheduler_
->NotifyReadyToCommit();
1279 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1280 EXPECT_TRUE(client
->HasAction("ScheduledActionSendBeginMainFrame"));
1283 scheduler_
->SetNeedsCommit();
1284 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1285 EXPECT_SCOPED(AdvanceFrame());
1286 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1287 task_runner().RunPendingTasks(); // Run posted deadline.
1288 EXPECT_EQ(scheduler_
->MainThreadIsInHighLatencyMode(),
1289 should_send_begin_main_frame
);
1290 EXPECT_EQ(client
->HasAction("ScheduledActionSendBeginMainFrame"),
1291 should_send_begin_main_frame
);
1294 TEST_F(SchedulerTest
,
1295 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline
) {
1296 // Set up client so that estimates indicate that we can commit and activate
1297 // before the deadline (~8ms by default).
1298 MainFrameInHighLatencyMode(1, 1, false, false);
1301 TEST_F(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong
) {
1302 // Set up client so that estimates indicate that the commit cannot finish
1303 // before the deadline (~8ms by default).
1304 MainFrameInHighLatencyMode(10, 1, false, true);
1307 TEST_F(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong
) {
1308 // Set up client so that estimates indicate that the activate cannot finish
1309 // before the deadline (~8ms by default).
1310 MainFrameInHighLatencyMode(1, 10, false, true);
1313 TEST_F(SchedulerTest
, NotSkipMainFrameInPreferImplLatencyMode
) {
1314 // Set up client so that estimates indicate that we can commit and activate
1315 // before the deadline (~8ms by default), but also enable impl latency takes
1317 MainFrameInHighLatencyMode(1, 1, true, true);
1320 TEST_F(SchedulerTest
, PollForCommitCompletion
) {
1321 // Since we are simulating a long commit, set up a client with draw duration
1322 // estimates that prevent skipping main frames to get to low latency mode.
1323 SchedulerClientWithFixedEstimates
* client
=
1324 new SchedulerClientWithFixedEstimates(
1325 base::TimeDelta::FromMilliseconds(1),
1326 base::TimeDelta::FromMilliseconds(32),
1327 base::TimeDelta::FromMilliseconds(32));
1328 scheduler_settings_
.use_external_begin_frame_source
= true;
1329 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1331 client
->set_log_anticipated_draw_time_change(true);
1333 BeginFrameArgs frame_args
=
1334 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1335 frame_args
.interval
= base::TimeDelta::FromMilliseconds(1000);
1337 // At this point, we've drawn a frame. Start another commit, but hold off on
1338 // the NotifyReadyToCommit for now.
1339 EXPECT_FALSE(scheduler_
->CommitPending());
1340 scheduler_
->SetNeedsCommit();
1341 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args
);
1342 EXPECT_TRUE(scheduler_
->CommitPending());
1344 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1345 // blocking on the renderer.
1346 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1347 task_runner().RunPendingTasks(); // Run posted deadline.
1348 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1349 scheduler_
->DidSwapBuffers();
1351 // Spin the event loop a few times and make sure we get more
1352 // DidAnticipateDrawTimeChange calls every time.
1353 int actions_so_far
= client
->num_actions_();
1355 // Does three iterations to make sure that the timer is properly repeating.
1356 for (int i
= 0; i
< 3; ++i
) {
1357 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1358 task_runner().DelayToNextTaskTime().InMicroseconds())
1359 << scheduler_
->AsValue()->ToString();
1360 task_runner().RunPendingTasks();
1361 EXPECT_GT(client
->num_actions_(), actions_so_far
);
1362 EXPECT_STREQ(client
->Action(client
->num_actions_() - 1),
1363 "DidAnticipatedDrawTimeChange");
1364 actions_so_far
= client
->num_actions_();
1367 // Do the same thing after BeginMainFrame starts but still before activation.
1368 scheduler_
->NotifyBeginMainFrameStarted();
1369 for (int i
= 0; i
< 3; ++i
) {
1370 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1371 task_runner().DelayToNextTaskTime().InMicroseconds())
1372 << scheduler_
->AsValue()->ToString();
1373 task_runner().RunPendingTasks();
1374 EXPECT_GT(client
->num_actions_(), actions_so_far
);
1375 EXPECT_STREQ(client
->Action(client
->num_actions_() - 1),
1376 "DidAnticipatedDrawTimeChange");
1377 actions_so_far
= client
->num_actions_();
1381 TEST_F(SchedulerTest
, BeginRetroFrame
) {
1382 scheduler_settings_
.use_external_begin_frame_source
= true;
1383 SetUpScheduler(true);
1385 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1386 scheduler_
->SetNeedsCommit();
1387 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1390 // Create a BeginFrame with a long deadline to avoid race conditions.
1391 // This is the first BeginFrame, which will be handled immediately.
1392 BeginFrameArgs args
=
1393 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1394 args
.deadline
+= base::TimeDelta::FromHours(1);
1395 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1396 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1397 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1398 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1399 EXPECT_TRUE(client_
->needs_begin_frames());
1402 // Queue BeginFrames while we are still handling the previous BeginFrame.
1403 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1404 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1405 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1406 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1408 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1409 task_runner().RunPendingTasks(); // Run posted deadline.
1410 EXPECT_NO_ACTION(client_
);
1411 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1412 EXPECT_TRUE(client_
->needs_begin_frames());
1415 // NotifyReadyToCommit should trigger the commit.
1416 scheduler_
->NotifyBeginMainFrameStarted();
1417 scheduler_
->NotifyReadyToCommit();
1418 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1419 EXPECT_TRUE(client_
->needs_begin_frames());
1422 // BeginImplFrame should prepare the draw.
1423 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1424 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1425 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1426 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1427 EXPECT_TRUE(client_
->needs_begin_frames());
1430 // BeginImplFrame deadline should draw.
1431 task_runner().RunPendingTasks(); // Run posted deadline.
1432 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
1433 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1434 EXPECT_TRUE(client_
->needs_begin_frames());
1437 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1438 // to avoid excessive toggles.
1439 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1440 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
1441 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1444 task_runner().RunPendingTasks(); // Run posted deadline.
1445 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
1446 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
1450 TEST_F(SchedulerTest
, BeginRetroFrame_SwapThrottled
) {
1451 scheduler_settings_
.use_external_begin_frame_source
= true;
1452 SetUpScheduler(true);
1454 scheduler_
->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1456 // To test swap ack throttling, this test disables automatic swap acks.
1457 scheduler_
->SetMaxSwapsPending(1);
1458 client_
->SetAutomaticSwapAck(false);
1460 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1462 scheduler_
->SetNeedsCommit();
1463 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1466 EXPECT_SCOPED(AdvanceFrame());
1467 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1468 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1469 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1470 EXPECT_TRUE(client_
->needs_begin_frames());
1473 // Queue BeginFrame while we are still handling the previous BeginFrame.
1474 SendNextBeginFrame();
1475 EXPECT_NO_ACTION(client_
);
1476 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1477 EXPECT_TRUE(client_
->needs_begin_frames());
1480 // NotifyReadyToCommit should trigger the pending commit and draw.
1481 scheduler_
->NotifyBeginMainFrameStarted();
1482 scheduler_
->NotifyReadyToCommit();
1483 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1484 EXPECT_TRUE(client_
->needs_begin_frames());
1487 // Swapping will put us into a swap throttled state.
1488 // Run posted deadline.
1489 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1490 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1491 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1492 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1493 EXPECT_TRUE(client_
->needs_begin_frames());
1496 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1497 // but not a BeginMainFrame or draw.
1498 scheduler_
->SetNeedsCommit();
1499 scheduler_
->SetNeedsRedraw();
1500 // Run posted BeginRetroFrame.
1501 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false));
1502 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1503 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1504 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1505 EXPECT_TRUE(client_
->needs_begin_frames());
1508 // Let time pass sufficiently beyond the regular deadline but not beyond the
1510 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1511 base::TimeDelta::FromMicroseconds(1));
1512 task_runner().RunUntilTime(now_src()->Now());
1513 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1515 // Take us out of a swap throttled state.
1516 scheduler_
->DidSwapBuffersComplete();
1517 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_
);
1518 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1519 EXPECT_TRUE(client_
->needs_begin_frames());
1522 // Verify that the deadline was rescheduled.
1523 task_runner().RunUntilTime(now_src()->Now());
1524 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
1525 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1526 EXPECT_TRUE(client_
->needs_begin_frames());
1530 TEST_F(SchedulerTest
, RetroFrameDoesNotExpireTooEarly
) {
1531 scheduler_settings_
.use_external_begin_frame_source
= true;
1532 SetUpScheduler(true);
1534 scheduler_
->SetNeedsCommit();
1535 EXPECT_TRUE(client_
->needs_begin_frames());
1536 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1539 EXPECT_SCOPED(AdvanceFrame());
1540 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1541 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1542 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1545 scheduler_
->NotifyBeginMainFrameStarted();
1548 SendNextBeginFrame();
1549 // This BeginFrame is queued up as a retro frame.
1550 EXPECT_NO_ACTION(client_
);
1551 // The previous deadline is still pending.
1552 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1555 // This commit should schedule the (previous) deadline to trigger immediately.
1556 scheduler_
->NotifyReadyToCommit();
1557 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1560 // The deadline task should trigger causing a draw.
1561 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1562 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1563 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1564 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1568 scheduler_
->SetNeedsAnimate();
1569 scheduler_
->SetNeedsRedraw();
1570 EXPECT_NO_ACTION(client_
);
1572 // Let's advance sufficiently past the next frame's deadline.
1573 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1574 BeginFrameArgs::DefaultEstimatedParentDrawTime() +
1575 base::TimeDelta::FromMicroseconds(1));
1577 // The retro frame hasn't expired yet.
1578 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false));
1579 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1580 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1581 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1583 // This is an immediate deadline case.
1585 task_runner().RunPendingTasks();
1586 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1587 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
1590 TEST_F(SchedulerTest
, RetroFrameDoesNotExpireTooLate
) {
1591 scheduler_settings_
.use_external_begin_frame_source
= true;
1592 SetUpScheduler(true);
1594 scheduler_
->SetNeedsCommit();
1595 EXPECT_TRUE(client_
->needs_begin_frames());
1596 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1599 EXPECT_SCOPED(AdvanceFrame());
1600 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1601 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1602 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1605 scheduler_
->NotifyBeginMainFrameStarted();
1608 SendNextBeginFrame();
1609 // This BeginFrame is queued up as a retro frame.
1610 EXPECT_NO_ACTION(client_
);
1611 // The previous deadline is still pending.
1612 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1615 // This commit should schedule the (previous) deadline to trigger immediately.
1616 scheduler_
->NotifyReadyToCommit();
1617 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1620 // The deadline task should trigger causing a draw.
1621 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1622 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1623 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1624 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1628 scheduler_
->SetNeedsAnimate();
1629 scheduler_
->SetNeedsRedraw();
1630 EXPECT_NO_ACTION(client_
);
1632 // Let's advance sufficiently past the next frame's deadline.
1633 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() +
1634 base::TimeDelta::FromMicroseconds(1));
1636 // The retro frame should've expired.
1637 EXPECT_NO_ACTION(client_
);
1640 void SchedulerTest::BeginFramesNotFromClient(
1641 bool use_external_begin_frame_source
,
1642 bool throttle_frame_production
) {
1643 scheduler_settings_
.use_external_begin_frame_source
=
1644 use_external_begin_frame_source
;
1645 scheduler_settings_
.throttle_frame_production
= throttle_frame_production
;
1646 SetUpScheduler(true);
1648 // SetNeedsCommit should begin the frame on the next BeginImplFrame
1649 // without calling SetNeedsBeginFrame.
1650 scheduler_
->SetNeedsCommit();
1651 EXPECT_NO_ACTION(client_
);
1654 // When the client-driven BeginFrame are disabled, the scheduler posts it's
1655 // own BeginFrame tasks.
1656 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1657 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1658 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1659 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1662 // If we don't swap on the deadline, we wait for the next BeginFrame.
1663 task_runner().RunPendingTasks(); // Run posted deadline.
1664 EXPECT_NO_ACTION(client_
);
1665 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1668 // NotifyReadyToCommit should trigger the commit.
1669 scheduler_
->NotifyBeginMainFrameStarted();
1670 scheduler_
->NotifyReadyToCommit();
1671 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1674 // BeginImplFrame should prepare the draw.
1675 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1676 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1677 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1678 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1681 // BeginImplFrame deadline should draw.
1682 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1683 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
1684 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1687 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1688 // to avoid excessive toggles.
1689 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1690 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
1691 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1694 // Make sure SetNeedsBeginFrame isn't called on the client
1695 // when the BeginFrame is no longer needed.
1696 task_runner().RunPendingTasks(); // Run posted deadline.
1697 EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_
);
1701 TEST_F(SchedulerTest
, SyntheticBeginFrames
) {
1702 bool use_external_begin_frame_source
= false;
1703 bool throttle_frame_production
= true;
1704 BeginFramesNotFromClient(use_external_begin_frame_source
,
1705 throttle_frame_production
);
1708 TEST_F(SchedulerTest
, VSyncThrottlingDisabled
) {
1709 bool use_external_begin_frame_source
= true;
1710 bool throttle_frame_production
= false;
1711 BeginFramesNotFromClient(use_external_begin_frame_source
,
1712 throttle_frame_production
);
1715 TEST_F(SchedulerTest
, SyntheticBeginFrames_And_VSyncThrottlingDisabled
) {
1716 bool use_external_begin_frame_source
= false;
1717 bool throttle_frame_production
= false;
1718 BeginFramesNotFromClient(use_external_begin_frame_source
,
1719 throttle_frame_production
);
1722 void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
1723 bool use_external_begin_frame_source
,
1724 bool throttle_frame_production
) {
1725 scheduler_settings_
.use_external_begin_frame_source
=
1726 use_external_begin_frame_source
;
1727 scheduler_settings_
.throttle_frame_production
= throttle_frame_production
;
1728 SetUpScheduler(true);
1730 scheduler_
->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1732 // To test swap ack throttling, this test disables automatic swap acks.
1733 scheduler_
->SetMaxSwapsPending(1);
1734 client_
->SetAutomaticSwapAck(false);
1736 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1738 scheduler_
->SetNeedsCommit();
1739 EXPECT_NO_ACTION(client_
);
1742 // Trigger the first BeginImplFrame and BeginMainFrame
1743 EXPECT_SCOPED(AdvanceFrame());
1744 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1745 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1746 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1749 // NotifyReadyToCommit should trigger the pending commit and draw.
1750 scheduler_
->NotifyBeginMainFrameStarted();
1751 scheduler_
->NotifyReadyToCommit();
1752 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1755 // Swapping will put us into a swap throttled state.
1756 // Run posted deadline.
1757 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1758 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1759 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1760 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1763 // While swap throttled, BeginFrames should trigger BeginImplFrames,
1764 // but not a BeginMainFrame or draw.
1765 scheduler_
->SetNeedsCommit();
1766 scheduler_
->SetNeedsRedraw();
1767 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
1768 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1769 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1770 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1773 // Let time pass sufficiently beyond the regular deadline but not beyond the
1775 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1776 base::TimeDelta::FromMicroseconds(1));
1777 task_runner().RunUntilTime(now_src()->Now());
1778 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1780 // Take us out of a swap throttled state.
1781 scheduler_
->DidSwapBuffersComplete();
1782 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_
);
1783 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1786 // Verify that the deadline was rescheduled.
1787 // We can't use RunUntilTime(now) here because the next frame is also
1788 // scheduled if throttle_frame_production = false.
1789 base::TimeTicks before_deadline
= now_src()->Now();
1790 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1791 base::TimeTicks after_deadline
= now_src()->Now();
1792 EXPECT_EQ(after_deadline
, before_deadline
);
1793 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1797 TEST_F(SchedulerTest
, SyntheticBeginFrames_SwapThrottled
) {
1798 bool use_external_begin_frame_source
= false;
1799 bool throttle_frame_production
= true;
1800 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1801 throttle_frame_production
);
1804 TEST_F(SchedulerTest
, VSyncThrottlingDisabled_SwapThrottled
) {
1805 bool use_external_begin_frame_source
= true;
1806 bool throttle_frame_production
= false;
1807 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1808 throttle_frame_production
);
1811 TEST_F(SchedulerTest
,
1812 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled
) {
1813 bool use_external_begin_frame_source
= false;
1814 bool throttle_frame_production
= false;
1815 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1816 throttle_frame_production
);
1819 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized
) {
1820 scheduler_settings_
.use_external_begin_frame_source
= true;
1821 SetUpScheduler(false);
1823 scheduler_
->SetCanStart();
1824 scheduler_
->SetVisible(true);
1825 scheduler_
->SetCanDraw(true);
1827 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
1829 scheduler_
->DidCreateAndInitializeOutputSurface();
1830 EXPECT_NO_ACTION(client_
);
1832 scheduler_
->DidLoseOutputSurface();
1833 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
1836 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterBeginFrameStarted
) {
1837 scheduler_settings_
.use_external_begin_frame_source
= true;
1838 SetUpScheduler(true);
1840 // SetNeedsCommit should begin the frame.
1841 scheduler_
->SetNeedsCommit();
1842 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1845 EXPECT_SCOPED(AdvanceFrame());
1846 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1847 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1848 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1851 scheduler_
->DidLoseOutputSurface();
1852 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1853 EXPECT_NO_ACTION(client_
);
1856 scheduler_
->NotifyBeginMainFrameStarted();
1857 scheduler_
->NotifyReadyToCommit();
1858 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 1);
1861 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1862 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
1863 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
1864 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
1867 void SchedulerTest::DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
1868 bool impl_side_painting
) {
1869 scheduler_settings_
.impl_side_painting
= impl_side_painting
;
1870 scheduler_settings_
.use_external_begin_frame_source
= true;
1871 SetUpScheduler(true);
1873 // SetNeedsCommit should begin the frame.
1874 scheduler_
->SetNeedsCommit();
1875 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1878 EXPECT_SCOPED(AdvanceFrame());
1879 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1880 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1881 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1884 scheduler_
->DidLoseOutputSurface();
1885 // Do nothing when impl frame is in deadine pending state.
1886 EXPECT_NO_ACTION(client_
);
1889 // Run posted deadline.
1890 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1891 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1892 // OnBeginImplFrameDeadline didn't schedule output surface creation because
1893 // main frame is not yet completed.
1894 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
1895 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
1896 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1898 // BeginImplFrame is not started.
1900 task_runner().RunUntilTime(now_src()->Now() +
1901 base::TimeDelta::FromMilliseconds(10));
1902 EXPECT_NO_ACTION(client_
);
1903 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1906 scheduler_
->NotifyBeginMainFrameStarted();
1907 scheduler_
->NotifyReadyToCommit();
1908 if (impl_side_painting
) {
1909 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 3);
1910 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 1, 3);
1911 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 2, 3);
1913 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 2);
1914 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 1, 2);
1918 TEST_F(SchedulerTest
,
1919 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency
) {
1920 bool impl_side_painting
= false;
1921 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
1924 TEST_F(SchedulerTest
,
1925 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint
) {
1926 bool impl_side_painting
= true;
1927 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
1930 void SchedulerTest::DidLoseOutputSurfaceAfterReadyToCommit(
1931 bool impl_side_painting
) {
1932 scheduler_settings_
.impl_side_painting
= impl_side_painting
;
1933 scheduler_settings_
.use_external_begin_frame_source
= true;
1934 SetUpScheduler(true);
1936 // SetNeedsCommit should begin the frame.
1937 scheduler_
->SetNeedsCommit();
1938 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1941 EXPECT_SCOPED(AdvanceFrame());
1942 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1943 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1944 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1947 scheduler_
->NotifyBeginMainFrameStarted();
1948 scheduler_
->NotifyReadyToCommit();
1949 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1952 scheduler_
->DidLoseOutputSurface();
1953 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1954 if (impl_side_painting
) {
1955 // Sync tree should be forced to activate.
1956 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
1958 EXPECT_NO_ACTION(client_
);
1962 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1963 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
1964 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
1965 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
1968 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommit
) {
1969 DidLoseOutputSurfaceAfterReadyToCommit(false);
1972 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting
) {
1973 DidLoseOutputSurfaceAfterReadyToCommit(true);
1976 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles
) {
1977 scheduler_settings_
.use_external_begin_frame_source
= true;
1978 SetUpScheduler(true);
1980 scheduler_
->SetNeedsPrepareTiles();
1981 scheduler_
->SetNeedsRedraw();
1982 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1985 EXPECT_SCOPED(AdvanceFrame());
1986 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1987 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1988 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1991 scheduler_
->DidLoseOutputSurface();
1992 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1993 EXPECT_NO_ACTION(client_
);
1996 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1997 EXPECT_ACTION("ScheduledActionPrepareTiles", client_
, 0, 4);
1998 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 1, 4);
1999 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 2, 4);
2000 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 3, 4);
2003 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterBeginRetroFramePosted
) {
2004 scheduler_settings_
.use_external_begin_frame_source
= true;
2005 SetUpScheduler(true);
2007 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2008 scheduler_
->SetNeedsCommit();
2009 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2011 // Create a BeginFrame with a long deadline to avoid race conditions.
2012 // This is the first BeginFrame, which will be handled immediately.
2014 BeginFrameArgs args
=
2015 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
2016 args
.deadline
+= base::TimeDelta::FromHours(1);
2017 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2018 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2019 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2020 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2021 EXPECT_TRUE(client_
->needs_begin_frames());
2023 // Queue BeginFrames while we are still handling the previous BeginFrame.
2024 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2025 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2026 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2027 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2029 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2031 task_runner().RunPendingTasks(); // Run posted deadline.
2032 EXPECT_NO_ACTION(client_
);
2033 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2034 EXPECT_TRUE(client_
->needs_begin_frames());
2036 // NotifyReadyToCommit should trigger the commit.
2038 scheduler_
->NotifyBeginMainFrameStarted();
2039 scheduler_
->NotifyReadyToCommit();
2040 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2041 EXPECT_TRUE(client_
->needs_begin_frames());
2044 EXPECT_FALSE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2045 scheduler_
->DidLoseOutputSurface();
2046 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2047 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2048 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2049 EXPECT_TRUE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2051 // Posted BeginRetroFrame is aborted.
2053 task_runner().RunPendingTasks();
2054 EXPECT_NO_ACTION(client_
);
2057 TEST_F(SchedulerTest
, DidLoseOutputSurfaceDuringBeginRetroFrameRunning
) {
2058 scheduler_settings_
.use_external_begin_frame_source
= true;
2059 SetUpScheduler(true);
2061 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2062 scheduler_
->SetNeedsCommit();
2063 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2065 // Create a BeginFrame with a long deadline to avoid race conditions.
2066 // This is the first BeginFrame, which will be handled immediately.
2068 BeginFrameArgs args
=
2069 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
2070 args
.deadline
+= base::TimeDelta::FromHours(1);
2071 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2072 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2073 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2074 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2075 EXPECT_TRUE(client_
->needs_begin_frames());
2077 // Queue BeginFrames while we are still handling the previous BeginFrame.
2078 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2079 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2080 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2081 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2083 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2085 task_runner().RunPendingTasks(); // Run posted deadline.
2086 EXPECT_NO_ACTION(client_
);
2087 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2088 EXPECT_TRUE(client_
->needs_begin_frames());
2090 // NotifyReadyToCommit should trigger the commit.
2092 scheduler_
->NotifyBeginMainFrameStarted();
2093 scheduler_
->NotifyReadyToCommit();
2094 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2095 EXPECT_TRUE(client_
->needs_begin_frames());
2097 // BeginImplFrame should prepare the draw.
2099 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2100 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2101 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2102 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2103 EXPECT_TRUE(client_
->needs_begin_frames());
2106 EXPECT_FALSE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2107 scheduler_
->DidLoseOutputSurface();
2108 EXPECT_NO_ACTION(client_
);
2109 EXPECT_TRUE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2111 // BeginImplFrame deadline should abort drawing.
2113 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2114 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2115 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2116 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2117 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2118 EXPECT_FALSE(client_
->needs_begin_frames());
2120 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
2122 task_runner().RunPendingTasks();
2123 EXPECT_NO_ACTION(client_
);
2126 TEST_F(SchedulerTest
, DidLoseOutputSurfaceWithSyntheticBeginFrameSource
) {
2127 SetUpScheduler(true);
2129 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2130 EXPECT_FALSE(scheduler_
->frame_source().NeedsBeginFrames());
2131 scheduler_
->SetNeedsCommit();
2132 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2136 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2137 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2138 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2139 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2141 // NotifyReadyToCommit should trigger the commit.
2143 scheduler_
->NotifyBeginMainFrameStarted();
2144 scheduler_
->NotifyReadyToCommit();
2145 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2146 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2149 scheduler_
->DidLoseOutputSurface();
2150 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2151 EXPECT_NO_ACTION(client_
);
2152 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2155 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2156 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 2);
2157 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
2158 EXPECT_FALSE(scheduler_
->frame_source().NeedsBeginFrames());
2161 TEST_F(SchedulerTest
, DidLoseOutputSurfaceWhenIdle
) {
2162 scheduler_settings_
.use_external_begin_frame_source
= true;
2163 SetUpScheduler(true);
2165 // SetNeedsCommit should begin the frame.
2166 scheduler_
->SetNeedsCommit();
2167 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2170 EXPECT_SCOPED(AdvanceFrame());
2171 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2172 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2173 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2176 scheduler_
->NotifyBeginMainFrameStarted();
2177 scheduler_
->NotifyReadyToCommit();
2178 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2181 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2182 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2183 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2185 // Idle time between BeginFrames.
2187 scheduler_
->DidLoseOutputSurface();
2188 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2189 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2190 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2193 TEST_F(SchedulerTest
, ScheduledActionActivateAfterBecomingInvisible
) {
2194 scheduler_settings_
.impl_side_painting
= true;
2195 scheduler_settings_
.use_external_begin_frame_source
= true;
2196 SetUpScheduler(true);
2198 // SetNeedsCommit should begin the frame.
2199 scheduler_
->SetNeedsCommit();
2200 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2203 EXPECT_SCOPED(AdvanceFrame());
2204 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2205 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2206 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2209 scheduler_
->NotifyBeginMainFrameStarted();
2210 scheduler_
->NotifyReadyToCommit();
2211 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2214 scheduler_
->SetVisible(false);
2215 // Sync tree should be forced to activate.
2216 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
2217 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 1, 2);
2220 // Tests to ensure frame sources can be successfully changed while drawing.
2221 TEST_F(SchedulerTest
, SwitchFrameSourceToUnthrottled
) {
2222 scheduler_settings_
.use_external_begin_frame_source
= true;
2223 SetUpScheduler(true);
2225 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2226 scheduler_
->SetNeedsRedraw();
2227 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", 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);
2238 scheduler_
->SetNeedsRedraw();
2240 // Switch to an unthrottled frame source.
2241 scheduler_
->SetThrottleFrameProduction(false);
2244 // Unthrottled frame source will immediately begin a new frame.
2245 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2246 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2247 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2248 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2251 // If we don't swap on the deadline, we wait for the next BeginFrame.
2252 task_runner().RunPendingTasks(); // Run posted deadline.
2253 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2254 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2258 // Tests to ensure frame sources can be successfully changed while a frame
2259 // deadline is pending.
2260 TEST_F(SchedulerTest
, SwitchFrameSourceToUnthrottledBeforeDeadline
) {
2261 scheduler_settings_
.use_external_begin_frame_source
= true;
2262 SetUpScheduler(true);
2264 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2265 scheduler_
->SetNeedsRedraw();
2266 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2269 EXPECT_SCOPED(AdvanceFrame());
2270 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2271 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2273 // Switch to an unthrottled frame source before the frame deadline is hit.
2274 scheduler_
->SetThrottleFrameProduction(false);
2277 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2278 EXPECT_TRUE(client_
->needs_begin_frames());
2281 task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame.
2282 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 2);
2283 // Unthrottled frame source will immediately begin a new frame.
2284 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 2);
2285 scheduler_
->SetNeedsRedraw();
2288 task_runner().RunPendingTasks(); // Run posted deadline.
2289 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2290 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2291 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2295 // Tests to ensure that the active frame source can successfully be changed from
2296 // unthrottled to throttled.
2297 TEST_F(SchedulerTest
, SwitchFrameSourceToThrottled
) {
2298 scheduler_settings_
.throttle_frame_production
= false;
2299 scheduler_settings_
.use_external_begin_frame_source
= true;
2300 SetUpScheduler(true);
2302 scheduler_
->SetNeedsRedraw();
2303 EXPECT_NO_ACTION(client_
);
2306 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2307 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2308 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2309 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2312 task_runner().RunPendingTasks(); // Run posted deadline.
2313 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2314 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2317 // Switch to a throttled frame source.
2318 scheduler_
->SetThrottleFrameProduction(true);
2321 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2322 scheduler_
->SetNeedsRedraw();
2323 task_runner().RunPendingTasks();
2324 EXPECT_NO_ACTION(client_
);
2327 EXPECT_SCOPED(AdvanceFrame());
2328 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2329 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2330 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2331 EXPECT_TRUE(client_
->needs_begin_frames());
2333 task_runner().RunPendingTasks(); // Run posted deadline.
2334 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2337 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
2338 TEST_F(SchedulerTest
, SendBeginMainFrameNotExpectedSoon
) {
2339 scheduler_settings_
.use_external_begin_frame_source
= true;
2340 SetUpScheduler(true);
2342 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2343 scheduler_
->SetNeedsCommit();
2344 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2347 // Trigger a frame draw.
2348 EXPECT_SCOPED(AdvanceFrame());
2349 scheduler_
->NotifyBeginMainFrameStarted();
2350 scheduler_
->NotifyReadyToCommit();
2351 task_runner().RunPendingTasks();
2352 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 5);
2353 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 5);
2354 EXPECT_ACTION("ScheduledActionCommit", client_
, 2, 5);
2355 EXPECT_ACTION("ScheduledActionAnimate", client_
, 3, 5);
2356 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 4, 5);
2359 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2360 // and send a SendBeginMainFrameNotExpectedSoon.
2361 EXPECT_SCOPED(AdvanceFrame());
2362 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
2363 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2366 task_runner().RunPendingTasks(); // Run posted deadline.
2367 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
2368 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
2372 TEST_F(SchedulerTest
, UsingSynchronousCompositor
) {
2373 scheduler_settings_
.using_synchronous_renderer_compositor
= true;
2374 scheduler_settings_
.use_external_begin_frame_source
= true;
2375 scheduler_settings_
.impl_side_painting
= true;
2376 SetUpScheduler(true);
2378 // Compositor thread initiated input/animation.
2379 // --------------------------------------------
2380 scheduler_
->SetNeedsAnimate();
2381 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2386 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2387 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
2388 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
2389 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2392 // Continue with animation.
2393 scheduler_
->SetNeedsAnimate();
2394 EXPECT_NO_ACTION(client_
);
2397 scheduler_
->SetNeedsRedraw();
2398 scheduler_
->OnDrawForOutputSurface();
2399 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
2400 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2405 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2406 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
2407 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
2408 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2412 scheduler_
->SetNeedsRedraw();
2413 scheduler_
->OnDrawForOutputSurface();
2414 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
2415 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2418 // Idle on next vsync.
2420 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2421 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2422 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2423 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2426 // Android onDraw after idle.
2427 // --------------------------
2428 scheduler_
->SetNeedsRedraw();
2429 scheduler_
->OnDrawForOutputSurface();
2430 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_
, 0, 3);
2431 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
2432 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 2, 3);
2433 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2436 // Idle on next vsync.
2438 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2439 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2440 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2441 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2444 // Main thread initiated activity.
2445 // -------------------------------
2446 scheduler_
->SetNeedsCommit();
2447 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2452 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2453 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2454 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2457 scheduler_
->NotifyBeginMainFrameStarted();
2458 EXPECT_NO_ACTION(client_
);
2462 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
2463 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2466 scheduler_
->NotifyReadyToCommit();
2467 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2470 scheduler_
->NotifyReadyToActivate();
2471 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
2476 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2477 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
2478 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
2479 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2483 scheduler_
->SetNeedsRedraw();
2484 scheduler_
->OnDrawForOutputSurface();
2485 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
2486 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2489 // Idle on next vsync.
2491 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2492 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2493 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2494 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2498 TEST_F(SchedulerTest
, AuthoritativeVSyncInterval
) {
2499 SetUpScheduler(true);
2501 base::TimeDelta initial_interval
=
2502 scheduler_
->begin_impl_frame_args().interval
;
2503 base::TimeDelta authoritative_interval
=
2504 base::TimeDelta::FromMilliseconds(33);
2506 scheduler_
->SetNeedsCommit();
2507 EXPECT_SCOPED(AdvanceFrame());
2509 EXPECT_EQ(initial_interval
, scheduler_
->begin_impl_frame_args().interval
);
2511 scheduler_
->NotifyBeginMainFrameStarted();
2512 scheduler_
->NotifyReadyToCommit();
2513 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2515 scheduler_
->SetAuthoritativeVSyncInterval(authoritative_interval
);
2517 EXPECT_SCOPED(AdvanceFrame());
2519 // At the next BeginFrame, authoritative interval is used instead of previous
2521 EXPECT_NE(initial_interval
, scheduler_
->begin_impl_frame_args().interval
);
2522 EXPECT_EQ(authoritative_interval
,
2523 scheduler_
->begin_impl_frame_args().interval
);