1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/scheduler/scheduler.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_vector.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "base/time/time.h"
15 #include "base/trace_event/trace_event.h"
16 #include "cc/test/begin_frame_args_test.h"
17 #include "cc/test/ordered_simple_task_runner.h"
18 #include "cc/test/scheduler_test_common.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
24 EXPECT_EQ(expected_num_actions, client->num_actions_()); \
25 if (action_index >= 0) { \
26 ASSERT_LT(action_index, client->num_actions_()) << scheduler_.get(); \
27 EXPECT_STREQ(action, client->Action(action_index)); \
29 for (int i = expected_num_actions; i < client->num_actions_(); ++i) \
30 ADD_FAILURE() << "Unexpected action: " << client->Action(i) \
31 << " with state:\n" << client->StateForAction(i); \
34 #define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0)
36 #define EXPECT_SINGLE_ACTION(action, client) \
37 EXPECT_ACTION(action, client, 0, 1)
39 #define EXPECT_SCOPED(statements) \
48 class FakeSchedulerClient
: public SchedulerClient
{
51 : automatic_swap_ack_(true),
52 begin_frame_is_sent_to_children_(false),
60 draw_will_happen_
= true;
61 swap_will_happen_if_draw_happens_
= true;
63 log_anticipated_draw_time_change_
= false;
64 begin_frame_is_sent_to_children_
= false;
67 void set_scheduler(TestScheduler
* scheduler
) { scheduler_
= scheduler
; }
69 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
71 void set_log_anticipated_draw_time_change(bool log
) {
72 log_anticipated_draw_time_change_
= log
;
74 bool needs_begin_frames() {
75 return scheduler_
->frame_source().NeedsBeginFrames();
77 int num_draws() const { return num_draws_
; }
78 int num_actions_() const { return static_cast<int>(actions_
.size()); }
79 const char* Action(int i
) const { return actions_
[i
]; }
80 std::string
StateForAction(int i
) const { return states_
[i
]->ToString(); }
81 base::TimeTicks
posted_begin_impl_frame_deadline() const {
82 return posted_begin_impl_frame_deadline_
;
85 int ActionIndex(const char* action
) const {
86 for (size_t i
= 0; i
< actions_
.size(); i
++)
87 if (!strcmp(actions_
[i
], action
))
92 bool HasAction(const char* action
) const {
93 return ActionIndex(action
) >= 0;
96 void SetDrawWillHappen(bool draw_will_happen
) {
97 draw_will_happen_
= draw_will_happen
;
99 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens
) {
100 swap_will_happen_if_draw_happens_
= swap_will_happen_if_draw_happens
;
102 void SetAutomaticSwapAck(bool automatic_swap_ack
) {
103 automatic_swap_ack_
= automatic_swap_ack
;
105 // SchedulerClient implementation.
106 void WillBeginImplFrame(const BeginFrameArgs
& args
) override
{
107 PushAction("WillBeginImplFrame");
109 void ScheduledActionSendBeginMainFrame() override
{
110 PushAction("ScheduledActionSendBeginMainFrame");
112 void ScheduledActionAnimate() override
{
113 PushAction("ScheduledActionAnimate");
115 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
116 PushAction("ScheduledActionDrawAndSwapIfPossible");
119 draw_will_happen_
? DRAW_SUCCESS
: DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
;
120 bool swap_will_happen
=
121 draw_will_happen_
&& swap_will_happen_if_draw_happens_
;
122 if (swap_will_happen
) {
123 scheduler_
->DidSwapBuffers();
125 if (automatic_swap_ack_
)
126 scheduler_
->DidSwapBuffersComplete();
130 DrawResult
ScheduledActionDrawAndSwapForced() override
{
131 PushAction("ScheduledActionDrawAndSwapForced");
134 void ScheduledActionCommit() override
{ PushAction("ScheduledActionCommit"); }
135 void ScheduledActionActivateSyncTree() override
{
136 PushAction("ScheduledActionActivateSyncTree");
138 void ScheduledActionBeginOutputSurfaceCreation() override
{
139 PushAction("ScheduledActionBeginOutputSurfaceCreation");
141 void ScheduledActionPrepareTiles() override
{
142 PushAction("ScheduledActionPrepareTiles");
144 void ScheduledActionInvalidateOutputSurface() override
{
145 actions_
.push_back("ScheduledActionInvalidateOutputSurface");
146 states_
.push_back(scheduler_
->AsValue());
148 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{
149 if (log_anticipated_draw_time_change_
)
150 PushAction("DidAnticipatedDrawTimeChange");
152 base::TimeDelta
DrawDurationEstimate() override
{ return base::TimeDelta(); }
153 base::TimeDelta
BeginMainFrameToCommitDurationEstimate() override
{
154 return base::TimeDelta();
156 base::TimeDelta
CommitToActivateDurationEstimate() override
{
157 return base::TimeDelta();
160 void DidBeginImplFrameDeadline() override
{}
162 void SendBeginFramesToChildren(const BeginFrameArgs
& args
) override
{
163 begin_frame_is_sent_to_children_
= true;
166 void SendBeginMainFrameNotExpectedSoon() override
{
167 PushAction("SendBeginMainFrameNotExpectedSoon");
170 base::Callback
<bool(void)> ImplFrameDeadlinePending(bool state
) {
171 return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback
,
172 base::Unretained(this),
176 bool begin_frame_is_sent_to_children() const {
177 return begin_frame_is_sent_to_children_
;
180 void PushAction(const char* description
) {
181 actions_
.push_back(description
);
182 states_
.push_back(scheduler_
->AsValue());
186 bool ImplFrameDeadlinePendingCallback(bool state
) {
187 return scheduler_
->BeginImplFrameDeadlinePending() == state
;
190 bool draw_will_happen_
;
191 bool swap_will_happen_if_draw_happens_
;
192 bool automatic_swap_ack_
;
194 bool log_anticipated_draw_time_change_
;
195 bool begin_frame_is_sent_to_children_
;
196 base::TimeTicks posted_begin_impl_frame_deadline_
;
197 std::vector
<const char*> actions_
;
198 std::vector
<scoped_refptr
<base::trace_event::ConvertableToTraceFormat
>>
200 TestScheduler
* scheduler_
;
203 class FakeExternalBeginFrameSource
: public BeginFrameSourceMixIn
{
205 explicit FakeExternalBeginFrameSource(FakeSchedulerClient
* client
)
207 ~FakeExternalBeginFrameSource() override
{}
209 void OnNeedsBeginFramesChange(bool needs_begin_frames
) override
{
210 if (needs_begin_frames
) {
211 client_
->PushAction("SetNeedsBeginFrames(true)");
213 client_
->PushAction("SetNeedsBeginFrames(false)");
217 void TestOnBeginFrame(const BeginFrameArgs
& args
) {
218 return CallOnBeginFrame(args
);
222 FakeSchedulerClient
* client_
;
225 class SchedulerTest
: public testing::Test
{
228 : now_src_(TestNowSource::Create()),
229 task_runner_(new OrderedSimpleTaskRunner(now_src_
, true)),
230 fake_external_begin_frame_source_(nullptr) {
231 // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval()
232 now_src_
->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
233 // Fail if we need to run 100 tasks in a row.
234 task_runner_
->SetRunTaskLimit(100);
237 ~SchedulerTest() override
{}
240 TestScheduler
* CreateScheduler() {
241 scoped_ptr
<FakeExternalBeginFrameSource
> fake_external_begin_frame_source
;
242 if (scheduler_settings_
.use_external_begin_frame_source
) {
243 fake_external_begin_frame_source
.reset(
244 new FakeExternalBeginFrameSource(client_
.get()));
245 fake_external_begin_frame_source_
=
246 fake_external_begin_frame_source
.get();
248 scheduler_
= TestScheduler::Create(now_src_
, client_
.get(),
249 scheduler_settings_
, 0, task_runner_
,
250 fake_external_begin_frame_source
.Pass());
252 client_
->set_scheduler(scheduler_
.get());
253 return scheduler_
.get();
256 void CreateSchedulerAndInitSurface() {
258 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit());
261 void SetUpScheduler(bool initSurface
) {
262 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient
), initSurface
);
265 void SetUpScheduler(scoped_ptr
<FakeSchedulerClient
> client
,
267 client_
= client
.Pass();
269 CreateSchedulerAndInitSurface();
274 OrderedSimpleTaskRunner
& task_runner() { return *task_runner_
; }
275 TestNowSource
* now_src() { return now_src_
.get(); }
277 // As this function contains EXPECT macros, to allow debugging it should be
278 // called inside EXPECT_SCOPED like so;
279 // EXPECT_SCOPED(client.InitializeOutputSurfaceAndFirstCommit(scheduler));
280 void InitializeOutputSurfaceAndFirstCommit() {
282 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit");
285 // Check the client doesn't have any actions queued when calling this
287 EXPECT_NO_ACTION(client_
);
288 EXPECT_FALSE(client_
->needs_begin_frames());
290 // Start the initial output surface creation.
291 EXPECT_FALSE(scheduler_
->CanStart());
292 scheduler_
->SetCanStart();
293 scheduler_
->SetVisible(true);
294 scheduler_
->SetCanDraw(true);
295 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
299 // We don't see anything happening until the first impl frame.
300 scheduler_
->DidCreateAndInitializeOutputSurface();
301 scheduler_
->SetNeedsCommit();
302 EXPECT_TRUE(client_
->needs_begin_frames());
303 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
307 SCOPED_TRACE("Do first frame to commit after initialize.");
310 scheduler_
->NotifyBeginMainFrameStarted();
311 scheduler_
->NotifyReadyToCommitThenActivateIfNeeded();
313 EXPECT_FALSE(scheduler_
->CommitPending());
315 if (scheduler_settings_
.using_synchronous_renderer_compositor
) {
316 scheduler_
->SetNeedsRedraw();
317 scheduler_
->OnDrawForOutputSurface();
319 // Run the posted deadline task.
320 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
321 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
324 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
331 "Run second frame so Scheduler calls SetNeedsBeginFrame(false).");
334 if (!scheduler_settings_
.using_synchronous_renderer_compositor
) {
335 // Run the posted deadline task.
336 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
337 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
340 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
343 EXPECT_FALSE(client_
->needs_begin_frames());
347 // As this function contains EXPECT macros, to allow debugging it should be
348 // called inside EXPECT_SCOPED like so;
349 // EXPECT_SCOPED(client.AdvanceFrame());
350 void AdvanceFrame() {
351 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
352 "FakeSchedulerClient::AdvanceFrame");
353 // Consume any previous deadline first, if no deadline is currently
354 // pending, ImplFrameDeadlinePending will return false straight away and we
355 // will run no tasks.
356 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
357 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
359 // Send the next BeginFrame message if using an external source, otherwise
360 // it will be already in the task queue.
361 if (scheduler_
->settings().use_external_begin_frame_source
&&
362 scheduler_
->FrameProductionThrottled()) {
363 EXPECT_TRUE(client_
->needs_begin_frames());
364 SendNextBeginFrame();
367 if (!scheduler_
->settings().using_synchronous_renderer_compositor
) {
368 // Then run tasks until new deadline is scheduled.
369 EXPECT_TRUE(task_runner_
->RunTasksWhile(
370 client_
->ImplFrameDeadlinePending(false)));
371 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
375 void SendNextBeginFrame() {
376 DCHECK(scheduler_
->settings().use_external_begin_frame_source
);
377 // Creep the time forward so that any BeginFrameArgs is not equal to the
378 // last one otherwise we violate the BeginFrameSource contract.
379 now_src_
->AdvanceNow(BeginFrameArgs::DefaultInterval());
380 fake_external_begin_frame_source_
->TestOnBeginFrame(
381 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src()));
384 FakeExternalBeginFrameSource
* fake_external_begin_frame_source() const {
385 return fake_external_begin_frame_source_
;
388 void MainFrameInHighLatencyMode(
389 int64 begin_main_frame_to_commit_estimate_in_ms
,
390 int64 commit_to_activate_estimate_in_ms
,
391 bool impl_latency_takes_priority
,
392 bool should_send_begin_main_frame
);
393 void BeginFramesNotFromClient(bool use_external_begin_frame_source
,
394 bool throttle_frame_production
);
395 void BeginFramesNotFromClient_SwapThrottled(
396 bool use_external_begin_frame_source
,
397 bool throttle_frame_production
);
398 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
399 bool impl_side_painting
);
400 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting
);
402 scoped_refptr
<TestNowSource
> now_src_
;
403 scoped_refptr
<OrderedSimpleTaskRunner
> task_runner_
;
404 FakeExternalBeginFrameSource
* fake_external_begin_frame_source_
;
405 SchedulerSettings scheduler_settings_
;
406 scoped_ptr
<FakeSchedulerClient
> client_
;
407 scoped_ptr
<TestScheduler
> scheduler_
;
410 TEST_F(SchedulerTest
, InitializeOutputSurfaceDoesNotBeginImplFrame
) {
411 scheduler_settings_
.use_external_begin_frame_source
= true;
412 SetUpScheduler(false);
413 scheduler_
->SetCanStart();
414 scheduler_
->SetVisible(true);
415 scheduler_
->SetCanDraw(true);
417 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
419 scheduler_
->DidCreateAndInitializeOutputSurface();
420 EXPECT_NO_ACTION(client_
);
423 TEST_F(SchedulerTest
, SendBeginFramesToChildren
) {
424 scheduler_settings_
.use_external_begin_frame_source
= true;
425 SetUpScheduler(true);
427 EXPECT_FALSE(client_
->begin_frame_is_sent_to_children());
428 scheduler_
->SetNeedsCommit();
429 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
430 EXPECT_TRUE(client_
->needs_begin_frames());
432 scheduler_
->SetChildrenNeedBeginFrames(true);
435 EXPECT_SCOPED(AdvanceFrame());
436 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
437 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
438 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
439 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
440 EXPECT_TRUE(client_
->needs_begin_frames());
443 TEST_F(SchedulerTest
, SendBeginFramesToChildrenWithoutCommit
) {
444 scheduler_settings_
.use_external_begin_frame_source
= true;
445 SetUpScheduler(true);
447 EXPECT_FALSE(client_
->needs_begin_frames());
448 scheduler_
->SetChildrenNeedBeginFrames(true);
449 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
450 EXPECT_TRUE(client_
->needs_begin_frames());
453 EXPECT_SCOPED(AdvanceFrame());
454 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
457 TEST_F(SchedulerTest
, VideoNeedsBeginFrames
) {
458 scheduler_settings_
.use_external_begin_frame_source
= true;
459 SetUpScheduler(true);
461 scheduler_
->SetVideoNeedsBeginFrames(true);
462 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
463 EXPECT_TRUE(client_
->needs_begin_frames());
466 EXPECT_SCOPED(AdvanceFrame());
467 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
468 // WillBeginImplFrame is responsible for sending BeginFrames to video.
469 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
472 EXPECT_SCOPED(AdvanceFrame());
473 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
474 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
477 scheduler_
->SetVideoNeedsBeginFrames(false);
478 EXPECT_NO_ACTION(client_
);
481 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
482 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
483 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
484 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
485 EXPECT_FALSE(client_
->needs_begin_frames());
488 TEST_F(SchedulerTest
, RequestCommit
) {
489 scheduler_settings_
.use_external_begin_frame_source
= true;
490 SetUpScheduler(true);
492 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
493 scheduler_
->SetNeedsCommit();
494 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
497 EXPECT_SCOPED(AdvanceFrame());
498 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
499 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
500 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
501 EXPECT_TRUE(client_
->needs_begin_frames());
504 // If we don't swap on the deadline, we wait for the next BeginFrame.
505 task_runner().RunPendingTasks(); // Run posted deadline.
506 EXPECT_NO_ACTION(client_
);
507 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
508 EXPECT_TRUE(client_
->needs_begin_frames());
511 // NotifyReadyToCommit should trigger the commit.
512 scheduler_
->NotifyBeginMainFrameStarted();
513 scheduler_
->NotifyReadyToCommit();
514 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
515 EXPECT_TRUE(client_
->needs_begin_frames());
518 // BeginImplFrame should prepare the draw.
519 EXPECT_SCOPED(AdvanceFrame());
520 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
521 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
522 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
523 EXPECT_TRUE(client_
->needs_begin_frames());
526 // BeginImplFrame deadline should draw.
527 task_runner().RunPendingTasks(); // Run posted deadline.
528 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
529 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
530 EXPECT_TRUE(client_
->needs_begin_frames());
533 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
534 // to avoid excessive toggles.
535 EXPECT_SCOPED(AdvanceFrame());
536 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
537 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
540 task_runner().RunPendingTasks(); // Run posted deadline.
541 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
542 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
546 TEST_F(SchedulerTest
, RequestCommitAfterSetDeferCommit
) {
547 scheduler_settings_
.use_external_begin_frame_source
= true;
548 SetUpScheduler(true);
550 scheduler_
->SetDeferCommits(true);
552 scheduler_
->SetNeedsCommit();
553 EXPECT_NO_ACTION(client_
);
556 task_runner().RunPendingTasks();
557 // There are no pending tasks or actions.
558 EXPECT_NO_ACTION(client_
);
559 EXPECT_FALSE(client_
->needs_begin_frames());
562 scheduler_
->SetDeferCommits(false);
563 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
565 // Start new BeginMainFrame after defer commit is off.
567 EXPECT_SCOPED(AdvanceFrame());
568 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
569 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
570 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
573 TEST_F(SchedulerTest
, DeferCommitWithRedraw
) {
574 scheduler_settings_
.use_external_begin_frame_source
= true;
575 SetUpScheduler(true);
577 scheduler_
->SetDeferCommits(true);
579 scheduler_
->SetNeedsCommit();
580 EXPECT_NO_ACTION(client_
);
582 // The SetNeedsRedraw will override the SetDeferCommits(true), to allow a
583 // begin frame to be needed.
585 scheduler_
->SetNeedsRedraw();
586 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
590 // BeginMainFrame is not sent during the defer commit is on.
591 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
592 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
595 task_runner().RunPendingTasks(); // Run posted deadline.
596 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
597 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
598 EXPECT_TRUE(client_
->needs_begin_frames());
602 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
605 TEST_F(SchedulerTest
, RequestCommitAfterBeginMainFrameSent
) {
606 scheduler_settings_
.use_external_begin_frame_source
= true;
607 SetUpScheduler(true);
609 // SetNeedsCommit should begin the frame.
610 scheduler_
->SetNeedsCommit();
611 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
614 EXPECT_SCOPED(AdvanceFrame());
615 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
616 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
617 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
619 EXPECT_TRUE(client_
->needs_begin_frames());
622 // Now SetNeedsCommit again. Calling here means we need a second commit.
623 scheduler_
->SetNeedsCommit();
624 EXPECT_EQ(client_
->num_actions_(), 0);
627 // Finish the first commit.
628 scheduler_
->NotifyBeginMainFrameStarted();
629 scheduler_
->NotifyReadyToCommit();
630 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
631 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
633 task_runner().RunPendingTasks(); // Run posted deadline.
634 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
635 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
636 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
638 // Because we just swapped, the Scheduler should also request the next
639 // BeginImplFrame from the OutputSurface.
640 EXPECT_TRUE(client_
->needs_begin_frames());
642 // Since another commit is needed, the next BeginImplFrame should initiate
643 // the second commit.
644 EXPECT_SCOPED(AdvanceFrame());
645 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
646 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
647 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
650 // Finishing the commit before the deadline should post a new deadline task
651 // to trigger the deadline early.
652 scheduler_
->NotifyBeginMainFrameStarted();
653 scheduler_
->NotifyReadyToCommit();
654 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
655 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
657 task_runner().RunPendingTasks(); // Run posted deadline.
658 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
659 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
660 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
661 EXPECT_TRUE(client_
->needs_begin_frames());
664 // On the next BeginImplFrame, verify we go back to a quiescent state and
665 // no longer request BeginImplFrames.
666 EXPECT_SCOPED(AdvanceFrame());
667 task_runner().RunPendingTasks(); // Run posted deadline.
668 EXPECT_FALSE(client_
->needs_begin_frames());
672 class SchedulerClientThatsetNeedsDrawInsideDraw
: public FakeSchedulerClient
{
674 SchedulerClientThatsetNeedsDrawInsideDraw()
675 : FakeSchedulerClient(), request_redraws_(false) {}
677 void ScheduledActionSendBeginMainFrame() override
{}
679 void SetRequestRedrawsInsideDraw(bool enable
) { request_redraws_
= enable
; }
681 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
682 // Only SetNeedsRedraw the first time this is called
683 if (request_redraws_
) {
684 scheduler_
->SetNeedsRedraw();
686 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
689 DrawResult
ScheduledActionDrawAndSwapForced() override
{
694 void ScheduledActionCommit() override
{}
695 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{}
698 bool request_redraws_
;
701 // Tests for two different situations:
702 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
703 // a ScheduledActionDrawAndSwap
704 // 2. the scheduler drawing twice inside a single tick
705 TEST_F(SchedulerTest
, RequestRedrawInsideDraw
) {
706 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
707 new SchedulerClientThatsetNeedsDrawInsideDraw
;
708 scheduler_settings_
.use_external_begin_frame_source
= true;
709 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
710 client
->SetRequestRedrawsInsideDraw(true);
712 scheduler_
->SetNeedsRedraw();
713 EXPECT_TRUE(scheduler_
->RedrawPending());
714 EXPECT_TRUE(client
->needs_begin_frames());
715 EXPECT_EQ(0, client
->num_draws());
717 EXPECT_SCOPED(AdvanceFrame());
718 task_runner().RunPendingTasks(); // Run posted deadline.
719 EXPECT_EQ(1, client
->num_draws());
720 EXPECT_TRUE(scheduler_
->RedrawPending());
721 EXPECT_TRUE(client
->needs_begin_frames());
723 client
->SetRequestRedrawsInsideDraw(false);
725 EXPECT_SCOPED(AdvanceFrame());
726 task_runner().RunPendingTasks(); // Run posted deadline.
727 EXPECT_EQ(2, client_
->num_draws());
728 EXPECT_FALSE(scheduler_
->RedrawPending());
729 EXPECT_TRUE(client
->needs_begin_frames());
731 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
733 EXPECT_SCOPED(AdvanceFrame());
734 task_runner().RunPendingTasks(); // Run posted deadline.
735 EXPECT_EQ(2, client
->num_draws());
736 EXPECT_FALSE(scheduler_
->RedrawPending());
737 EXPECT_FALSE(client
->needs_begin_frames());
740 // Test that requesting redraw inside a failed draw doesn't lose the request.
741 TEST_F(SchedulerTest
, RequestRedrawInsideFailedDraw
) {
742 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
743 new SchedulerClientThatsetNeedsDrawInsideDraw
;
744 scheduler_settings_
.use_external_begin_frame_source
= true;
745 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
747 client
->SetRequestRedrawsInsideDraw(true);
748 client
->SetDrawWillHappen(false);
750 scheduler_
->SetNeedsRedraw();
751 EXPECT_TRUE(scheduler_
->RedrawPending());
752 EXPECT_TRUE(client
->needs_begin_frames());
753 EXPECT_EQ(0, client
->num_draws());
756 EXPECT_SCOPED(AdvanceFrame());
757 task_runner().RunPendingTasks(); // Run posted deadline.
758 EXPECT_EQ(1, client
->num_draws());
760 // We have a commit pending and the draw failed, and we didn't lose the redraw
762 EXPECT_TRUE(scheduler_
->CommitPending());
763 EXPECT_TRUE(scheduler_
->RedrawPending());
764 EXPECT_TRUE(client
->needs_begin_frames());
766 client
->SetRequestRedrawsInsideDraw(false);
768 // Fail the draw again.
769 EXPECT_SCOPED(AdvanceFrame());
770 task_runner().RunPendingTasks(); // Run posted deadline.
771 EXPECT_EQ(2, client
->num_draws());
772 EXPECT_TRUE(scheduler_
->CommitPending());
773 EXPECT_TRUE(scheduler_
->RedrawPending());
774 EXPECT_TRUE(client
->needs_begin_frames());
776 // Draw successfully.
777 client
->SetDrawWillHappen(true);
778 EXPECT_SCOPED(AdvanceFrame());
779 task_runner().RunPendingTasks(); // Run posted deadline.
780 EXPECT_EQ(3, client
->num_draws());
781 EXPECT_TRUE(scheduler_
->CommitPending());
782 EXPECT_FALSE(scheduler_
->RedrawPending());
783 EXPECT_TRUE(client
->needs_begin_frames());
786 class SchedulerClientThatSetNeedsCommitInsideDraw
: public FakeSchedulerClient
{
788 SchedulerClientThatSetNeedsCommitInsideDraw()
789 : set_needs_commit_on_next_draw_(false) {}
791 void ScheduledActionSendBeginMainFrame() override
{}
792 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
793 // Only SetNeedsCommit the first time this is called
794 if (set_needs_commit_on_next_draw_
) {
795 scheduler_
->SetNeedsCommit();
796 set_needs_commit_on_next_draw_
= false;
798 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
801 DrawResult
ScheduledActionDrawAndSwapForced() override
{
806 void ScheduledActionCommit() override
{}
807 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{}
809 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_
= true; }
812 bool set_needs_commit_on_next_draw_
;
815 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
816 // happen inside a ScheduledActionDrawAndSwap
817 TEST_F(SchedulerTest
, RequestCommitInsideDraw
) {
818 SchedulerClientThatSetNeedsCommitInsideDraw
* client
=
819 new SchedulerClientThatSetNeedsCommitInsideDraw
;
821 scheduler_settings_
.use_external_begin_frame_source
= true;
822 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
824 EXPECT_FALSE(client
->needs_begin_frames());
825 scheduler_
->SetNeedsRedraw();
826 EXPECT_TRUE(scheduler_
->RedrawPending());
827 EXPECT_EQ(0, client
->num_draws());
828 EXPECT_TRUE(client
->needs_begin_frames());
830 client
->SetNeedsCommitOnNextDraw();
831 EXPECT_SCOPED(AdvanceFrame());
832 client
->SetNeedsCommitOnNextDraw();
833 task_runner().RunPendingTasks(); // Run posted deadline.
834 EXPECT_EQ(1, client
->num_draws());
835 EXPECT_TRUE(scheduler_
->CommitPending());
836 EXPECT_TRUE(client
->needs_begin_frames());
837 scheduler_
->NotifyBeginMainFrameStarted();
838 scheduler_
->NotifyReadyToCommit();
840 EXPECT_SCOPED(AdvanceFrame());
841 task_runner().RunPendingTasks(); // Run posted deadline.
842 EXPECT_EQ(2, client
->num_draws());
844 EXPECT_FALSE(scheduler_
->RedrawPending());
845 EXPECT_FALSE(scheduler_
->CommitPending());
846 EXPECT_TRUE(client
->needs_begin_frames());
848 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
850 EXPECT_SCOPED(AdvanceFrame());
851 task_runner().RunPendingTasks(); // Run posted deadline.
852 EXPECT_EQ(2, client
->num_draws());
853 EXPECT_FALSE(scheduler_
->RedrawPending());
854 EXPECT_FALSE(scheduler_
->CommitPending());
855 EXPECT_FALSE(client
->needs_begin_frames());
858 // Tests that when a draw fails then the pending commit should not be dropped.
859 TEST_F(SchedulerTest
, RequestCommitInsideFailedDraw
) {
860 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
861 new SchedulerClientThatsetNeedsDrawInsideDraw
;
862 scheduler_settings_
.use_external_begin_frame_source
= true;
863 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
865 client
->SetDrawWillHappen(false);
867 scheduler_
->SetNeedsRedraw();
868 EXPECT_TRUE(scheduler_
->RedrawPending());
869 EXPECT_TRUE(client
->needs_begin_frames());
870 EXPECT_EQ(0, client
->num_draws());
873 EXPECT_SCOPED(AdvanceFrame());
874 task_runner().RunPendingTasks(); // Run posted deadline.
875 EXPECT_EQ(1, client
->num_draws());
877 // We have a commit pending and the draw failed, and we didn't lose the commit
879 EXPECT_TRUE(scheduler_
->CommitPending());
880 EXPECT_TRUE(scheduler_
->RedrawPending());
881 EXPECT_TRUE(client
->needs_begin_frames());
883 // Fail the draw again.
884 EXPECT_SCOPED(AdvanceFrame());
886 task_runner().RunPendingTasks(); // Run posted deadline.
887 EXPECT_EQ(2, client
->num_draws());
888 EXPECT_TRUE(scheduler_
->CommitPending());
889 EXPECT_TRUE(scheduler_
->RedrawPending());
890 EXPECT_TRUE(client
->needs_begin_frames());
892 // Draw successfully.
893 client
->SetDrawWillHappen(true);
894 EXPECT_SCOPED(AdvanceFrame());
895 task_runner().RunPendingTasks(); // Run posted deadline.
896 EXPECT_EQ(3, client
->num_draws());
897 EXPECT_TRUE(scheduler_
->CommitPending());
898 EXPECT_FALSE(scheduler_
->RedrawPending());
899 EXPECT_TRUE(client
->needs_begin_frames());
902 TEST_F(SchedulerTest
, NoSwapWhenDrawFails
) {
903 SchedulerClientThatSetNeedsCommitInsideDraw
* client
=
904 new SchedulerClientThatSetNeedsCommitInsideDraw
;
905 scheduler_settings_
.use_external_begin_frame_source
= true;
906 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
908 scheduler_
->SetNeedsRedraw();
909 EXPECT_TRUE(scheduler_
->RedrawPending());
910 EXPECT_TRUE(client
->needs_begin_frames());
911 EXPECT_EQ(0, client
->num_draws());
913 // Draw successfully, this starts a new frame.
914 client
->SetNeedsCommitOnNextDraw();
915 EXPECT_SCOPED(AdvanceFrame());
916 task_runner().RunPendingTasks(); // Run posted deadline.
917 EXPECT_EQ(1, client
->num_draws());
919 scheduler_
->SetNeedsRedraw();
920 EXPECT_TRUE(scheduler_
->RedrawPending());
921 EXPECT_TRUE(client
->needs_begin_frames());
923 // Fail to draw, this should not start a frame.
924 client
->SetDrawWillHappen(false);
925 client
->SetNeedsCommitOnNextDraw();
926 EXPECT_SCOPED(AdvanceFrame());
927 task_runner().RunPendingTasks(); // Run posted deadline.
928 EXPECT_EQ(2, client
->num_draws());
931 class SchedulerClientNeedsPrepareTilesInDraw
: public FakeSchedulerClient
{
933 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
934 scheduler_
->SetNeedsPrepareTiles();
935 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
939 // Test prepare tiles is independant of draws.
940 TEST_F(SchedulerTest
, PrepareTiles
) {
941 SchedulerClientNeedsPrepareTilesInDraw
* client
=
942 new SchedulerClientNeedsPrepareTilesInDraw
;
943 scheduler_settings_
.use_external_begin_frame_source
= true;
944 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
946 // Request both draw and prepare tiles. PrepareTiles shouldn't
947 // be trigged until BeginImplFrame.
949 scheduler_
->SetNeedsPrepareTiles();
950 scheduler_
->SetNeedsRedraw();
951 EXPECT_TRUE(scheduler_
->RedrawPending());
952 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
953 EXPECT_TRUE(client
->needs_begin_frames());
954 EXPECT_EQ(0, client
->num_draws());
955 EXPECT_FALSE(client
->HasAction("ScheduledActionPrepareTiles"));
956 EXPECT_FALSE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
958 // We have no immediate actions to perform, so the BeginImplFrame should post
959 // the deadline task.
961 EXPECT_SCOPED(AdvanceFrame());
962 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
963 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
964 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
966 // On the deadline, he actions should have occured in the right order.
968 task_runner().RunPendingTasks(); // Run posted deadline.
969 EXPECT_EQ(1, client
->num_draws());
970 EXPECT_TRUE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
971 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
972 EXPECT_LT(client
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
973 client
->ActionIndex("ScheduledActionPrepareTiles"));
974 EXPECT_FALSE(scheduler_
->RedrawPending());
975 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
976 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
978 // Request a draw. We don't need a PrepareTiles yet.
980 scheduler_
->SetNeedsRedraw();
981 EXPECT_TRUE(scheduler_
->RedrawPending());
982 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
983 EXPECT_TRUE(client
->needs_begin_frames());
984 EXPECT_EQ(0, client
->num_draws());
986 // We have no immediate actions to perform, so the BeginImplFrame should post
987 // the deadline task.
989 EXPECT_SCOPED(AdvanceFrame());
990 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
991 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
992 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
994 // Draw. The draw will trigger SetNeedsPrepareTiles, and
995 // then the PrepareTiles action will be triggered after the Draw.
996 // Afterwards, neither a draw nor PrepareTiles are pending.
998 task_runner().RunPendingTasks(); // Run posted deadline.
999 EXPECT_EQ(1, client
->num_draws());
1000 EXPECT_TRUE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1001 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
1002 EXPECT_LT(client
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1003 client
->ActionIndex("ScheduledActionPrepareTiles"));
1004 EXPECT_FALSE(scheduler_
->RedrawPending());
1005 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1006 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1008 // We need a BeginImplFrame where we don't swap to go idle.
1010 EXPECT_SCOPED(AdvanceFrame());
1011 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
1012 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1014 task_runner().RunPendingTasks(); // Run posted deadline.
1015 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
1016 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
1017 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1018 EXPECT_EQ(0, client
->num_draws());
1020 // Now trigger a PrepareTiles outside of a draw. We will then need
1021 // a begin-frame for the PrepareTiles, but we don't need a draw.
1023 EXPECT_FALSE(client
->needs_begin_frames());
1024 scheduler_
->SetNeedsPrepareTiles();
1025 EXPECT_TRUE(client
->needs_begin_frames());
1026 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1027 EXPECT_FALSE(scheduler_
->RedrawPending());
1029 // BeginImplFrame. There will be no draw, only PrepareTiles.
1031 EXPECT_SCOPED(AdvanceFrame());
1032 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
1033 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1035 task_runner().RunPendingTasks(); // Run posted deadline.
1036 EXPECT_EQ(0, client
->num_draws());
1037 EXPECT_FALSE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1038 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
1039 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1042 // Test that PrepareTiles only happens once per frame. If an external caller
1043 // initiates it, then the state machine should not PrepareTiles on that frame.
1044 TEST_F(SchedulerTest
, PrepareTilesOncePerFrame
) {
1045 scheduler_settings_
.use_external_begin_frame_source
= true;
1046 SetUpScheduler(true);
1048 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
1050 scheduler_
->SetNeedsPrepareTiles();
1051 scheduler_
->SetNeedsRedraw();
1053 EXPECT_SCOPED(AdvanceFrame());
1054 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1055 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1056 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1058 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1059 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1060 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1063 task_runner().RunPendingTasks(); // Run posted deadline.
1064 EXPECT_EQ(1, client_
->num_draws());
1065 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1066 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1067 EXPECT_FALSE(scheduler_
->RedrawPending());
1068 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1069 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1071 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1072 scheduler_
->SetNeedsPrepareTiles();
1073 scheduler_
->SetNeedsRedraw();
1075 EXPECT_SCOPED(AdvanceFrame());
1076 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1077 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1078 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1081 task_runner().RunPendingTasks(); // Run posted deadline.
1082 EXPECT_EQ(1, client_
->num_draws());
1083 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1084 EXPECT_TRUE(client_
->HasAction("ScheduledActionPrepareTiles"));
1085 EXPECT_LT(client_
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1086 client_
->ActionIndex("ScheduledActionPrepareTiles"));
1087 EXPECT_FALSE(scheduler_
->RedrawPending());
1088 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1089 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1090 scheduler_
->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1092 // If we get another DidPrepareTiles within the same frame, we should
1093 // not PrepareTiles on the next frame.
1094 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1095 scheduler_
->SetNeedsPrepareTiles();
1096 scheduler_
->SetNeedsRedraw();
1098 EXPECT_SCOPED(AdvanceFrame());
1099 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1100 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1101 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1103 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1106 task_runner().RunPendingTasks(); // Run posted deadline.
1107 EXPECT_EQ(1, client_
->num_draws());
1108 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1109 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1110 EXPECT_FALSE(scheduler_
->RedrawPending());
1111 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1113 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1114 // frame. This verifies we don't alternate calling PrepareTiles once and
1116 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1117 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1118 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1119 scheduler_
->SetNeedsPrepareTiles();
1120 scheduler_
->SetNeedsRedraw();
1122 EXPECT_SCOPED(AdvanceFrame());
1123 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1124 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1125 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1127 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1130 task_runner().RunPendingTasks(); // Run posted deadline.
1131 EXPECT_EQ(1, client_
->num_draws());
1132 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1133 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1134 EXPECT_FALSE(scheduler_
->RedrawPending());
1135 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1137 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1138 scheduler_
->SetNeedsPrepareTiles();
1139 scheduler_
->SetNeedsRedraw();
1141 EXPECT_SCOPED(AdvanceFrame());
1142 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1143 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1144 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1147 task_runner().RunPendingTasks(); // Run posted deadline.
1148 EXPECT_EQ(1, client_
->num_draws());
1149 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1150 EXPECT_TRUE(client_
->HasAction("ScheduledActionPrepareTiles"));
1151 EXPECT_LT(client_
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1152 client_
->ActionIndex("ScheduledActionPrepareTiles"));
1153 EXPECT_FALSE(scheduler_
->RedrawPending());
1154 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1155 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1156 scheduler_
->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1159 TEST_F(SchedulerTest
, TriggerBeginFrameDeadlineEarly
) {
1160 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1161 new SchedulerClientNeedsPrepareTilesInDraw
;
1162 scheduler_settings_
.use_external_begin_frame_source
= true;
1163 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1165 scheduler_
->SetNeedsRedraw();
1166 EXPECT_SCOPED(AdvanceFrame());
1168 // The deadline should be zero since there is no work other than drawing
1170 EXPECT_EQ(base::TimeTicks(), client
->posted_begin_impl_frame_deadline());
1173 TEST_F(SchedulerTest
, WaitForReadyToDrawDoNotPostDeadline
) {
1174 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1175 new SchedulerClientNeedsPrepareTilesInDraw
;
1176 scheduler_settings_
.use_external_begin_frame_source
= true;
1177 scheduler_settings_
.impl_side_painting
= true;
1178 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1180 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1181 scheduler_
->SetNeedsCommit();
1182 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1186 EXPECT_SCOPED(AdvanceFrame());
1187 scheduler_
->NotifyBeginMainFrameStarted();
1188 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1189 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1192 scheduler_
->NotifyReadyToCommit();
1193 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1196 scheduler_
->NotifyReadyToActivate();
1197 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
1199 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1201 scheduler_
->SetWaitForReadyToDraw();
1203 task_runner().RunPendingTasks(); // Try to run posted deadline.
1204 // There is no posted deadline.
1205 EXPECT_NO_ACTION(client_
);
1207 // Scheduler received ready to draw signal, and posted deadline.
1208 scheduler_
->NotifyReadyToDraw();
1210 task_runner().RunPendingTasks(); // Run posted deadline.
1211 EXPECT_EQ(1, client_
->num_draws());
1212 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1215 TEST_F(SchedulerTest
, WaitForReadyToDrawCancelledWhenLostOutputSurface
) {
1216 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1217 new SchedulerClientNeedsPrepareTilesInDraw
;
1218 scheduler_settings_
.use_external_begin_frame_source
= true;
1219 scheduler_settings_
.impl_side_painting
= true;
1220 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1222 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1223 scheduler_
->SetNeedsCommit();
1224 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1228 EXPECT_SCOPED(AdvanceFrame());
1229 scheduler_
->NotifyBeginMainFrameStarted();
1230 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1231 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1234 scheduler_
->NotifyReadyToCommit();
1235 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1238 scheduler_
->NotifyReadyToActivate();
1239 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
1241 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1243 scheduler_
->SetWaitForReadyToDraw();
1245 task_runner().RunPendingTasks(); // Try to run posted deadline.
1246 // There is no posted deadline.
1247 EXPECT_NO_ACTION(client_
);
1249 // Scheduler loses output surface, and stops waiting for ready to draw signal.
1251 scheduler_
->DidLoseOutputSurface();
1252 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1253 task_runner().RunPendingTasks(); // Run posted deadline.
1254 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
1255 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
1256 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
1259 class SchedulerClientWithFixedEstimates
: public FakeSchedulerClient
{
1261 SchedulerClientWithFixedEstimates(
1262 base::TimeDelta draw_duration
,
1263 base::TimeDelta begin_main_frame_to_commit_duration
,
1264 base::TimeDelta commit_to_activate_duration
)
1265 : draw_duration_(draw_duration
),
1266 begin_main_frame_to_commit_duration_(
1267 begin_main_frame_to_commit_duration
),
1268 commit_to_activate_duration_(commit_to_activate_duration
) {}
1270 base::TimeDelta
DrawDurationEstimate() override
{ return draw_duration_
; }
1271 base::TimeDelta
BeginMainFrameToCommitDurationEstimate() override
{
1272 return begin_main_frame_to_commit_duration_
;
1274 base::TimeDelta
CommitToActivateDurationEstimate() override
{
1275 return commit_to_activate_duration_
;
1279 base::TimeDelta draw_duration_
;
1280 base::TimeDelta begin_main_frame_to_commit_duration_
;
1281 base::TimeDelta commit_to_activate_duration_
;
1284 void SchedulerTest::MainFrameInHighLatencyMode(
1285 int64 begin_main_frame_to_commit_estimate_in_ms
,
1286 int64 commit_to_activate_estimate_in_ms
,
1287 bool impl_latency_takes_priority
,
1288 bool should_send_begin_main_frame
) {
1289 // Set up client with specified estimates (draw duration is set to 1).
1290 SchedulerClientWithFixedEstimates
* client
=
1291 new SchedulerClientWithFixedEstimates(
1292 base::TimeDelta::FromMilliseconds(1),
1293 base::TimeDelta::FromMilliseconds(
1294 begin_main_frame_to_commit_estimate_in_ms
),
1295 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms
));
1297 scheduler_settings_
.use_external_begin_frame_source
= true;
1298 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1300 scheduler_
->SetImplLatencyTakesPriority(impl_latency_takes_priority
);
1302 // Impl thread hits deadline before commit finishes.
1303 scheduler_
->SetNeedsCommit();
1304 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1305 EXPECT_SCOPED(AdvanceFrame());
1306 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1307 task_runner().RunPendingTasks(); // Run posted deadline.
1308 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1309 scheduler_
->NotifyBeginMainFrameStarted();
1310 scheduler_
->NotifyReadyToCommit();
1311 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1312 EXPECT_TRUE(client
->HasAction("ScheduledActionSendBeginMainFrame"));
1315 scheduler_
->SetNeedsCommit();
1316 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1317 EXPECT_SCOPED(AdvanceFrame());
1318 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1319 task_runner().RunPendingTasks(); // Run posted deadline.
1320 EXPECT_EQ(scheduler_
->MainThreadIsInHighLatencyMode(),
1321 should_send_begin_main_frame
);
1322 EXPECT_EQ(client
->HasAction("ScheduledActionSendBeginMainFrame"),
1323 should_send_begin_main_frame
);
1326 TEST_F(SchedulerTest
,
1327 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline
) {
1328 // Set up client so that estimates indicate that we can commit and activate
1329 // before the deadline (~8ms by default).
1330 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, false, false));
1333 TEST_F(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong
) {
1334 // Set up client so that estimates indicate that the commit cannot finish
1335 // before the deadline (~8ms by default).
1336 EXPECT_SCOPED(MainFrameInHighLatencyMode(10, 1, false, true));
1339 TEST_F(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong
) {
1340 // Set up client so that estimates indicate that the activate cannot finish
1341 // before the deadline (~8ms by default).
1342 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true));
1345 TEST_F(SchedulerTest
, NotSkipMainFrameInPreferImplLatencyMode
) {
1346 // Set up client so that estimates indicate that we can commit and activate
1347 // before the deadline (~8ms by default), but also enable impl latency takes
1349 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true));
1352 TEST_F(SchedulerTest
, PollForCommitCompletion
) {
1353 // Since we are simulating a long commit, set up a client with draw duration
1354 // estimates that prevent skipping main frames to get to low latency mode.
1355 SchedulerClientWithFixedEstimates
* client
=
1356 new SchedulerClientWithFixedEstimates(
1357 base::TimeDelta::FromMilliseconds(1),
1358 base::TimeDelta::FromMilliseconds(32),
1359 base::TimeDelta::FromMilliseconds(32));
1360 scheduler_settings_
.use_external_begin_frame_source
= true;
1361 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1363 client
->set_log_anticipated_draw_time_change(true);
1365 BeginFrameArgs frame_args
=
1366 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1367 frame_args
.interval
= base::TimeDelta::FromMilliseconds(1000);
1369 // At this point, we've drawn a frame. Start another commit, but hold off on
1370 // the NotifyReadyToCommit for now.
1371 EXPECT_FALSE(scheduler_
->CommitPending());
1372 scheduler_
->SetNeedsCommit();
1373 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args
);
1374 EXPECT_TRUE(scheduler_
->CommitPending());
1376 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1377 // blocking on the renderer.
1378 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1379 task_runner().RunPendingTasks(); // Run posted deadline.
1380 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1381 scheduler_
->DidSwapBuffers();
1383 // Spin the event loop a few times and make sure we get more
1384 // DidAnticipateDrawTimeChange calls every time.
1385 int actions_so_far
= client
->num_actions_();
1387 // Does three iterations to make sure that the timer is properly repeating.
1388 for (int i
= 0; i
< 3; ++i
) {
1389 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1390 task_runner().DelayToNextTaskTime().InMicroseconds())
1391 << scheduler_
->AsValue()->ToString();
1392 task_runner().RunPendingTasks();
1393 EXPECT_GT(client
->num_actions_(), actions_so_far
);
1394 EXPECT_STREQ(client
->Action(client
->num_actions_() - 1),
1395 "DidAnticipatedDrawTimeChange");
1396 actions_so_far
= client
->num_actions_();
1399 // Do the same thing after BeginMainFrame starts but still before activation.
1400 scheduler_
->NotifyBeginMainFrameStarted();
1401 for (int i
= 0; i
< 3; ++i
) {
1402 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1403 task_runner().DelayToNextTaskTime().InMicroseconds())
1404 << scheduler_
->AsValue()->ToString();
1405 task_runner().RunPendingTasks();
1406 EXPECT_GT(client
->num_actions_(), actions_so_far
);
1407 EXPECT_STREQ(client
->Action(client
->num_actions_() - 1),
1408 "DidAnticipatedDrawTimeChange");
1409 actions_so_far
= client
->num_actions_();
1413 TEST_F(SchedulerTest
, BeginRetroFrame
) {
1414 scheduler_settings_
.use_external_begin_frame_source
= true;
1415 SetUpScheduler(true);
1417 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1418 scheduler_
->SetNeedsCommit();
1419 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1422 // Create a BeginFrame with a long deadline to avoid race conditions.
1423 // This is the first BeginFrame, which will be handled immediately.
1424 BeginFrameArgs args
=
1425 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1426 args
.deadline
+= base::TimeDelta::FromHours(1);
1427 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1428 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1429 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1430 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1431 EXPECT_TRUE(client_
->needs_begin_frames());
1434 // Queue BeginFrames while we are still handling the previous BeginFrame.
1435 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1436 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1437 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1438 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1440 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1441 task_runner().RunPendingTasks(); // Run posted deadline.
1442 EXPECT_NO_ACTION(client_
);
1443 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1444 EXPECT_TRUE(client_
->needs_begin_frames());
1447 // NotifyReadyToCommit should trigger the commit.
1448 scheduler_
->NotifyBeginMainFrameStarted();
1449 scheduler_
->NotifyReadyToCommit();
1450 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1451 EXPECT_TRUE(client_
->needs_begin_frames());
1454 // BeginImplFrame should prepare the draw.
1455 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1456 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1457 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1458 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1459 EXPECT_TRUE(client_
->needs_begin_frames());
1462 // BeginImplFrame deadline should draw.
1463 task_runner().RunPendingTasks(); // Run posted deadline.
1464 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
1465 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1466 EXPECT_TRUE(client_
->needs_begin_frames());
1469 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1470 // to avoid excessive toggles.
1471 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1472 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
1473 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1476 task_runner().RunPendingTasks(); // Run posted deadline.
1477 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
1478 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
1482 TEST_F(SchedulerTest
, BeginRetroFrame_SwapThrottled
) {
1483 scheduler_settings_
.use_external_begin_frame_source
= true;
1484 SetUpScheduler(true);
1486 scheduler_
->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1488 // To test swap ack throttling, this test disables automatic swap acks.
1489 scheduler_
->SetMaxSwapsPending(1);
1490 client_
->SetAutomaticSwapAck(false);
1492 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1494 scheduler_
->SetNeedsCommit();
1495 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1498 EXPECT_SCOPED(AdvanceFrame());
1499 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1500 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1501 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1502 EXPECT_TRUE(client_
->needs_begin_frames());
1505 // Queue BeginFrame while we are still handling the previous BeginFrame.
1506 SendNextBeginFrame();
1507 EXPECT_NO_ACTION(client_
);
1508 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1509 EXPECT_TRUE(client_
->needs_begin_frames());
1512 // NotifyReadyToCommit should trigger the pending commit and draw.
1513 scheduler_
->NotifyBeginMainFrameStarted();
1514 scheduler_
->NotifyReadyToCommit();
1515 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1516 EXPECT_TRUE(client_
->needs_begin_frames());
1519 // Swapping will put us into a swap throttled state.
1520 // Run posted deadline.
1521 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1522 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1523 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1524 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1525 EXPECT_TRUE(client_
->needs_begin_frames());
1528 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1529 // but not a BeginMainFrame or draw.
1530 scheduler_
->SetNeedsCommit();
1531 scheduler_
->SetNeedsRedraw();
1532 // Run posted BeginRetroFrame.
1533 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false));
1534 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1535 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1536 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1537 EXPECT_TRUE(client_
->needs_begin_frames());
1540 // Let time pass sufficiently beyond the regular deadline but not beyond the
1542 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1543 base::TimeDelta::FromMicroseconds(1));
1544 task_runner().RunUntilTime(now_src()->Now());
1545 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1547 // Take us out of a swap throttled state.
1548 scheduler_
->DidSwapBuffersComplete();
1549 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_
);
1550 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1551 EXPECT_TRUE(client_
->needs_begin_frames());
1554 // Verify that the deadline was rescheduled.
1555 task_runner().RunUntilTime(now_src()->Now());
1556 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
1557 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1558 EXPECT_TRUE(client_
->needs_begin_frames());
1562 TEST_F(SchedulerTest
, RetroFrameDoesNotExpireTooEarly
) {
1563 scheduler_settings_
.use_external_begin_frame_source
= true;
1564 SetUpScheduler(true);
1566 scheduler_
->SetNeedsCommit();
1567 EXPECT_TRUE(client_
->needs_begin_frames());
1568 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1571 EXPECT_SCOPED(AdvanceFrame());
1572 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1573 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1574 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1577 scheduler_
->NotifyBeginMainFrameStarted();
1580 SendNextBeginFrame();
1581 // This BeginFrame is queued up as a retro frame.
1582 EXPECT_NO_ACTION(client_
);
1583 // The previous deadline is still pending.
1584 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1587 // This commit should schedule the (previous) deadline to trigger immediately.
1588 scheduler_
->NotifyReadyToCommit();
1589 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1592 // The deadline task should trigger causing a draw.
1593 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1594 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1595 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1596 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1600 scheduler_
->SetNeedsAnimate();
1601 scheduler_
->SetNeedsRedraw();
1602 EXPECT_NO_ACTION(client_
);
1604 // Let's advance sufficiently past the next frame's deadline.
1605 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1606 BeginFrameArgs::DefaultEstimatedParentDrawTime() +
1607 base::TimeDelta::FromMicroseconds(1));
1609 // The retro frame hasn't expired yet.
1610 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false));
1611 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1612 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1613 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1615 // This is an immediate deadline case.
1617 task_runner().RunPendingTasks();
1618 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1619 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
1622 TEST_F(SchedulerTest
, RetroFrameDoesNotExpireTooLate
) {
1623 scheduler_settings_
.use_external_begin_frame_source
= true;
1624 SetUpScheduler(true);
1626 scheduler_
->SetNeedsCommit();
1627 EXPECT_TRUE(client_
->needs_begin_frames());
1628 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1631 EXPECT_SCOPED(AdvanceFrame());
1632 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1633 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1634 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1637 scheduler_
->NotifyBeginMainFrameStarted();
1640 SendNextBeginFrame();
1641 // This BeginFrame is queued up as a retro frame.
1642 EXPECT_NO_ACTION(client_
);
1643 // The previous deadline is still pending.
1644 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1647 // This commit should schedule the (previous) deadline to trigger immediately.
1648 scheduler_
->NotifyReadyToCommit();
1649 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1652 // The deadline task should trigger causing a draw.
1653 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1654 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1655 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1656 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1660 scheduler_
->SetNeedsAnimate();
1661 scheduler_
->SetNeedsRedraw();
1662 EXPECT_NO_ACTION(client_
);
1664 // Let's advance sufficiently past the next frame's deadline.
1665 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() +
1666 base::TimeDelta::FromMicroseconds(1));
1668 // The retro frame should've expired.
1669 EXPECT_NO_ACTION(client_
);
1672 void SchedulerTest::BeginFramesNotFromClient(
1673 bool use_external_begin_frame_source
,
1674 bool throttle_frame_production
) {
1675 scheduler_settings_
.use_external_begin_frame_source
=
1676 use_external_begin_frame_source
;
1677 scheduler_settings_
.throttle_frame_production
= throttle_frame_production
;
1678 SetUpScheduler(true);
1680 // SetNeedsCommit should begin the frame on the next BeginImplFrame
1681 // without calling SetNeedsBeginFrame.
1682 scheduler_
->SetNeedsCommit();
1683 EXPECT_NO_ACTION(client_
);
1686 // When the client-driven BeginFrame are disabled, the scheduler posts it's
1687 // own BeginFrame tasks.
1688 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1689 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1690 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1691 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1694 // If we don't swap on the deadline, we wait for the next BeginFrame.
1695 task_runner().RunPendingTasks(); // Run posted deadline.
1696 EXPECT_NO_ACTION(client_
);
1697 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1700 // NotifyReadyToCommit should trigger the commit.
1701 scheduler_
->NotifyBeginMainFrameStarted();
1702 scheduler_
->NotifyReadyToCommit();
1703 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1706 // BeginImplFrame should prepare the draw.
1707 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1708 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1709 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1710 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1713 // BeginImplFrame deadline should draw.
1714 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1715 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
1716 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1719 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1720 // to avoid excessive toggles.
1721 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1722 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
1723 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1726 // Make sure SetNeedsBeginFrame isn't called on the client
1727 // when the BeginFrame is no longer needed.
1728 task_runner().RunPendingTasks(); // Run posted deadline.
1729 EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_
);
1733 TEST_F(SchedulerTest
, SyntheticBeginFrames
) {
1734 bool use_external_begin_frame_source
= false;
1735 bool throttle_frame_production
= true;
1736 BeginFramesNotFromClient(use_external_begin_frame_source
,
1737 throttle_frame_production
);
1740 TEST_F(SchedulerTest
, VSyncThrottlingDisabled
) {
1741 bool use_external_begin_frame_source
= true;
1742 bool throttle_frame_production
= false;
1743 BeginFramesNotFromClient(use_external_begin_frame_source
,
1744 throttle_frame_production
);
1747 TEST_F(SchedulerTest
, SyntheticBeginFrames_And_VSyncThrottlingDisabled
) {
1748 bool use_external_begin_frame_source
= false;
1749 bool throttle_frame_production
= false;
1750 BeginFramesNotFromClient(use_external_begin_frame_source
,
1751 throttle_frame_production
);
1754 void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
1755 bool use_external_begin_frame_source
,
1756 bool throttle_frame_production
) {
1757 scheduler_settings_
.use_external_begin_frame_source
=
1758 use_external_begin_frame_source
;
1759 scheduler_settings_
.throttle_frame_production
= throttle_frame_production
;
1760 SetUpScheduler(true);
1762 scheduler_
->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1764 // To test swap ack throttling, this test disables automatic swap acks.
1765 scheduler_
->SetMaxSwapsPending(1);
1766 client_
->SetAutomaticSwapAck(false);
1768 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1770 scheduler_
->SetNeedsCommit();
1771 EXPECT_NO_ACTION(client_
);
1774 // Trigger the first BeginImplFrame and BeginMainFrame
1775 EXPECT_SCOPED(AdvanceFrame());
1776 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1777 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1778 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1781 // NotifyReadyToCommit should trigger the pending commit and draw.
1782 scheduler_
->NotifyBeginMainFrameStarted();
1783 scheduler_
->NotifyReadyToCommit();
1784 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1787 // Swapping will put us into a swap throttled state.
1788 // Run posted deadline.
1789 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1790 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1791 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1792 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1795 // While swap throttled, BeginFrames should trigger BeginImplFrames,
1796 // but not a BeginMainFrame or draw.
1797 scheduler_
->SetNeedsCommit();
1798 scheduler_
->SetNeedsRedraw();
1799 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
1800 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1801 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1802 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1805 // Let time pass sufficiently beyond the regular deadline but not beyond the
1807 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1808 base::TimeDelta::FromMicroseconds(1));
1809 task_runner().RunUntilTime(now_src()->Now());
1810 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1812 // Take us out of a swap throttled state.
1813 scheduler_
->DidSwapBuffersComplete();
1814 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_
);
1815 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1818 // Verify that the deadline was rescheduled.
1819 // We can't use RunUntilTime(now) here because the next frame is also
1820 // scheduled if throttle_frame_production = false.
1821 base::TimeTicks before_deadline
= now_src()->Now();
1822 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1823 base::TimeTicks after_deadline
= now_src()->Now();
1824 EXPECT_EQ(after_deadline
, before_deadline
);
1825 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1829 TEST_F(SchedulerTest
, SyntheticBeginFrames_SwapThrottled
) {
1830 bool use_external_begin_frame_source
= false;
1831 bool throttle_frame_production
= true;
1832 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1833 throttle_frame_production
);
1836 TEST_F(SchedulerTest
, VSyncThrottlingDisabled_SwapThrottled
) {
1837 bool use_external_begin_frame_source
= true;
1838 bool throttle_frame_production
= false;
1839 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1840 throttle_frame_production
);
1843 TEST_F(SchedulerTest
,
1844 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled
) {
1845 bool use_external_begin_frame_source
= false;
1846 bool throttle_frame_production
= false;
1847 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1848 throttle_frame_production
);
1851 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized
) {
1852 scheduler_settings_
.use_external_begin_frame_source
= true;
1853 SetUpScheduler(false);
1855 scheduler_
->SetCanStart();
1856 scheduler_
->SetVisible(true);
1857 scheduler_
->SetCanDraw(true);
1859 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
1861 scheduler_
->DidCreateAndInitializeOutputSurface();
1862 EXPECT_NO_ACTION(client_
);
1864 scheduler_
->DidLoseOutputSurface();
1865 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
1868 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterBeginFrameStarted
) {
1869 scheduler_settings_
.use_external_begin_frame_source
= true;
1870 SetUpScheduler(true);
1872 // SetNeedsCommit should begin the frame.
1873 scheduler_
->SetNeedsCommit();
1874 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1877 EXPECT_SCOPED(AdvanceFrame());
1878 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1879 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1880 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1883 scheduler_
->DidLoseOutputSurface();
1884 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1885 EXPECT_NO_ACTION(client_
);
1888 scheduler_
->NotifyBeginMainFrameStarted();
1889 scheduler_
->NotifyReadyToCommit();
1890 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 1);
1893 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1894 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
1895 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
1896 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
1899 void SchedulerTest::DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
1900 bool impl_side_painting
) {
1901 scheduler_settings_
.impl_side_painting
= impl_side_painting
;
1902 scheduler_settings_
.use_external_begin_frame_source
= true;
1903 SetUpScheduler(true);
1905 // SetNeedsCommit should begin the frame.
1906 scheduler_
->SetNeedsCommit();
1907 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1910 EXPECT_SCOPED(AdvanceFrame());
1911 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1912 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1913 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1916 scheduler_
->DidLoseOutputSurface();
1917 // Do nothing when impl frame is in deadine pending state.
1918 EXPECT_NO_ACTION(client_
);
1921 // Run posted deadline.
1922 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1923 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1924 // OnBeginImplFrameDeadline didn't schedule output surface creation because
1925 // main frame is not yet completed.
1926 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
1927 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
1928 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1930 // BeginImplFrame is not started.
1932 task_runner().RunUntilTime(now_src()->Now() +
1933 base::TimeDelta::FromMilliseconds(10));
1934 EXPECT_NO_ACTION(client_
);
1935 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1938 scheduler_
->NotifyBeginMainFrameStarted();
1939 scheduler_
->NotifyReadyToCommit();
1940 if (impl_side_painting
) {
1941 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 3);
1942 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 1, 3);
1943 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 2, 3);
1945 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 2);
1946 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 1, 2);
1950 TEST_F(SchedulerTest
,
1951 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency
) {
1952 bool impl_side_painting
= false;
1953 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
1956 TEST_F(SchedulerTest
,
1957 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint
) {
1958 bool impl_side_painting
= true;
1959 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
1962 void SchedulerTest::DidLoseOutputSurfaceAfterReadyToCommit(
1963 bool impl_side_painting
) {
1964 scheduler_settings_
.impl_side_painting
= impl_side_painting
;
1965 scheduler_settings_
.use_external_begin_frame_source
= true;
1966 SetUpScheduler(true);
1968 // SetNeedsCommit should begin the frame.
1969 scheduler_
->SetNeedsCommit();
1970 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1973 EXPECT_SCOPED(AdvanceFrame());
1974 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1975 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1976 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1979 scheduler_
->NotifyBeginMainFrameStarted();
1980 scheduler_
->NotifyReadyToCommit();
1981 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1984 scheduler_
->DidLoseOutputSurface();
1985 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1986 if (impl_side_painting
) {
1987 // Sync tree should be forced to activate.
1988 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
1990 EXPECT_NO_ACTION(client_
);
1994 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1995 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
1996 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
1997 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2000 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommit
) {
2001 DidLoseOutputSurfaceAfterReadyToCommit(false);
2004 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting
) {
2005 DidLoseOutputSurfaceAfterReadyToCommit(true);
2008 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles
) {
2009 scheduler_settings_
.use_external_begin_frame_source
= true;
2010 SetUpScheduler(true);
2012 scheduler_
->SetNeedsPrepareTiles();
2013 scheduler_
->SetNeedsRedraw();
2014 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2017 EXPECT_SCOPED(AdvanceFrame());
2018 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2019 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2020 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2023 scheduler_
->DidLoseOutputSurface();
2024 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2025 EXPECT_NO_ACTION(client_
);
2028 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2029 EXPECT_ACTION("ScheduledActionPrepareTiles", client_
, 0, 4);
2030 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 1, 4);
2031 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 2, 4);
2032 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 3, 4);
2035 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterBeginRetroFramePosted
) {
2036 scheduler_settings_
.use_external_begin_frame_source
= true;
2037 SetUpScheduler(true);
2039 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2040 scheduler_
->SetNeedsCommit();
2041 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2043 // Create a BeginFrame with a long deadline to avoid race conditions.
2044 // This is the first BeginFrame, which will be handled immediately.
2046 BeginFrameArgs args
=
2047 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
2048 args
.deadline
+= base::TimeDelta::FromHours(1);
2049 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2050 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2051 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2052 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2053 EXPECT_TRUE(client_
->needs_begin_frames());
2055 // Queue BeginFrames while we are still handling the previous BeginFrame.
2056 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2057 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2058 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2059 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2061 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2063 task_runner().RunPendingTasks(); // Run posted deadline.
2064 EXPECT_NO_ACTION(client_
);
2065 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2066 EXPECT_TRUE(client_
->needs_begin_frames());
2068 // NotifyReadyToCommit should trigger the commit.
2070 scheduler_
->NotifyBeginMainFrameStarted();
2071 scheduler_
->NotifyReadyToCommit();
2072 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2073 EXPECT_TRUE(client_
->needs_begin_frames());
2076 EXPECT_FALSE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2077 scheduler_
->DidLoseOutputSurface();
2078 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2079 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2080 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2081 EXPECT_TRUE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2083 // Posted BeginRetroFrame is aborted.
2085 task_runner().RunPendingTasks();
2086 EXPECT_NO_ACTION(client_
);
2089 TEST_F(SchedulerTest
, DidLoseOutputSurfaceDuringBeginRetroFrameRunning
) {
2090 scheduler_settings_
.use_external_begin_frame_source
= true;
2091 SetUpScheduler(true);
2093 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2094 scheduler_
->SetNeedsCommit();
2095 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2097 // Create a BeginFrame with a long deadline to avoid race conditions.
2098 // This is the first BeginFrame, which will be handled immediately.
2100 BeginFrameArgs args
=
2101 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
2102 args
.deadline
+= base::TimeDelta::FromHours(1);
2103 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2104 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2105 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2106 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2107 EXPECT_TRUE(client_
->needs_begin_frames());
2109 // Queue BeginFrames while we are still handling the previous BeginFrame.
2110 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2111 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2112 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2113 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2115 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2117 task_runner().RunPendingTasks(); // Run posted deadline.
2118 EXPECT_NO_ACTION(client_
);
2119 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2120 EXPECT_TRUE(client_
->needs_begin_frames());
2122 // NotifyReadyToCommit should trigger the commit.
2124 scheduler_
->NotifyBeginMainFrameStarted();
2125 scheduler_
->NotifyReadyToCommit();
2126 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2127 EXPECT_TRUE(client_
->needs_begin_frames());
2129 // BeginImplFrame should prepare the draw.
2131 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2132 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2133 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2134 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2135 EXPECT_TRUE(client_
->needs_begin_frames());
2138 EXPECT_FALSE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2139 scheduler_
->DidLoseOutputSurface();
2140 EXPECT_NO_ACTION(client_
);
2141 EXPECT_TRUE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2143 // BeginImplFrame deadline should abort drawing.
2145 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2146 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2147 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2148 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2149 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2150 EXPECT_FALSE(client_
->needs_begin_frames());
2152 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
2154 task_runner().RunPendingTasks();
2155 EXPECT_NO_ACTION(client_
);
2158 TEST_F(SchedulerTest
, DidLoseOutputSurfaceWithSyntheticBeginFrameSource
) {
2159 SetUpScheduler(true);
2161 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2162 EXPECT_FALSE(scheduler_
->frame_source().NeedsBeginFrames());
2163 scheduler_
->SetNeedsCommit();
2164 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2168 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2169 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2170 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2171 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2173 // NotifyReadyToCommit should trigger the commit.
2175 scheduler_
->NotifyBeginMainFrameStarted();
2176 scheduler_
->NotifyReadyToCommit();
2177 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2178 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2181 scheduler_
->DidLoseOutputSurface();
2182 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2183 EXPECT_NO_ACTION(client_
);
2184 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2187 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2188 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 2);
2189 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
2190 EXPECT_FALSE(scheduler_
->frame_source().NeedsBeginFrames());
2193 TEST_F(SchedulerTest
, DidLoseOutputSurfaceWhenIdle
) {
2194 scheduler_settings_
.use_external_begin_frame_source
= true;
2195 SetUpScheduler(true);
2197 // SetNeedsCommit should begin the frame.
2198 scheduler_
->SetNeedsCommit();
2199 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2202 EXPECT_SCOPED(AdvanceFrame());
2203 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2204 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2205 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2208 scheduler_
->NotifyBeginMainFrameStarted();
2209 scheduler_
->NotifyReadyToCommit();
2210 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2213 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2214 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2215 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2217 // Idle time between BeginFrames.
2219 scheduler_
->DidLoseOutputSurface();
2220 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2221 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2222 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2225 TEST_F(SchedulerTest
, ScheduledActionActivateAfterBecomingInvisible
) {
2226 scheduler_settings_
.impl_side_painting
= true;
2227 scheduler_settings_
.use_external_begin_frame_source
= true;
2228 SetUpScheduler(true);
2230 // SetNeedsCommit should begin the frame.
2231 scheduler_
->SetNeedsCommit();
2232 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2235 EXPECT_SCOPED(AdvanceFrame());
2236 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2237 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2238 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2241 scheduler_
->NotifyBeginMainFrameStarted();
2242 scheduler_
->NotifyReadyToCommit();
2243 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2244 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2247 scheduler_
->SetVisible(false);
2248 task_runner().RunPendingTasks(); // Run posted deadline.
2250 // Sync tree should be forced to activate.
2251 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 0, 3);
2252 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2253 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2256 // Tests to ensure frame sources can be successfully changed while drawing.
2257 TEST_F(SchedulerTest
, SwitchFrameSourceToUnthrottled
) {
2258 scheduler_settings_
.use_external_begin_frame_source
= true;
2259 SetUpScheduler(true);
2261 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2262 scheduler_
->SetNeedsRedraw();
2263 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2266 EXPECT_SCOPED(AdvanceFrame());
2267 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2268 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2269 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2270 EXPECT_TRUE(client_
->needs_begin_frames());
2272 task_runner().RunPendingTasks(); // Run posted deadline.
2273 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2274 scheduler_
->SetNeedsRedraw();
2276 // Switch to an unthrottled frame source.
2277 scheduler_
->SetThrottleFrameProduction(false);
2280 // Unthrottled frame source will immediately begin a new frame.
2281 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2282 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2283 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2284 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2287 // If we don't swap on the deadline, we wait for the next BeginFrame.
2288 task_runner().RunPendingTasks(); // Run posted deadline.
2289 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2290 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2294 // Tests to ensure frame sources can be successfully changed while a frame
2295 // deadline is pending.
2296 TEST_F(SchedulerTest
, SwitchFrameSourceToUnthrottledBeforeDeadline
) {
2297 scheduler_settings_
.use_external_begin_frame_source
= true;
2298 SetUpScheduler(true);
2300 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2301 scheduler_
->SetNeedsRedraw();
2302 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2305 EXPECT_SCOPED(AdvanceFrame());
2306 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2307 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2309 // Switch to an unthrottled frame source before the frame deadline is hit.
2310 scheduler_
->SetThrottleFrameProduction(false);
2313 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2314 EXPECT_TRUE(client_
->needs_begin_frames());
2317 task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame.
2318 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 2);
2319 // Unthrottled frame source will immediately begin a new frame.
2320 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 2);
2321 scheduler_
->SetNeedsRedraw();
2324 task_runner().RunPendingTasks(); // Run posted deadline.
2325 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2326 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2327 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2331 // Tests to ensure that the active frame source can successfully be changed from
2332 // unthrottled to throttled.
2333 TEST_F(SchedulerTest
, SwitchFrameSourceToThrottled
) {
2334 scheduler_settings_
.throttle_frame_production
= false;
2335 scheduler_settings_
.use_external_begin_frame_source
= true;
2336 SetUpScheduler(true);
2338 scheduler_
->SetNeedsRedraw();
2339 EXPECT_NO_ACTION(client_
);
2342 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2343 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2344 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2345 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2348 task_runner().RunPendingTasks(); // Run posted deadline.
2349 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2350 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2353 // Switch to a throttled frame source.
2354 scheduler_
->SetThrottleFrameProduction(true);
2357 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2358 scheduler_
->SetNeedsRedraw();
2359 task_runner().RunPendingTasks();
2360 EXPECT_NO_ACTION(client_
);
2363 EXPECT_SCOPED(AdvanceFrame());
2364 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2365 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2366 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2367 EXPECT_TRUE(client_
->needs_begin_frames());
2369 task_runner().RunPendingTasks(); // Run posted deadline.
2370 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2373 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
2374 TEST_F(SchedulerTest
, SendBeginMainFrameNotExpectedSoon
) {
2375 scheduler_settings_
.use_external_begin_frame_source
= true;
2376 SetUpScheduler(true);
2378 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2379 scheduler_
->SetNeedsCommit();
2380 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2383 // Trigger a frame draw.
2384 EXPECT_SCOPED(AdvanceFrame());
2385 scheduler_
->NotifyBeginMainFrameStarted();
2386 scheduler_
->NotifyReadyToCommit();
2387 task_runner().RunPendingTasks();
2388 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 5);
2389 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 5);
2390 EXPECT_ACTION("ScheduledActionCommit", client_
, 2, 5);
2391 EXPECT_ACTION("ScheduledActionAnimate", client_
, 3, 5);
2392 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 4, 5);
2395 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2396 // and send a SendBeginMainFrameNotExpectedSoon.
2397 EXPECT_SCOPED(AdvanceFrame());
2398 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
2399 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2402 task_runner().RunPendingTasks(); // Run posted deadline.
2403 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
2404 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
2408 TEST_F(SchedulerTest
, SynchronousCompositorAnimation
) {
2409 scheduler_settings_
.using_synchronous_renderer_compositor
= true;
2410 scheduler_settings_
.use_external_begin_frame_source
= true;
2411 scheduler_settings_
.impl_side_painting
= true;
2412 SetUpScheduler(true);
2414 scheduler_
->SetNeedsAnimate();
2415 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2420 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2421 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
2422 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
2423 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2426 // Continue with animation.
2427 scheduler_
->SetNeedsAnimate();
2428 EXPECT_NO_ACTION(client_
);
2431 scheduler_
->SetNeedsRedraw();
2432 scheduler_
->OnDrawForOutputSurface();
2433 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
2434 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2439 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2440 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
2441 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
2442 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2446 scheduler_
->SetNeedsRedraw();
2447 scheduler_
->OnDrawForOutputSurface();
2448 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
2449 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2452 // Idle on next vsync.
2454 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2455 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2456 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2457 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2461 TEST_F(SchedulerTest
, SynchronousCompositorOnDrawDuringIdle
) {
2462 scheduler_settings_
.using_synchronous_renderer_compositor
= true;
2463 scheduler_settings_
.use_external_begin_frame_source
= true;
2464 scheduler_settings_
.impl_side_painting
= true;
2465 SetUpScheduler(true);
2467 scheduler_
->SetNeedsRedraw();
2468 scheduler_
->OnDrawForOutputSurface();
2469 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_
, 0, 3);
2470 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
2471 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 2, 3);
2472 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2475 // Idle on next vsync.
2477 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2478 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2479 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2480 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2484 TEST_F(SchedulerTest
, SynchronousCompositorCommit
) {
2485 scheduler_settings_
.using_synchronous_renderer_compositor
= true;
2486 scheduler_settings_
.use_external_begin_frame_source
= true;
2487 scheduler_settings_
.impl_side_painting
= true;
2488 SetUpScheduler(true);
2490 scheduler_
->SetNeedsCommit();
2491 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2496 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2497 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2498 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2501 scheduler_
->NotifyBeginMainFrameStarted();
2502 EXPECT_NO_ACTION(client_
);
2506 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
2507 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2510 scheduler_
->NotifyReadyToCommit();
2511 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2514 scheduler_
->NotifyReadyToActivate();
2515 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
2520 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2521 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
2522 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
2523 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2527 scheduler_
->SetNeedsRedraw();
2528 scheduler_
->OnDrawForOutputSurface();
2529 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
2530 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2533 // Idle on next vsync.
2535 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2536 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2537 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2538 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2542 TEST_F(SchedulerTest
, SynchronousCompositorDoubleCommitWithoutDraw
) {
2543 scheduler_settings_
.using_synchronous_renderer_compositor
= true;
2544 scheduler_settings_
.use_external_begin_frame_source
= true;
2545 scheduler_settings_
.impl_side_painting
= true;
2546 SetUpScheduler(true);
2548 scheduler_
->SetNeedsCommit();
2549 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2554 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2555 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2556 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2559 scheduler_
->NotifyBeginMainFrameStarted();
2560 EXPECT_NO_ACTION(client_
);
2562 scheduler_
->NotifyReadyToCommit();
2563 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2566 scheduler_
->NotifyReadyToActivate();
2567 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
2570 // Ask for another commit.
2571 scheduler_
->SetNeedsCommit();
2574 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 4);
2575 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 4);
2576 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 2, 4);
2577 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 3, 4);
2578 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2581 scheduler_
->NotifyBeginMainFrameStarted();
2582 EXPECT_NO_ACTION(client_
);
2584 // Allow new commit even though previous commit hasn't been drawn.
2585 scheduler_
->NotifyReadyToCommit();
2586 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2590 TEST_F(SchedulerTest
, AuthoritativeVSyncInterval
) {
2591 SetUpScheduler(true);
2593 base::TimeDelta initial_interval
=
2594 scheduler_
->begin_impl_frame_args().interval
;
2595 base::TimeDelta authoritative_interval
=
2596 base::TimeDelta::FromMilliseconds(33);
2598 scheduler_
->SetNeedsCommit();
2599 EXPECT_SCOPED(AdvanceFrame());
2601 EXPECT_EQ(initial_interval
, scheduler_
->begin_impl_frame_args().interval
);
2603 scheduler_
->NotifyBeginMainFrameStarted();
2604 scheduler_
->NotifyReadyToCommit();
2605 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2607 scheduler_
->SetAuthoritativeVSyncInterval(authoritative_interval
);
2609 EXPECT_SCOPED(AdvanceFrame());
2611 // At the next BeginFrame, authoritative interval is used instead of previous
2613 EXPECT_NE(initial_interval
, scheduler_
->begin_impl_frame_args().interval
);
2614 EXPECT_EQ(authoritative_interval
,
2615 scheduler_
->begin_impl_frame_args().interval
);