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),
59 draw_will_happen_
= true;
60 swap_will_happen_if_draw_happens_
= true;
62 log_anticipated_draw_time_change_
= false;
63 begin_frame_args_sent_to_children_
= BeginFrameArgs();
66 void set_scheduler(TestScheduler
* scheduler
) { scheduler_
= scheduler
; }
68 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
70 void set_log_anticipated_draw_time_change(bool log
) {
71 log_anticipated_draw_time_change_
= log
;
73 bool needs_begin_frames() {
74 return scheduler_
->frame_source().NeedsBeginFrames();
76 int num_draws() const { return num_draws_
; }
77 int num_actions_() const { return static_cast<int>(actions_
.size()); }
78 const char* Action(int i
) const { return actions_
[i
]; }
79 std::string
StateForAction(int i
) const { return states_
[i
]->ToString(); }
80 base::TimeTicks
posted_begin_impl_frame_deadline() const {
81 return posted_begin_impl_frame_deadline_
;
84 int ActionIndex(const char* action
) const {
85 for (size_t i
= 0; i
< actions_
.size(); i
++)
86 if (!strcmp(actions_
[i
], action
))
91 bool HasAction(const char* action
) const {
92 return ActionIndex(action
) >= 0;
95 void SetDrawWillHappen(bool draw_will_happen
) {
96 draw_will_happen_
= draw_will_happen
;
98 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens
) {
99 swap_will_happen_if_draw_happens_
= swap_will_happen_if_draw_happens
;
101 void SetAutomaticSwapAck(bool automatic_swap_ack
) {
102 automatic_swap_ack_
= automatic_swap_ack
;
104 // SchedulerClient implementation.
105 void WillBeginImplFrame(const BeginFrameArgs
& args
) override
{
106 PushAction("WillBeginImplFrame");
108 void DidFinishImplFrame() override
{}
110 void ScheduledActionSendBeginMainFrame() override
{
111 PushAction("ScheduledActionSendBeginMainFrame");
113 void ScheduledActionAnimate() override
{
114 PushAction("ScheduledActionAnimate");
116 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
117 PushAction("ScheduledActionDrawAndSwapIfPossible");
120 draw_will_happen_
? DRAW_SUCCESS
: DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
;
121 bool swap_will_happen
=
122 draw_will_happen_
&& swap_will_happen_if_draw_happens_
;
123 if (swap_will_happen
) {
124 scheduler_
->DidSwapBuffers();
126 if (automatic_swap_ack_
)
127 scheduler_
->DidSwapBuffersComplete();
131 DrawResult
ScheduledActionDrawAndSwapForced() override
{
132 PushAction("ScheduledActionDrawAndSwapForced");
135 void ScheduledActionCommit() override
{ PushAction("ScheduledActionCommit"); }
136 void ScheduledActionActivateSyncTree() override
{
137 PushAction("ScheduledActionActivateSyncTree");
139 void ScheduledActionBeginOutputSurfaceCreation() override
{
140 PushAction("ScheduledActionBeginOutputSurfaceCreation");
142 void ScheduledActionPrepareTiles() override
{
143 PushAction("ScheduledActionPrepareTiles");
145 void ScheduledActionInvalidateOutputSurface() override
{
146 actions_
.push_back("ScheduledActionInvalidateOutputSurface");
147 states_
.push_back(scheduler_
->AsValue());
149 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{
150 if (log_anticipated_draw_time_change_
)
151 PushAction("DidAnticipatedDrawTimeChange");
153 base::TimeDelta
DrawDurationEstimate() override
{ return base::TimeDelta(); }
154 base::TimeDelta
BeginMainFrameToCommitDurationEstimate() override
{
155 return base::TimeDelta();
157 base::TimeDelta
CommitToActivateDurationEstimate() override
{
158 return base::TimeDelta();
161 void SendBeginFramesToChildren(const BeginFrameArgs
& args
) override
{
162 begin_frame_args_sent_to_children_
= args
;
165 void SendBeginMainFrameNotExpectedSoon() override
{
166 PushAction("SendBeginMainFrameNotExpectedSoon");
169 base::Callback
<bool(void)> ImplFrameDeadlinePending(bool state
) {
170 return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback
,
171 base::Unretained(this),
175 bool begin_frame_is_sent_to_children() const {
176 return begin_frame_args_sent_to_children_
.IsValid();
179 const BeginFrameArgs
& begin_frame_args_sent_to_children() const {
180 return begin_frame_args_sent_to_children_
;
183 void PushAction(const char* description
) {
184 actions_
.push_back(description
);
185 states_
.push_back(scheduler_
->AsValue());
189 bool ImplFrameDeadlinePendingCallback(bool state
) {
190 return scheduler_
->BeginImplFrameDeadlinePending() == state
;
193 bool draw_will_happen_
;
194 bool swap_will_happen_if_draw_happens_
;
195 bool automatic_swap_ack_
;
197 bool log_anticipated_draw_time_change_
;
198 BeginFrameArgs begin_frame_args_sent_to_children_
;
199 base::TimeTicks posted_begin_impl_frame_deadline_
;
200 std::vector
<const char*> actions_
;
201 std::vector
<scoped_refptr
<base::trace_event::ConvertableToTraceFormat
>>
203 TestScheduler
* scheduler_
;
206 class SchedulerClientWithFixedEstimates
: public FakeSchedulerClient
{
208 SchedulerClientWithFixedEstimates(
209 base::TimeDelta draw_duration
,
210 base::TimeDelta begin_main_frame_to_commit_duration
,
211 base::TimeDelta commit_to_activate_duration
)
212 : draw_duration_(draw_duration
),
213 begin_main_frame_to_commit_duration_(
214 begin_main_frame_to_commit_duration
),
215 commit_to_activate_duration_(commit_to_activate_duration
) {}
217 base::TimeDelta
DrawDurationEstimate() override
{ return draw_duration_
; }
218 base::TimeDelta
BeginMainFrameToCommitDurationEstimate() override
{
219 return begin_main_frame_to_commit_duration_
;
221 base::TimeDelta
CommitToActivateDurationEstimate() override
{
222 return commit_to_activate_duration_
;
226 base::TimeDelta draw_duration_
;
227 base::TimeDelta begin_main_frame_to_commit_duration_
;
228 base::TimeDelta commit_to_activate_duration_
;
231 class FakeExternalBeginFrameSource
: public BeginFrameSourceMixIn
{
233 explicit FakeExternalBeginFrameSource(FakeSchedulerClient
* client
)
235 ~FakeExternalBeginFrameSource() override
{}
237 void OnNeedsBeginFramesChange(bool needs_begin_frames
) override
{
238 if (needs_begin_frames
) {
239 client_
->PushAction("SetNeedsBeginFrames(true)");
241 client_
->PushAction("SetNeedsBeginFrames(false)");
245 void TestOnBeginFrame(const BeginFrameArgs
& args
) {
246 return CallOnBeginFrame(args
);
250 FakeSchedulerClient
* client_
;
253 class SchedulerTest
: public testing::Test
{
256 : now_src_(TestNowSource::Create()),
257 task_runner_(new OrderedSimpleTaskRunner(now_src_
, true)),
258 fake_external_begin_frame_source_(nullptr) {
259 // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval()
260 now_src_
->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
261 // Fail if we need to run 100 tasks in a row.
262 task_runner_
->SetRunTaskLimit(100);
265 ~SchedulerTest() override
{}
268 TestScheduler
* CreateScheduler() {
269 scoped_ptr
<FakeExternalBeginFrameSource
> fake_external_begin_frame_source
;
270 if (scheduler_settings_
.use_external_begin_frame_source
) {
271 fake_external_begin_frame_source
.reset(
272 new FakeExternalBeginFrameSource(client_
.get()));
273 fake_external_begin_frame_source_
=
274 fake_external_begin_frame_source
.get();
276 scheduler_
= TestScheduler::Create(now_src_
, client_
.get(),
277 scheduler_settings_
, 0, task_runner_
,
278 fake_external_begin_frame_source
.Pass());
280 client_
->set_scheduler(scheduler_
.get());
281 return scheduler_
.get();
284 void CreateSchedulerAndInitSurface() {
286 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit());
289 void SetUpScheduler(bool initSurface
) {
290 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient
), initSurface
);
293 void SetUpScheduler(scoped_ptr
<FakeSchedulerClient
> client
,
295 client_
= client
.Pass();
297 CreateSchedulerAndInitSurface();
302 OrderedSimpleTaskRunner
& task_runner() { return *task_runner_
; }
303 TestNowSource
* now_src() { return now_src_
.get(); }
305 // As this function contains EXPECT macros, to allow debugging it should be
306 // called inside EXPECT_SCOPED like so;
307 // EXPECT_SCOPED(client.InitializeOutputSurfaceAndFirstCommit(scheduler));
308 void InitializeOutputSurfaceAndFirstCommit() {
310 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit");
313 // Check the client doesn't have any actions queued when calling this
315 EXPECT_NO_ACTION(client_
);
316 EXPECT_FALSE(client_
->needs_begin_frames());
318 // Start the initial output surface creation.
319 EXPECT_FALSE(scheduler_
->CanStart());
320 scheduler_
->SetCanStart();
321 scheduler_
->SetVisible(true);
322 scheduler_
->SetCanDraw(true);
323 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
327 // We don't see anything happening until the first impl frame.
328 scheduler_
->DidCreateAndInitializeOutputSurface();
329 scheduler_
->SetNeedsCommit();
330 EXPECT_TRUE(client_
->needs_begin_frames());
331 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
335 SCOPED_TRACE("Do first frame to commit after initialize.");
338 scheduler_
->NotifyBeginMainFrameStarted();
339 scheduler_
->NotifyReadyToCommitThenActivateIfNeeded();
341 EXPECT_FALSE(scheduler_
->CommitPending());
343 if (scheduler_settings_
.using_synchronous_renderer_compositor
) {
344 scheduler_
->SetNeedsRedraw();
345 scheduler_
->OnDrawForOutputSurface();
347 // Run the posted deadline task.
348 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
349 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
352 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
359 "Run second frame so Scheduler calls SetNeedsBeginFrame(false).");
362 if (!scheduler_settings_
.using_synchronous_renderer_compositor
) {
363 // Run the posted deadline task.
364 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
365 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
368 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
371 EXPECT_FALSE(client_
->needs_begin_frames());
375 // As this function contains EXPECT macros, to allow debugging it should be
376 // called inside EXPECT_SCOPED like so;
377 // EXPECT_SCOPED(client.AdvanceFrame());
378 void AdvanceFrame() {
379 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
380 "FakeSchedulerClient::AdvanceFrame");
381 // Consume any previous deadline first, if no deadline is currently
382 // pending, ImplFrameDeadlinePending will return false straight away and we
383 // will run no tasks.
384 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
385 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
387 // Send the next BeginFrame message if using an external source, otherwise
388 // it will be already in the task queue.
389 if (scheduler_
->settings().use_external_begin_frame_source
&&
390 scheduler_
->FrameProductionThrottled()) {
391 EXPECT_TRUE(client_
->needs_begin_frames());
392 SendNextBeginFrame();
395 if (!scheduler_
->settings().using_synchronous_renderer_compositor
) {
396 // Then run tasks until new deadline is scheduled.
397 EXPECT_TRUE(task_runner_
->RunTasksWhile(
398 client_
->ImplFrameDeadlinePending(false)));
399 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
403 BeginFrameArgs
SendNextBeginFrame() {
404 DCHECK(scheduler_
->settings().use_external_begin_frame_source
);
405 // Creep the time forward so that any BeginFrameArgs is not equal to the
406 // last one otherwise we violate the BeginFrameSource contract.
407 now_src_
->AdvanceNow(BeginFrameArgs::DefaultInterval());
408 BeginFrameArgs args
=
409 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
410 fake_external_begin_frame_source_
->TestOnBeginFrame(args
);
414 FakeExternalBeginFrameSource
* fake_external_begin_frame_source() const {
415 return fake_external_begin_frame_source_
;
418 void MainFrameInHighLatencyMode(
419 int64 begin_main_frame_to_commit_estimate_in_ms
,
420 int64 commit_to_activate_estimate_in_ms
,
421 bool impl_latency_takes_priority
,
422 bool should_send_begin_main_frame
);
423 void BeginFramesNotFromClient(bool use_external_begin_frame_source
,
424 bool throttle_frame_production
);
425 void BeginFramesNotFromClient_SwapThrottled(
426 bool use_external_begin_frame_source
,
427 bool throttle_frame_production
);
428 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
429 bool impl_side_painting
);
430 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting
);
432 scoped_refptr
<TestNowSource
> now_src_
;
433 scoped_refptr
<OrderedSimpleTaskRunner
> task_runner_
;
434 FakeExternalBeginFrameSource
* fake_external_begin_frame_source_
;
435 SchedulerSettings scheduler_settings_
;
436 scoped_ptr
<FakeSchedulerClient
> client_
;
437 scoped_ptr
<TestScheduler
> scheduler_
;
440 TEST_F(SchedulerTest
, InitializeOutputSurfaceDoesNotBeginImplFrame
) {
441 scheduler_settings_
.use_external_begin_frame_source
= true;
442 SetUpScheduler(false);
443 scheduler_
->SetCanStart();
444 scheduler_
->SetVisible(true);
445 scheduler_
->SetCanDraw(true);
447 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
449 scheduler_
->DidCreateAndInitializeOutputSurface();
450 EXPECT_NO_ACTION(client_
);
453 TEST_F(SchedulerTest
, SendBeginFramesToChildren
) {
454 scheduler_settings_
.use_external_begin_frame_source
= true;
455 SetUpScheduler(true);
457 EXPECT_FALSE(client_
->begin_frame_is_sent_to_children());
458 scheduler_
->SetNeedsCommit();
459 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
460 EXPECT_TRUE(client_
->needs_begin_frames());
462 scheduler_
->SetChildrenNeedBeginFrames(true);
465 EXPECT_SCOPED(AdvanceFrame());
466 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
467 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
468 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
469 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
470 EXPECT_TRUE(client_
->needs_begin_frames());
473 TEST_F(SchedulerTest
, SendBeginFramesToChildrenWithoutCommit
) {
474 scheduler_settings_
.use_external_begin_frame_source
= true;
475 SetUpScheduler(true);
477 EXPECT_FALSE(client_
->needs_begin_frames());
478 scheduler_
->SetChildrenNeedBeginFrames(true);
479 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
480 EXPECT_TRUE(client_
->needs_begin_frames());
483 EXPECT_SCOPED(AdvanceFrame());
484 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
487 TEST_F(SchedulerTest
, SendBeginFramesToChildrenDeadlineNotAdjusted
) {
488 // Set up client with specified estimates.
489 SchedulerClientWithFixedEstimates
* client
=
490 new SchedulerClientWithFixedEstimates(
491 base::TimeDelta::FromMilliseconds(1),
492 base::TimeDelta::FromMilliseconds(2),
493 base::TimeDelta::FromMilliseconds(4));
494 scheduler_settings_
.use_external_begin_frame_source
= true;
495 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
497 EXPECT_FALSE(client_
->needs_begin_frames());
498 scheduler_
->SetChildrenNeedBeginFrames(true);
499 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
500 EXPECT_TRUE(client_
->needs_begin_frames());
504 BeginFrameArgs frame_args
=
505 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
506 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args
);
508 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
509 EXPECT_EQ(client_
->begin_frame_args_sent_to_children().deadline
,
510 frame_args
.deadline
);
513 TEST_F(SchedulerTest
, VideoNeedsBeginFrames
) {
514 scheduler_settings_
.use_external_begin_frame_source
= true;
515 SetUpScheduler(true);
517 scheduler_
->SetVideoNeedsBeginFrames(true);
518 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
519 EXPECT_TRUE(client_
->needs_begin_frames());
522 EXPECT_SCOPED(AdvanceFrame());
523 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
524 // WillBeginImplFrame is responsible for sending BeginFrames to video.
525 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
528 EXPECT_SCOPED(AdvanceFrame());
529 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
530 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
533 scheduler_
->SetVideoNeedsBeginFrames(false);
534 EXPECT_NO_ACTION(client_
);
537 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
538 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
539 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
540 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
541 EXPECT_FALSE(client_
->needs_begin_frames());
544 TEST_F(SchedulerTest
, RequestCommit
) {
545 scheduler_settings_
.use_external_begin_frame_source
= true;
546 SetUpScheduler(true);
548 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
549 scheduler_
->SetNeedsCommit();
550 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
553 EXPECT_SCOPED(AdvanceFrame());
554 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
555 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
556 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
557 EXPECT_TRUE(client_
->needs_begin_frames());
560 // If we don't swap on the deadline, we wait for the next BeginFrame.
561 task_runner().RunPendingTasks(); // Run posted deadline.
562 EXPECT_NO_ACTION(client_
);
563 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
564 EXPECT_TRUE(client_
->needs_begin_frames());
567 // NotifyReadyToCommit should trigger the commit.
568 scheduler_
->NotifyBeginMainFrameStarted();
569 scheduler_
->NotifyReadyToCommit();
570 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
571 EXPECT_TRUE(client_
->needs_begin_frames());
574 // BeginImplFrame should prepare the draw.
575 EXPECT_SCOPED(AdvanceFrame());
576 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
577 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
578 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
579 EXPECT_TRUE(client_
->needs_begin_frames());
582 // BeginImplFrame deadline should draw.
583 task_runner().RunPendingTasks(); // Run posted deadline.
584 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
585 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
586 EXPECT_TRUE(client_
->needs_begin_frames());
589 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
590 // to avoid excessive toggles.
591 EXPECT_SCOPED(AdvanceFrame());
592 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
593 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
596 task_runner().RunPendingTasks(); // Run posted deadline.
597 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
598 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
602 TEST_F(SchedulerTest
, RequestCommitAfterSetDeferCommit
) {
603 scheduler_settings_
.use_external_begin_frame_source
= true;
604 SetUpScheduler(true);
606 scheduler_
->SetDeferCommits(true);
608 scheduler_
->SetNeedsCommit();
609 EXPECT_NO_ACTION(client_
);
612 task_runner().RunPendingTasks();
613 // There are no pending tasks or actions.
614 EXPECT_NO_ACTION(client_
);
615 EXPECT_FALSE(client_
->needs_begin_frames());
618 scheduler_
->SetDeferCommits(false);
619 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
621 // Start new BeginMainFrame after defer commit is off.
623 EXPECT_SCOPED(AdvanceFrame());
624 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
625 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
626 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
629 TEST_F(SchedulerTest
, DeferCommitWithRedraw
) {
630 scheduler_settings_
.use_external_begin_frame_source
= true;
631 SetUpScheduler(true);
633 scheduler_
->SetDeferCommits(true);
635 scheduler_
->SetNeedsCommit();
636 EXPECT_NO_ACTION(client_
);
638 // The SetNeedsRedraw will override the SetDeferCommits(true), to allow a
639 // begin frame to be needed.
641 scheduler_
->SetNeedsRedraw();
642 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
646 // BeginMainFrame is not sent during the defer commit is on.
647 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
648 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
651 task_runner().RunPendingTasks(); // Run posted deadline.
652 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
653 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
654 EXPECT_TRUE(client_
->needs_begin_frames());
658 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
661 TEST_F(SchedulerTest
, RequestCommitAfterBeginMainFrameSent
) {
662 scheduler_settings_
.use_external_begin_frame_source
= true;
663 SetUpScheduler(true);
665 // SetNeedsCommit should begin the frame.
666 scheduler_
->SetNeedsCommit();
667 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
670 EXPECT_SCOPED(AdvanceFrame());
671 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
672 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
673 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
675 EXPECT_TRUE(client_
->needs_begin_frames());
678 // Now SetNeedsCommit again. Calling here means we need a second commit.
679 scheduler_
->SetNeedsCommit();
680 EXPECT_EQ(client_
->num_actions_(), 0);
683 // Finish the first commit.
684 scheduler_
->NotifyBeginMainFrameStarted();
685 scheduler_
->NotifyReadyToCommit();
686 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
687 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
689 task_runner().RunPendingTasks(); // Run posted deadline.
690 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
691 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
692 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
694 // Because we just swapped, the Scheduler should also request the next
695 // BeginImplFrame from the OutputSurface.
696 EXPECT_TRUE(client_
->needs_begin_frames());
698 // Since another commit is needed, the next BeginImplFrame should initiate
699 // the second commit.
700 EXPECT_SCOPED(AdvanceFrame());
701 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
702 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
703 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
706 // Finishing the commit before the deadline should post a new deadline task
707 // to trigger the deadline early.
708 scheduler_
->NotifyBeginMainFrameStarted();
709 scheduler_
->NotifyReadyToCommit();
710 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
711 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
713 task_runner().RunPendingTasks(); // Run posted deadline.
714 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
715 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
716 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
717 EXPECT_TRUE(client_
->needs_begin_frames());
720 // On the next BeginImplFrame, verify we go back to a quiescent state and
721 // no longer request BeginImplFrames.
722 EXPECT_SCOPED(AdvanceFrame());
723 task_runner().RunPendingTasks(); // Run posted deadline.
724 EXPECT_FALSE(client_
->needs_begin_frames());
728 class SchedulerClientThatsetNeedsDrawInsideDraw
: public FakeSchedulerClient
{
730 SchedulerClientThatsetNeedsDrawInsideDraw()
731 : FakeSchedulerClient(), request_redraws_(false) {}
733 void ScheduledActionSendBeginMainFrame() override
{}
735 void SetRequestRedrawsInsideDraw(bool enable
) { request_redraws_
= enable
; }
737 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
738 // Only SetNeedsRedraw the first time this is called
739 if (request_redraws_
) {
740 scheduler_
->SetNeedsRedraw();
742 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
745 DrawResult
ScheduledActionDrawAndSwapForced() override
{
750 void ScheduledActionCommit() override
{}
751 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{}
754 bool request_redraws_
;
757 // Tests for two different situations:
758 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
759 // a ScheduledActionDrawAndSwap
760 // 2. the scheduler drawing twice inside a single tick
761 TEST_F(SchedulerTest
, RequestRedrawInsideDraw
) {
762 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
763 new SchedulerClientThatsetNeedsDrawInsideDraw
;
764 scheduler_settings_
.use_external_begin_frame_source
= true;
765 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
766 client
->SetRequestRedrawsInsideDraw(true);
768 scheduler_
->SetNeedsRedraw();
769 EXPECT_TRUE(scheduler_
->RedrawPending());
770 EXPECT_TRUE(client
->needs_begin_frames());
771 EXPECT_EQ(0, client
->num_draws());
773 EXPECT_SCOPED(AdvanceFrame());
774 task_runner().RunPendingTasks(); // Run posted deadline.
775 EXPECT_EQ(1, client
->num_draws());
776 EXPECT_TRUE(scheduler_
->RedrawPending());
777 EXPECT_TRUE(client
->needs_begin_frames());
779 client
->SetRequestRedrawsInsideDraw(false);
781 EXPECT_SCOPED(AdvanceFrame());
782 task_runner().RunPendingTasks(); // Run posted deadline.
783 EXPECT_EQ(2, client_
->num_draws());
784 EXPECT_FALSE(scheduler_
->RedrawPending());
785 EXPECT_TRUE(client
->needs_begin_frames());
787 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
789 EXPECT_SCOPED(AdvanceFrame());
790 task_runner().RunPendingTasks(); // Run posted deadline.
791 EXPECT_EQ(2, client
->num_draws());
792 EXPECT_FALSE(scheduler_
->RedrawPending());
793 EXPECT_FALSE(client
->needs_begin_frames());
796 // Test that requesting redraw inside a failed draw doesn't lose the request.
797 TEST_F(SchedulerTest
, RequestRedrawInsideFailedDraw
) {
798 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
799 new SchedulerClientThatsetNeedsDrawInsideDraw
;
800 scheduler_settings_
.use_external_begin_frame_source
= true;
801 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
803 client
->SetRequestRedrawsInsideDraw(true);
804 client
->SetDrawWillHappen(false);
806 scheduler_
->SetNeedsRedraw();
807 EXPECT_TRUE(scheduler_
->RedrawPending());
808 EXPECT_TRUE(client
->needs_begin_frames());
809 EXPECT_EQ(0, client
->num_draws());
812 EXPECT_SCOPED(AdvanceFrame());
813 task_runner().RunPendingTasks(); // Run posted deadline.
814 EXPECT_EQ(1, client
->num_draws());
816 // We have a commit pending and the draw failed, and we didn't lose the redraw
818 EXPECT_TRUE(scheduler_
->CommitPending());
819 EXPECT_TRUE(scheduler_
->RedrawPending());
820 EXPECT_TRUE(client
->needs_begin_frames());
822 client
->SetRequestRedrawsInsideDraw(false);
824 // Fail the draw again.
825 EXPECT_SCOPED(AdvanceFrame());
826 task_runner().RunPendingTasks(); // Run posted deadline.
827 EXPECT_EQ(2, client
->num_draws());
828 EXPECT_TRUE(scheduler_
->CommitPending());
829 EXPECT_TRUE(scheduler_
->RedrawPending());
830 EXPECT_TRUE(client
->needs_begin_frames());
832 // Draw successfully.
833 client
->SetDrawWillHappen(true);
834 EXPECT_SCOPED(AdvanceFrame());
835 task_runner().RunPendingTasks(); // Run posted deadline.
836 EXPECT_EQ(3, client
->num_draws());
837 EXPECT_TRUE(scheduler_
->CommitPending());
838 EXPECT_FALSE(scheduler_
->RedrawPending());
839 EXPECT_TRUE(client
->needs_begin_frames());
842 class SchedulerClientThatSetNeedsCommitInsideDraw
: public FakeSchedulerClient
{
844 SchedulerClientThatSetNeedsCommitInsideDraw()
845 : set_needs_commit_on_next_draw_(false) {}
847 void ScheduledActionSendBeginMainFrame() override
{}
848 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
849 // Only SetNeedsCommit the first time this is called
850 if (set_needs_commit_on_next_draw_
) {
851 scheduler_
->SetNeedsCommit();
852 set_needs_commit_on_next_draw_
= false;
854 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
857 DrawResult
ScheduledActionDrawAndSwapForced() override
{
862 void ScheduledActionCommit() override
{}
863 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{}
865 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_
= true; }
868 bool set_needs_commit_on_next_draw_
;
871 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
872 // happen inside a ScheduledActionDrawAndSwap
873 TEST_F(SchedulerTest
, RequestCommitInsideDraw
) {
874 SchedulerClientThatSetNeedsCommitInsideDraw
* client
=
875 new SchedulerClientThatSetNeedsCommitInsideDraw
;
877 scheduler_settings_
.use_external_begin_frame_source
= true;
878 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
880 EXPECT_FALSE(client
->needs_begin_frames());
881 scheduler_
->SetNeedsRedraw();
882 EXPECT_TRUE(scheduler_
->RedrawPending());
883 EXPECT_EQ(0, client
->num_draws());
884 EXPECT_TRUE(client
->needs_begin_frames());
886 client
->SetNeedsCommitOnNextDraw();
887 EXPECT_SCOPED(AdvanceFrame());
888 client
->SetNeedsCommitOnNextDraw();
889 task_runner().RunPendingTasks(); // Run posted deadline.
890 EXPECT_EQ(1, client
->num_draws());
891 EXPECT_TRUE(scheduler_
->CommitPending());
892 EXPECT_TRUE(client
->needs_begin_frames());
893 scheduler_
->NotifyBeginMainFrameStarted();
894 scheduler_
->NotifyReadyToCommit();
896 EXPECT_SCOPED(AdvanceFrame());
897 task_runner().RunPendingTasks(); // Run posted deadline.
898 EXPECT_EQ(2, client
->num_draws());
900 EXPECT_FALSE(scheduler_
->RedrawPending());
901 EXPECT_FALSE(scheduler_
->CommitPending());
902 EXPECT_TRUE(client
->needs_begin_frames());
904 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
906 EXPECT_SCOPED(AdvanceFrame());
907 task_runner().RunPendingTasks(); // Run posted deadline.
908 EXPECT_EQ(2, client
->num_draws());
909 EXPECT_FALSE(scheduler_
->RedrawPending());
910 EXPECT_FALSE(scheduler_
->CommitPending());
911 EXPECT_FALSE(client
->needs_begin_frames());
914 // Tests that when a draw fails then the pending commit should not be dropped.
915 TEST_F(SchedulerTest
, RequestCommitInsideFailedDraw
) {
916 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
917 new SchedulerClientThatsetNeedsDrawInsideDraw
;
918 scheduler_settings_
.use_external_begin_frame_source
= true;
919 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
921 client
->SetDrawWillHappen(false);
923 scheduler_
->SetNeedsRedraw();
924 EXPECT_TRUE(scheduler_
->RedrawPending());
925 EXPECT_TRUE(client
->needs_begin_frames());
926 EXPECT_EQ(0, client
->num_draws());
929 EXPECT_SCOPED(AdvanceFrame());
930 task_runner().RunPendingTasks(); // Run posted deadline.
931 EXPECT_EQ(1, client
->num_draws());
933 // We have a commit pending and the draw failed, and we didn't lose the commit
935 EXPECT_TRUE(scheduler_
->CommitPending());
936 EXPECT_TRUE(scheduler_
->RedrawPending());
937 EXPECT_TRUE(client
->needs_begin_frames());
939 // Fail the draw again.
940 EXPECT_SCOPED(AdvanceFrame());
942 task_runner().RunPendingTasks(); // Run posted deadline.
943 EXPECT_EQ(2, client
->num_draws());
944 EXPECT_TRUE(scheduler_
->CommitPending());
945 EXPECT_TRUE(scheduler_
->RedrawPending());
946 EXPECT_TRUE(client
->needs_begin_frames());
948 // Draw successfully.
949 client
->SetDrawWillHappen(true);
950 EXPECT_SCOPED(AdvanceFrame());
951 task_runner().RunPendingTasks(); // Run posted deadline.
952 EXPECT_EQ(3, client
->num_draws());
953 EXPECT_TRUE(scheduler_
->CommitPending());
954 EXPECT_FALSE(scheduler_
->RedrawPending());
955 EXPECT_TRUE(client
->needs_begin_frames());
958 TEST_F(SchedulerTest
, NoSwapWhenDrawFails
) {
959 SchedulerClientThatSetNeedsCommitInsideDraw
* client
=
960 new SchedulerClientThatSetNeedsCommitInsideDraw
;
961 scheduler_settings_
.use_external_begin_frame_source
= true;
962 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
964 scheduler_
->SetNeedsRedraw();
965 EXPECT_TRUE(scheduler_
->RedrawPending());
966 EXPECT_TRUE(client
->needs_begin_frames());
967 EXPECT_EQ(0, client
->num_draws());
969 // Draw successfully, this starts a new frame.
970 client
->SetNeedsCommitOnNextDraw();
971 EXPECT_SCOPED(AdvanceFrame());
972 task_runner().RunPendingTasks(); // Run posted deadline.
973 EXPECT_EQ(1, client
->num_draws());
975 scheduler_
->SetNeedsRedraw();
976 EXPECT_TRUE(scheduler_
->RedrawPending());
977 EXPECT_TRUE(client
->needs_begin_frames());
979 // Fail to draw, this should not start a frame.
980 client
->SetDrawWillHappen(false);
981 client
->SetNeedsCommitOnNextDraw();
982 EXPECT_SCOPED(AdvanceFrame());
983 task_runner().RunPendingTasks(); // Run posted deadline.
984 EXPECT_EQ(2, client
->num_draws());
987 class SchedulerClientNeedsPrepareTilesInDraw
: public FakeSchedulerClient
{
989 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
990 scheduler_
->SetNeedsPrepareTiles();
991 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
995 // Test prepare tiles is independant of draws.
996 TEST_F(SchedulerTest
, PrepareTiles
) {
997 SchedulerClientNeedsPrepareTilesInDraw
* client
=
998 new SchedulerClientNeedsPrepareTilesInDraw
;
999 scheduler_settings_
.use_external_begin_frame_source
= true;
1000 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1002 // Request both draw and prepare tiles. PrepareTiles shouldn't
1003 // be trigged until BeginImplFrame.
1005 scheduler_
->SetNeedsPrepareTiles();
1006 scheduler_
->SetNeedsRedraw();
1007 EXPECT_TRUE(scheduler_
->RedrawPending());
1008 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1009 EXPECT_TRUE(client
->needs_begin_frames());
1010 EXPECT_EQ(0, client
->num_draws());
1011 EXPECT_FALSE(client
->HasAction("ScheduledActionPrepareTiles"));
1012 EXPECT_FALSE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1014 // We have no immediate actions to perform, so the BeginImplFrame should post
1015 // the deadline task.
1017 EXPECT_SCOPED(AdvanceFrame());
1018 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1019 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1020 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1022 // On the deadline, he actions should have occured in the right order.
1024 task_runner().RunPendingTasks(); // Run posted deadline.
1025 EXPECT_EQ(1, client
->num_draws());
1026 EXPECT_TRUE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1027 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
1028 EXPECT_LT(client
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1029 client
->ActionIndex("ScheduledActionPrepareTiles"));
1030 EXPECT_FALSE(scheduler_
->RedrawPending());
1031 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1032 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1034 // Request a draw. We don't need a PrepareTiles yet.
1036 scheduler_
->SetNeedsRedraw();
1037 EXPECT_TRUE(scheduler_
->RedrawPending());
1038 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1039 EXPECT_TRUE(client
->needs_begin_frames());
1040 EXPECT_EQ(0, client
->num_draws());
1042 // We have no immediate actions to perform, so the BeginImplFrame should post
1043 // the deadline task.
1045 EXPECT_SCOPED(AdvanceFrame());
1046 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1047 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1048 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1050 // Draw. The draw will trigger SetNeedsPrepareTiles, and
1051 // then the PrepareTiles action will be triggered after the Draw.
1052 // Afterwards, neither a draw nor PrepareTiles are pending.
1054 task_runner().RunPendingTasks(); // Run posted deadline.
1055 EXPECT_EQ(1, client
->num_draws());
1056 EXPECT_TRUE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1057 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
1058 EXPECT_LT(client
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1059 client
->ActionIndex("ScheduledActionPrepareTiles"));
1060 EXPECT_FALSE(scheduler_
->RedrawPending());
1061 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1062 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1064 // We need a BeginImplFrame where we don't swap to go idle.
1066 EXPECT_SCOPED(AdvanceFrame());
1067 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
1068 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1070 task_runner().RunPendingTasks(); // Run posted deadline.
1071 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
1072 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
1073 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1074 EXPECT_EQ(0, client
->num_draws());
1076 // Now trigger a PrepareTiles outside of a draw. We will then need
1077 // a begin-frame for the PrepareTiles, but we don't need a draw.
1079 EXPECT_FALSE(client
->needs_begin_frames());
1080 scheduler_
->SetNeedsPrepareTiles();
1081 EXPECT_TRUE(client
->needs_begin_frames());
1082 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1083 EXPECT_FALSE(scheduler_
->RedrawPending());
1085 // BeginImplFrame. There will be no draw, only PrepareTiles.
1087 EXPECT_SCOPED(AdvanceFrame());
1088 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
1089 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1091 task_runner().RunPendingTasks(); // Run posted deadline.
1092 EXPECT_EQ(0, client
->num_draws());
1093 EXPECT_FALSE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1094 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
1095 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1098 // Test that PrepareTiles only happens once per frame. If an external caller
1099 // initiates it, then the state machine should not PrepareTiles on that frame.
1100 TEST_F(SchedulerTest
, PrepareTilesOncePerFrame
) {
1101 scheduler_settings_
.use_external_begin_frame_source
= true;
1102 SetUpScheduler(true);
1104 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
1106 scheduler_
->SetNeedsPrepareTiles();
1107 scheduler_
->SetNeedsRedraw();
1109 EXPECT_SCOPED(AdvanceFrame());
1110 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1111 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1112 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1114 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1115 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1116 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1119 task_runner().RunPendingTasks(); // Run posted deadline.
1120 EXPECT_EQ(1, client_
->num_draws());
1121 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1122 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1123 EXPECT_FALSE(scheduler_
->RedrawPending());
1124 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1125 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1127 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1128 scheduler_
->SetNeedsPrepareTiles();
1129 scheduler_
->SetNeedsRedraw();
1131 EXPECT_SCOPED(AdvanceFrame());
1132 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1133 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1134 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1137 task_runner().RunPendingTasks(); // Run posted deadline.
1138 EXPECT_EQ(1, client_
->num_draws());
1139 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1140 EXPECT_TRUE(client_
->HasAction("ScheduledActionPrepareTiles"));
1141 EXPECT_LT(client_
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1142 client_
->ActionIndex("ScheduledActionPrepareTiles"));
1143 EXPECT_FALSE(scheduler_
->RedrawPending());
1144 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1145 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1146 scheduler_
->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1148 // If we get another DidPrepareTiles within the same frame, we should
1149 // not PrepareTiles on the next frame.
1150 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1151 scheduler_
->SetNeedsPrepareTiles();
1152 scheduler_
->SetNeedsRedraw();
1154 EXPECT_SCOPED(AdvanceFrame());
1155 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1156 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1157 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1159 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1162 task_runner().RunPendingTasks(); // Run posted deadline.
1163 EXPECT_EQ(1, client_
->num_draws());
1164 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1165 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1166 EXPECT_FALSE(scheduler_
->RedrawPending());
1167 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1169 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1170 // frame. This verifies we don't alternate calling PrepareTiles once and
1172 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1173 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1174 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1175 scheduler_
->SetNeedsPrepareTiles();
1176 scheduler_
->SetNeedsRedraw();
1178 EXPECT_SCOPED(AdvanceFrame());
1179 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1180 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1181 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1183 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1186 task_runner().RunPendingTasks(); // Run posted deadline.
1187 EXPECT_EQ(1, client_
->num_draws());
1188 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1189 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1190 EXPECT_FALSE(scheduler_
->RedrawPending());
1191 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1193 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1194 scheduler_
->SetNeedsPrepareTiles();
1195 scheduler_
->SetNeedsRedraw();
1197 EXPECT_SCOPED(AdvanceFrame());
1198 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1199 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1200 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1203 task_runner().RunPendingTasks(); // Run posted deadline.
1204 EXPECT_EQ(1, client_
->num_draws());
1205 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1206 EXPECT_TRUE(client_
->HasAction("ScheduledActionPrepareTiles"));
1207 EXPECT_LT(client_
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1208 client_
->ActionIndex("ScheduledActionPrepareTiles"));
1209 EXPECT_FALSE(scheduler_
->RedrawPending());
1210 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1211 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1212 scheduler_
->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1215 TEST_F(SchedulerTest
, TriggerBeginFrameDeadlineEarly
) {
1216 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1217 new SchedulerClientNeedsPrepareTilesInDraw
;
1218 scheduler_settings_
.use_external_begin_frame_source
= true;
1219 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1221 scheduler_
->SetNeedsRedraw();
1222 EXPECT_SCOPED(AdvanceFrame());
1224 // The deadline should be zero since there is no work other than drawing
1226 EXPECT_EQ(base::TimeTicks(), client
->posted_begin_impl_frame_deadline());
1229 TEST_F(SchedulerTest
, WaitForReadyToDrawDoNotPostDeadline
) {
1230 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1231 new SchedulerClientNeedsPrepareTilesInDraw
;
1232 scheduler_settings_
.use_external_begin_frame_source
= true;
1233 scheduler_settings_
.impl_side_painting
= true;
1234 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1236 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1237 scheduler_
->SetNeedsCommit();
1238 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1242 EXPECT_SCOPED(AdvanceFrame());
1243 scheduler_
->NotifyBeginMainFrameStarted();
1244 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1245 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1248 scheduler_
->NotifyReadyToCommit();
1249 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1252 scheduler_
->NotifyReadyToActivate();
1253 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
1255 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1257 scheduler_
->SetWaitForReadyToDraw();
1259 task_runner().RunPendingTasks(); // Try to run posted deadline.
1260 // There is no posted deadline.
1261 EXPECT_NO_ACTION(client_
);
1263 // Scheduler received ready to draw signal, and posted deadline.
1264 scheduler_
->NotifyReadyToDraw();
1266 task_runner().RunPendingTasks(); // Run posted deadline.
1267 EXPECT_EQ(1, client_
->num_draws());
1268 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1271 TEST_F(SchedulerTest
, WaitForReadyToDrawCancelledWhenLostOutputSurface
) {
1272 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1273 new SchedulerClientNeedsPrepareTilesInDraw
;
1274 scheduler_settings_
.use_external_begin_frame_source
= true;
1275 scheduler_settings_
.impl_side_painting
= true;
1276 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1278 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1279 scheduler_
->SetNeedsCommit();
1280 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1284 EXPECT_SCOPED(AdvanceFrame());
1285 scheduler_
->NotifyBeginMainFrameStarted();
1286 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1287 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1290 scheduler_
->NotifyReadyToCommit();
1291 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1294 scheduler_
->NotifyReadyToActivate();
1295 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
1297 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1299 scheduler_
->SetWaitForReadyToDraw();
1301 task_runner().RunPendingTasks(); // Try to run posted deadline.
1302 // There is no posted deadline.
1303 EXPECT_NO_ACTION(client_
);
1305 // Scheduler loses output surface, and stops waiting for ready to draw signal.
1307 scheduler_
->DidLoseOutputSurface();
1308 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1309 task_runner().RunPendingTasks(); // Run posted deadline.
1310 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
1311 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
1312 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
1315 void SchedulerTest::MainFrameInHighLatencyMode(
1316 int64 begin_main_frame_to_commit_estimate_in_ms
,
1317 int64 commit_to_activate_estimate_in_ms
,
1318 bool impl_latency_takes_priority
,
1319 bool should_send_begin_main_frame
) {
1320 // Set up client with specified estimates (draw duration is set to 1).
1321 SchedulerClientWithFixedEstimates
* client
=
1322 new SchedulerClientWithFixedEstimates(
1323 base::TimeDelta::FromMilliseconds(1),
1324 base::TimeDelta::FromMilliseconds(
1325 begin_main_frame_to_commit_estimate_in_ms
),
1326 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms
));
1328 scheduler_settings_
.use_external_begin_frame_source
= true;
1329 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1331 scheduler_
->SetImplLatencyTakesPriority(impl_latency_takes_priority
);
1333 // Impl thread hits deadline before commit finishes.
1334 scheduler_
->SetNeedsCommit();
1335 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1336 EXPECT_SCOPED(AdvanceFrame());
1337 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1338 task_runner().RunPendingTasks(); // Run posted deadline.
1339 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1340 scheduler_
->NotifyBeginMainFrameStarted();
1341 scheduler_
->NotifyReadyToCommit();
1342 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1343 EXPECT_TRUE(client
->HasAction("ScheduledActionSendBeginMainFrame"));
1346 scheduler_
->SetNeedsCommit();
1347 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1348 EXPECT_SCOPED(AdvanceFrame());
1349 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1350 task_runner().RunPendingTasks(); // Run posted deadline.
1351 EXPECT_EQ(scheduler_
->MainThreadIsInHighLatencyMode(),
1352 should_send_begin_main_frame
);
1353 EXPECT_EQ(client
->HasAction("ScheduledActionSendBeginMainFrame"),
1354 should_send_begin_main_frame
);
1357 TEST_F(SchedulerTest
,
1358 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline
) {
1359 // Set up client so that estimates indicate that we can commit and activate
1360 // before the deadline (~8ms by default).
1361 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, false, false));
1364 TEST_F(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong
) {
1365 // Set up client so that estimates indicate that the commit cannot finish
1366 // before the deadline (~8ms by default).
1367 EXPECT_SCOPED(MainFrameInHighLatencyMode(10, 1, false, true));
1370 TEST_F(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong
) {
1371 // Set up client so that estimates indicate that the activate cannot finish
1372 // before the deadline (~8ms by default).
1373 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true));
1376 TEST_F(SchedulerTest
, NotSkipMainFrameInPreferImplLatencyMode
) {
1377 // Set up client so that estimates indicate that we can commit and activate
1378 // before the deadline (~8ms by default), but also enable impl latency takes
1380 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true));
1383 TEST_F(SchedulerTest
,
1384 Deadlock_NotifyReadyToCommitMakesProgressWhileSwapTrottled
) {
1385 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1386 // thread. This prevents the scheduler from receiving any pending swap acks.
1387 // This test makes sure that we keep updating the TextureUploader with
1388 // DidAnticipatedDrawTimeChange's so that it can make forward progress and
1389 // upload all the textures needed for the commit to complete.
1391 // Since we are simulating a long commit, set up a client with draw duration
1392 // estimates that prevent skipping main frames to get to low latency mode.
1393 SchedulerClientWithFixedEstimates
* client
=
1394 new SchedulerClientWithFixedEstimates(
1395 base::TimeDelta::FromMilliseconds(1),
1396 base::TimeDelta::FromMilliseconds(32),
1397 base::TimeDelta::FromMilliseconds(32));
1398 scheduler_settings_
.use_external_begin_frame_source
= true;
1399 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1401 client
->set_log_anticipated_draw_time_change(true);
1403 BeginFrameArgs frame_args
=
1404 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1405 frame_args
.interval
= base::TimeDelta::FromMilliseconds(1000);
1407 // At this point, we've drawn a frame. Start another commit, but hold off on
1408 // the NotifyReadyToCommit for now.
1409 EXPECT_FALSE(scheduler_
->CommitPending());
1410 scheduler_
->SetNeedsCommit();
1411 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args
);
1412 EXPECT_TRUE(scheduler_
->CommitPending());
1414 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1415 // blocking on the renderer.
1416 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1417 task_runner().RunPendingTasks(); // Run posted deadline.
1418 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1419 scheduler_
->DidSwapBuffers();
1421 // Spin the event loop a few times and make sure we get more
1422 // DidAnticipateDrawTimeChange calls every time.
1423 int actions_so_far
= client
->num_actions_();
1425 // Does three iterations to make sure that the timer is properly repeating.
1426 for (int i
= 0; i
< 3; ++i
) {
1427 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1428 task_runner().DelayToNextTaskTime().InMicroseconds())
1429 << scheduler_
->AsValue()->ToString();
1430 task_runner().RunPendingTasks();
1431 EXPECT_GT(client
->num_actions_(), actions_so_far
);
1432 EXPECT_STREQ(client
->Action(client
->num_actions_() - 1),
1433 "DidAnticipatedDrawTimeChange");
1434 actions_so_far
= client
->num_actions_();
1437 // Do the same thing after BeginMainFrame starts but still before activation.
1438 scheduler_
->NotifyBeginMainFrameStarted();
1439 for (int i
= 0; i
< 3; ++i
) {
1440 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1441 task_runner().DelayToNextTaskTime().InMicroseconds())
1442 << scheduler_
->AsValue()->ToString();
1443 task_runner().RunPendingTasks();
1444 EXPECT_GT(client
->num_actions_(), actions_so_far
);
1445 EXPECT_STREQ(client
->Action(client
->num_actions_() - 1),
1446 "DidAnticipatedDrawTimeChange");
1447 actions_so_far
= client
->num_actions_();
1453 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw
) {
1454 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1455 // thread. This prevents the scheduler from receiving any pending swap acks.
1457 // Since we are simulating a long commit, set up a client with draw duration
1458 // estimates that prevent skipping main frames to get to low latency mode.
1459 SchedulerClientWithFixedEstimates
* client
=
1460 new SchedulerClientWithFixedEstimates(
1461 base::TimeDelta::FromMilliseconds(1),
1462 base::TimeDelta::FromMilliseconds(32),
1463 base::TimeDelta::FromMilliseconds(32));
1464 scheduler_settings_
.use_external_begin_frame_source
= true;
1465 scheduler_settings_
.main_frame_while_swap_throttled_enabled
= true;
1466 scheduler_settings_
.impl_side_painting
= true;
1467 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1469 // Disables automatic swap acks so this test can force swap ack throttling
1470 // to simulate a blocked Browser ui thread.
1471 scheduler_
->SetMaxSwapsPending(1);
1472 client_
->SetAutomaticSwapAck(false);
1474 // Get a new active tree in main-thread high latency mode and put us
1475 // in a swap throttled state.
1477 EXPECT_FALSE(scheduler_
->CommitPending());
1478 scheduler_
->SetNeedsCommit();
1479 scheduler_
->SetNeedsRedraw();
1480 EXPECT_SCOPED(AdvanceFrame());
1481 EXPECT_TRUE(scheduler_
->CommitPending());
1482 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1483 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1484 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1485 scheduler_
->NotifyBeginMainFrameStarted();
1486 scheduler_
->NotifyReadyToCommit();
1487 scheduler_
->NotifyReadyToActivate();
1488 EXPECT_FALSE(scheduler_
->CommitPending());
1489 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_
, 0, 7);
1490 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 7);
1491 EXPECT_ACTION("ScheduledActionAnimate", client_
, 2, 7);
1492 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 3, 7);
1493 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 4, 7);
1494 EXPECT_ACTION("ScheduledActionCommit", client_
, 5, 7);
1495 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 6, 7);
1497 // Make sure that we can finish the next commit even while swap throttled.
1499 EXPECT_FALSE(scheduler_
->CommitPending());
1500 scheduler_
->SetNeedsCommit();
1501 EXPECT_SCOPED(AdvanceFrame());
1502 scheduler_
->NotifyBeginMainFrameStarted();
1503 scheduler_
->NotifyReadyToCommit();
1504 scheduler_
->NotifyReadyToActivate();
1505 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1506 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1507 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1508 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 5);
1509 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 5);
1510 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 2, 5);
1511 EXPECT_ACTION("ScheduledActionCommit", client_
, 3, 5);
1512 EXPECT_ACTION("ScheduledActionAnimate", client_
, 4, 5);
1514 // Make sure we do not send a BeginMainFrame while swap throttled and
1515 // we have both a pending tree and an active tree.
1517 EXPECT_FALSE(scheduler_
->CommitPending());
1518 scheduler_
->SetNeedsCommit();
1519 EXPECT_SCOPED(AdvanceFrame());
1520 EXPECT_FALSE(scheduler_
->CommitPending());
1521 task_runner().RunPendingTasks(); // Run posted deadline.
1522 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1523 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1526 TEST_F(SchedulerTest
,
1527 Deadlock_NoBeginMainFrameWhileSwapTrottledAndPipelineFull
) {
1528 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1529 // thread. This prevents the scheduler from receiving any pending swap acks.
1531 // This particular test makes sure we do not send a BeginMainFrame while
1532 // swap trottled and we have a pending tree and active tree that
1533 // still needs to be drawn for the first time.
1535 // Since we are simulating a long commit, set up a client with draw duration
1536 // estimates that prevent skipping main frames to get to low latency mode.
1537 SchedulerClientWithFixedEstimates
* client
=
1538 new SchedulerClientWithFixedEstimates(
1539 base::TimeDelta::FromMilliseconds(1),
1540 base::TimeDelta::FromMilliseconds(32),
1541 base::TimeDelta::FromMilliseconds(32));
1542 scheduler_settings_
.use_external_begin_frame_source
= true;
1543 scheduler_settings_
.main_frame_while_swap_throttled_enabled
= true;
1544 scheduler_settings_
.main_frame_before_activation_enabled
= true;
1545 scheduler_settings_
.impl_side_painting
= true;
1546 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1548 // Disables automatic swap acks so this test can force swap ack throttling
1549 // to simulate a blocked Browser ui thread.
1550 scheduler_
->SetMaxSwapsPending(1);
1551 client_
->SetAutomaticSwapAck(false);
1553 // Start a new commit in main-thread high latency mode and hold off on
1556 EXPECT_FALSE(scheduler_
->CommitPending());
1557 scheduler_
->SetNeedsCommit();
1558 scheduler_
->SetNeedsRedraw();
1559 EXPECT_SCOPED(AdvanceFrame());
1560 EXPECT_TRUE(scheduler_
->CommitPending());
1561 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1562 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1563 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1564 scheduler_
->DidSwapBuffersComplete();
1565 scheduler_
->NotifyBeginMainFrameStarted();
1566 scheduler_
->NotifyReadyToCommit();
1567 EXPECT_FALSE(scheduler_
->CommitPending());
1568 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_
, 0, 6);
1569 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 6);
1570 EXPECT_ACTION("ScheduledActionAnimate", client_
, 2, 6);
1571 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 3, 6);
1572 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 4, 6);
1573 EXPECT_ACTION("ScheduledActionCommit", client_
, 5, 6);
1575 // Start another commit while we still have aa pending tree.
1576 // Enter a swap throttled state.
1578 EXPECT_FALSE(scheduler_
->CommitPending());
1579 scheduler_
->SetNeedsCommit();
1580 scheduler_
->SetNeedsRedraw();
1581 EXPECT_SCOPED(AdvanceFrame());
1582 EXPECT_TRUE(scheduler_
->CommitPending());
1583 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1584 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1585 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1586 scheduler_
->NotifyBeginMainFrameStarted();
1587 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 4);
1588 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 4);
1589 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 2, 4);
1590 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 3, 4);
1592 // Can't commit yet because there's still a pending tree.
1594 scheduler_
->NotifyReadyToCommit();
1595 EXPECT_NO_ACTION(client_
);
1597 // Activate the pending tree, which also unblocks the commit immediately.
1599 scheduler_
->NotifyReadyToActivate();
1600 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 0, 2);
1601 EXPECT_ACTION("ScheduledActionCommit", client_
, 1, 2);
1603 // Make sure we do not send a BeginMainFrame while swap throttled and
1604 // we have both a pending tree and an active tree that still needs
1607 EXPECT_FALSE(scheduler_
->CommitPending());
1608 scheduler_
->SetNeedsCommit();
1609 EXPECT_SCOPED(AdvanceFrame());
1610 EXPECT_FALSE(scheduler_
->CommitPending());
1611 task_runner().RunPendingTasks(); // Run posted deadline.
1612 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1613 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1618 CommitMakesProgressWhenIdleAndHasPendingTreeAndActiveTreeNeedsFirstDraw
) {
1619 // This verifies we don't block commits longer than we need to
1620 // for performance reasons - not deadlock reasons.
1622 // Since we are simulating a long commit, set up a client with draw duration
1623 // estimates that prevent skipping main frames to get to low latency mode.
1624 SchedulerClientWithFixedEstimates
* client
=
1625 new SchedulerClientWithFixedEstimates(
1626 base::TimeDelta::FromMilliseconds(1),
1627 base::TimeDelta::FromMilliseconds(32),
1628 base::TimeDelta::FromMilliseconds(32));
1629 scheduler_settings_
.use_external_begin_frame_source
= true;
1630 scheduler_settings_
.main_frame_while_swap_throttled_enabled
= true;
1631 scheduler_settings_
.main_frame_before_activation_enabled
= true;
1632 scheduler_settings_
.impl_side_painting
= true;
1633 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1635 // Disables automatic swap acks so this test can force swap ack throttling
1636 // to simulate a blocked Browser ui thread.
1637 scheduler_
->SetMaxSwapsPending(1);
1638 client_
->SetAutomaticSwapAck(false);
1640 // Start a new commit in main-thread high latency mode and hold off on
1643 EXPECT_FALSE(scheduler_
->CommitPending());
1644 scheduler_
->SetNeedsCommit();
1645 scheduler_
->SetNeedsRedraw();
1646 EXPECT_SCOPED(AdvanceFrame());
1647 EXPECT_TRUE(scheduler_
->CommitPending());
1648 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1649 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1650 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1651 scheduler_
->DidSwapBuffersComplete();
1652 scheduler_
->NotifyBeginMainFrameStarted();
1653 scheduler_
->NotifyReadyToCommit();
1654 EXPECT_FALSE(scheduler_
->CommitPending());
1655 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_
, 0, 6);
1656 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 6);
1657 EXPECT_ACTION("ScheduledActionAnimate", client_
, 2, 6);
1658 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 3, 6);
1659 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 4, 6);
1660 EXPECT_ACTION("ScheduledActionCommit", client_
, 5, 6);
1662 // Start another commit while we still have an active tree.
1664 EXPECT_FALSE(scheduler_
->CommitPending());
1665 scheduler_
->SetNeedsCommit();
1666 scheduler_
->SetNeedsRedraw();
1667 EXPECT_SCOPED(AdvanceFrame());
1668 EXPECT_TRUE(scheduler_
->CommitPending());
1669 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1670 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1671 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1672 scheduler_
->DidSwapBuffersComplete();
1673 scheduler_
->NotifyBeginMainFrameStarted();
1674 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 4);
1675 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 4);
1676 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 2, 4);
1677 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 3, 4);
1679 // Can't commit yet because there's still a pending tree.
1681 scheduler_
->NotifyReadyToCommit();
1682 EXPECT_NO_ACTION(client_
);
1684 // Activate the pending tree, which also unblocks the commit immediately
1685 // while we are in an idle state.
1687 scheduler_
->NotifyReadyToActivate();
1688 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 0, 2);
1689 EXPECT_ACTION("ScheduledActionCommit", client_
, 1, 2);
1692 TEST_F(SchedulerTest
, BeginRetroFrame
) {
1693 scheduler_settings_
.use_external_begin_frame_source
= true;
1694 SetUpScheduler(true);
1696 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1697 scheduler_
->SetNeedsCommit();
1698 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1701 // Create a BeginFrame with a long deadline to avoid race conditions.
1702 // This is the first BeginFrame, which will be handled immediately.
1703 BeginFrameArgs args
=
1704 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1705 args
.deadline
+= base::TimeDelta::FromHours(1);
1706 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1707 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1708 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1709 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1710 EXPECT_TRUE(client_
->needs_begin_frames());
1713 // Queue BeginFrames while we are still handling the previous BeginFrame.
1714 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1715 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1716 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1717 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1719 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1720 task_runner().RunPendingTasks(); // Run posted deadline.
1721 EXPECT_NO_ACTION(client_
);
1722 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1723 EXPECT_TRUE(client_
->needs_begin_frames());
1726 // NotifyReadyToCommit should trigger the commit.
1727 scheduler_
->NotifyBeginMainFrameStarted();
1728 scheduler_
->NotifyReadyToCommit();
1729 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1730 EXPECT_TRUE(client_
->needs_begin_frames());
1733 // BeginImplFrame should prepare the draw.
1734 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1735 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1736 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1737 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1738 EXPECT_TRUE(client_
->needs_begin_frames());
1741 // BeginImplFrame deadline should draw.
1742 task_runner().RunPendingTasks(); // Run posted deadline.
1743 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
1744 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1745 EXPECT_TRUE(client_
->needs_begin_frames());
1748 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1749 // to avoid excessive toggles.
1750 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1751 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
1752 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1755 task_runner().RunPendingTasks(); // Run posted deadline.
1756 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
1757 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
1761 TEST_F(SchedulerTest
, BeginRetroFrame_SwapThrottled
) {
1762 scheduler_settings_
.use_external_begin_frame_source
= true;
1763 SetUpScheduler(true);
1765 scheduler_
->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1767 // To test swap ack throttling, this test disables automatic swap acks.
1768 scheduler_
->SetMaxSwapsPending(1);
1769 client_
->SetAutomaticSwapAck(false);
1771 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1773 scheduler_
->SetNeedsCommit();
1774 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1777 EXPECT_SCOPED(AdvanceFrame());
1778 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1779 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1780 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1781 EXPECT_TRUE(client_
->needs_begin_frames());
1784 // Queue BeginFrame while we are still handling the previous BeginFrame.
1785 SendNextBeginFrame();
1786 EXPECT_NO_ACTION(client_
);
1787 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1788 EXPECT_TRUE(client_
->needs_begin_frames());
1791 // NotifyReadyToCommit should trigger the pending commit and draw.
1792 scheduler_
->NotifyBeginMainFrameStarted();
1793 scheduler_
->NotifyReadyToCommit();
1794 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1795 EXPECT_TRUE(client_
->needs_begin_frames());
1798 // Swapping will put us into a swap throttled state.
1799 // Run posted deadline.
1800 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1801 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1802 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1803 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1804 EXPECT_TRUE(client_
->needs_begin_frames());
1807 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1808 // but not a BeginMainFrame or draw.
1809 scheduler_
->SetNeedsCommit();
1810 scheduler_
->SetNeedsRedraw();
1811 // Run posted BeginRetroFrame.
1812 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false));
1813 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1814 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1815 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1816 EXPECT_TRUE(client_
->needs_begin_frames());
1819 // Let time pass sufficiently beyond the regular deadline but not beyond the
1821 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1822 base::TimeDelta::FromMicroseconds(1));
1823 task_runner().RunUntilTime(now_src()->Now());
1824 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1826 // Take us out of a swap throttled state.
1827 scheduler_
->DidSwapBuffersComplete();
1828 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_
);
1829 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1830 EXPECT_TRUE(client_
->needs_begin_frames());
1833 // Verify that the deadline was rescheduled.
1834 task_runner().RunUntilTime(now_src()->Now());
1835 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
1836 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1837 EXPECT_TRUE(client_
->needs_begin_frames());
1841 TEST_F(SchedulerTest
, RetroFrameDoesNotExpireTooEarly
) {
1842 scheduler_settings_
.use_external_begin_frame_source
= true;
1843 SetUpScheduler(true);
1845 scheduler_
->SetNeedsCommit();
1846 EXPECT_TRUE(client_
->needs_begin_frames());
1847 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1850 EXPECT_SCOPED(AdvanceFrame());
1851 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1852 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1853 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1856 scheduler_
->NotifyBeginMainFrameStarted();
1859 BeginFrameArgs retro_frame_args
= SendNextBeginFrame();
1860 // This BeginFrame is queued up as a retro frame.
1861 EXPECT_NO_ACTION(client_
);
1862 // The previous deadline is still pending.
1863 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1866 // This commit should schedule the (previous) deadline to trigger immediately.
1867 scheduler_
->NotifyReadyToCommit();
1868 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1871 // The deadline task should trigger causing a draw.
1872 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1873 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1874 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1875 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1879 scheduler_
->SetNeedsAnimate();
1880 scheduler_
->SetNeedsRedraw();
1881 EXPECT_NO_ACTION(client_
);
1883 // Let's advance to the retro frame's deadline.
1884 now_src()->AdvanceNow(retro_frame_args
.deadline
- now_src()->Now());
1886 // The retro frame hasn't expired yet.
1887 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false));
1888 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1889 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1890 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1892 // This is an immediate deadline case.
1894 task_runner().RunPendingTasks();
1895 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1896 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
1899 TEST_F(SchedulerTest
, RetroFrameExpiresOnTime
) {
1900 scheduler_settings_
.use_external_begin_frame_source
= true;
1901 SetUpScheduler(true);
1903 scheduler_
->SetNeedsCommit();
1904 EXPECT_TRUE(client_
->needs_begin_frames());
1905 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1908 EXPECT_SCOPED(AdvanceFrame());
1909 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1910 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1911 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1914 scheduler_
->NotifyBeginMainFrameStarted();
1917 BeginFrameArgs retro_frame_args
= SendNextBeginFrame();
1918 // This BeginFrame is queued up as a retro frame.
1919 EXPECT_NO_ACTION(client_
);
1920 // The previous deadline is still pending.
1921 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1924 // This commit should schedule the (previous) deadline to trigger immediately.
1925 scheduler_
->NotifyReadyToCommit();
1926 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1929 // The deadline task should trigger causing a draw.
1930 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1931 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1932 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1933 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1937 scheduler_
->SetNeedsAnimate();
1938 scheduler_
->SetNeedsRedraw();
1939 EXPECT_NO_ACTION(client_
);
1941 // Let's advance sufficiently past the retro frame's deadline.
1942 now_src()->AdvanceNow(retro_frame_args
.deadline
- now_src()->Now() +
1943 base::TimeDelta::FromMicroseconds(1));
1945 // The retro frame should've expired.
1946 EXPECT_NO_ACTION(client_
);
1949 TEST_F(SchedulerTest
, MissedFrameDoesNotExpireTooEarly
) {
1950 scheduler_settings_
.use_external_begin_frame_source
= true;
1951 SetUpScheduler(true);
1953 scheduler_
->SetNeedsCommit();
1954 EXPECT_TRUE(client_
->needs_begin_frames());
1955 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1957 BeginFrameArgs missed_frame_args
=
1958 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1959 missed_frame_args
.type
= BeginFrameArgs::MISSED
;
1961 // Advance to the deadline.
1962 now_src()->AdvanceNow(missed_frame_args
.deadline
- now_src()->Now());
1964 // Missed frame is handled because it's on time.
1966 fake_external_begin_frame_source_
->TestOnBeginFrame(missed_frame_args
);
1968 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false)));
1969 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1970 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1971 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1974 TEST_F(SchedulerTest
, MissedFrameExpiresOnTime
) {
1975 scheduler_settings_
.use_external_begin_frame_source
= true;
1976 SetUpScheduler(true);
1978 scheduler_
->SetNeedsCommit();
1979 EXPECT_TRUE(client_
->needs_begin_frames());
1980 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1982 BeginFrameArgs missed_frame_args
=
1983 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1984 missed_frame_args
.type
= BeginFrameArgs::MISSED
;
1986 // Advance sufficiently past the deadline.
1987 now_src()->AdvanceNow(missed_frame_args
.deadline
- now_src()->Now() +
1988 base::TimeDelta::FromMicroseconds(1));
1990 // Missed frame is dropped because it's too late.
1992 fake_external_begin_frame_source_
->TestOnBeginFrame(missed_frame_args
);
1994 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false)));
1995 EXPECT_NO_ACTION(client_
);
1996 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1999 void SchedulerTest::BeginFramesNotFromClient(
2000 bool use_external_begin_frame_source
,
2001 bool throttle_frame_production
) {
2002 scheduler_settings_
.use_external_begin_frame_source
=
2003 use_external_begin_frame_source
;
2004 scheduler_settings_
.throttle_frame_production
= throttle_frame_production
;
2005 SetUpScheduler(true);
2007 // SetNeedsCommit should begin the frame on the next BeginImplFrame
2008 // without calling SetNeedsBeginFrame.
2009 scheduler_
->SetNeedsCommit();
2010 EXPECT_NO_ACTION(client_
);
2013 // When the client-driven BeginFrame are disabled, the scheduler posts it's
2014 // own BeginFrame tasks.
2015 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2016 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2017 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2018 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2021 // If we don't swap on the deadline, we wait for the next BeginFrame.
2022 task_runner().RunPendingTasks(); // Run posted deadline.
2023 EXPECT_NO_ACTION(client_
);
2024 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2027 // NotifyReadyToCommit should trigger the commit.
2028 scheduler_
->NotifyBeginMainFrameStarted();
2029 scheduler_
->NotifyReadyToCommit();
2030 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2033 // BeginImplFrame should prepare the draw.
2034 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2035 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2036 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2037 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2040 // BeginImplFrame deadline should draw.
2041 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2042 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2043 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2046 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2047 // to avoid excessive toggles.
2048 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2049 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
2050 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2053 // Make sure SetNeedsBeginFrame isn't called on the client
2054 // when the BeginFrame is no longer needed.
2055 task_runner().RunPendingTasks(); // Run posted deadline.
2056 EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_
);
2060 TEST_F(SchedulerTest
, SyntheticBeginFrames
) {
2061 bool use_external_begin_frame_source
= false;
2062 bool throttle_frame_production
= true;
2063 BeginFramesNotFromClient(use_external_begin_frame_source
,
2064 throttle_frame_production
);
2067 TEST_F(SchedulerTest
, VSyncThrottlingDisabled
) {
2068 bool use_external_begin_frame_source
= true;
2069 bool throttle_frame_production
= false;
2070 BeginFramesNotFromClient(use_external_begin_frame_source
,
2071 throttle_frame_production
);
2074 TEST_F(SchedulerTest
, SyntheticBeginFrames_And_VSyncThrottlingDisabled
) {
2075 bool use_external_begin_frame_source
= false;
2076 bool throttle_frame_production
= false;
2077 BeginFramesNotFromClient(use_external_begin_frame_source
,
2078 throttle_frame_production
);
2081 void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
2082 bool use_external_begin_frame_source
,
2083 bool throttle_frame_production
) {
2084 scheduler_settings_
.use_external_begin_frame_source
=
2085 use_external_begin_frame_source
;
2086 scheduler_settings_
.throttle_frame_production
= throttle_frame_production
;
2087 SetUpScheduler(true);
2089 scheduler_
->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
2091 // To test swap ack throttling, this test disables automatic swap acks.
2092 scheduler_
->SetMaxSwapsPending(1);
2093 client_
->SetAutomaticSwapAck(false);
2095 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2097 scheduler_
->SetNeedsCommit();
2098 EXPECT_NO_ACTION(client_
);
2101 // Trigger the first BeginImplFrame and BeginMainFrame
2102 EXPECT_SCOPED(AdvanceFrame());
2103 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2104 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2105 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2108 // NotifyReadyToCommit should trigger the pending commit and draw.
2109 scheduler_
->NotifyBeginMainFrameStarted();
2110 scheduler_
->NotifyReadyToCommit();
2111 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2114 // Swapping will put us into a swap throttled state.
2115 // Run posted deadline.
2116 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2117 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2118 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2119 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2122 // While swap throttled, BeginFrames should trigger BeginImplFrames,
2123 // but not a BeginMainFrame or draw.
2124 scheduler_
->SetNeedsCommit();
2125 scheduler_
->SetNeedsRedraw();
2126 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
2127 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2128 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2129 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2132 // Let time pass sufficiently beyond the regular deadline but not beyond the
2134 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
2135 base::TimeDelta::FromMicroseconds(1));
2136 task_runner().RunUntilTime(now_src()->Now());
2137 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2139 // Take us out of a swap throttled state.
2140 scheduler_
->DidSwapBuffersComplete();
2141 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_
);
2142 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2145 // Verify that the deadline was rescheduled.
2146 // We can't use RunUntilTime(now) here because the next frame is also
2147 // scheduled if throttle_frame_production = false.
2148 base::TimeTicks before_deadline
= now_src()->Now();
2149 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2150 base::TimeTicks after_deadline
= now_src()->Now();
2151 EXPECT_EQ(after_deadline
, before_deadline
);
2152 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2156 TEST_F(SchedulerTest
, SyntheticBeginFrames_SwapThrottled
) {
2157 bool use_external_begin_frame_source
= false;
2158 bool throttle_frame_production
= true;
2159 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
2160 throttle_frame_production
);
2163 TEST_F(SchedulerTest
, VSyncThrottlingDisabled_SwapThrottled
) {
2164 bool use_external_begin_frame_source
= true;
2165 bool throttle_frame_production
= false;
2166 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
2167 throttle_frame_production
);
2170 TEST_F(SchedulerTest
,
2171 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled
) {
2172 bool use_external_begin_frame_source
= false;
2173 bool throttle_frame_production
= false;
2174 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
2175 throttle_frame_production
);
2178 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized
) {
2179 scheduler_settings_
.use_external_begin_frame_source
= true;
2180 SetUpScheduler(false);
2182 scheduler_
->SetCanStart();
2183 scheduler_
->SetVisible(true);
2184 scheduler_
->SetCanDraw(true);
2186 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
2188 scheduler_
->DidCreateAndInitializeOutputSurface();
2189 EXPECT_NO_ACTION(client_
);
2191 scheduler_
->DidLoseOutputSurface();
2192 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
2195 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterBeginFrameStarted
) {
2196 scheduler_settings_
.use_external_begin_frame_source
= true;
2197 SetUpScheduler(true);
2199 // SetNeedsCommit should begin the frame.
2200 scheduler_
->SetNeedsCommit();
2201 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2204 EXPECT_SCOPED(AdvanceFrame());
2205 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2206 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2207 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2210 scheduler_
->DidLoseOutputSurface();
2211 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2212 EXPECT_NO_ACTION(client_
);
2215 scheduler_
->NotifyBeginMainFrameStarted();
2216 scheduler_
->NotifyReadyToCommit();
2217 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 1);
2220 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2221 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2222 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2223 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2226 void SchedulerTest::DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
2227 bool impl_side_painting
) {
2228 scheduler_settings_
.impl_side_painting
= impl_side_painting
;
2229 scheduler_settings_
.use_external_begin_frame_source
= true;
2230 SetUpScheduler(true);
2232 // SetNeedsCommit should begin the frame.
2233 scheduler_
->SetNeedsCommit();
2234 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2237 EXPECT_SCOPED(AdvanceFrame());
2238 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2239 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2240 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2243 scheduler_
->DidLoseOutputSurface();
2244 // Do nothing when impl frame is in deadine pending state.
2245 EXPECT_NO_ACTION(client_
);
2248 // Run posted deadline.
2249 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2250 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2251 // OnBeginImplFrameDeadline didn't schedule output surface creation because
2252 // main frame is not yet completed.
2253 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
2254 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
2255 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2257 // BeginImplFrame is not started.
2259 task_runner().RunUntilTime(now_src()->Now() +
2260 base::TimeDelta::FromMilliseconds(10));
2261 EXPECT_NO_ACTION(client_
);
2262 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2265 scheduler_
->NotifyBeginMainFrameStarted();
2266 scheduler_
->NotifyReadyToCommit();
2267 if (impl_side_painting
) {
2268 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 3);
2269 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 1, 3);
2270 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 2, 3);
2272 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 2);
2273 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 1, 2);
2277 TEST_F(SchedulerTest
,
2278 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency
) {
2279 bool impl_side_painting
= false;
2280 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
2283 TEST_F(SchedulerTest
,
2284 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint
) {
2285 bool impl_side_painting
= true;
2286 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
2289 void SchedulerTest::DidLoseOutputSurfaceAfterReadyToCommit(
2290 bool impl_side_painting
) {
2291 scheduler_settings_
.impl_side_painting
= impl_side_painting
;
2292 scheduler_settings_
.use_external_begin_frame_source
= true;
2293 SetUpScheduler(true);
2295 // SetNeedsCommit should begin the frame.
2296 scheduler_
->SetNeedsCommit();
2297 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2300 EXPECT_SCOPED(AdvanceFrame());
2301 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2302 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2303 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2306 scheduler_
->NotifyBeginMainFrameStarted();
2307 scheduler_
->NotifyReadyToCommit();
2308 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2311 scheduler_
->DidLoseOutputSurface();
2312 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2313 if (impl_side_painting
) {
2314 // Sync tree should be forced to activate.
2315 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
2317 EXPECT_NO_ACTION(client_
);
2321 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2322 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2323 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2324 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2327 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommit
) {
2328 DidLoseOutputSurfaceAfterReadyToCommit(false);
2331 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting
) {
2332 DidLoseOutputSurfaceAfterReadyToCommit(true);
2335 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles
) {
2336 scheduler_settings_
.use_external_begin_frame_source
= true;
2337 SetUpScheduler(true);
2339 scheduler_
->SetNeedsPrepareTiles();
2340 scheduler_
->SetNeedsRedraw();
2341 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2344 EXPECT_SCOPED(AdvanceFrame());
2345 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2346 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2347 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2350 scheduler_
->DidLoseOutputSurface();
2351 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2352 EXPECT_NO_ACTION(client_
);
2355 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2356 EXPECT_ACTION("ScheduledActionPrepareTiles", client_
, 0, 4);
2357 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 1, 4);
2358 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 2, 4);
2359 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 3, 4);
2362 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterBeginRetroFramePosted
) {
2363 scheduler_settings_
.use_external_begin_frame_source
= true;
2364 SetUpScheduler(true);
2366 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2367 scheduler_
->SetNeedsCommit();
2368 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2370 // Create a BeginFrame with a long deadline to avoid race conditions.
2371 // This is the first BeginFrame, which will be handled immediately.
2373 BeginFrameArgs args
=
2374 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
2375 args
.deadline
+= base::TimeDelta::FromHours(1);
2376 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2377 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2378 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2379 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2380 EXPECT_TRUE(client_
->needs_begin_frames());
2382 // Queue BeginFrames while we are still handling the previous BeginFrame.
2383 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2384 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2385 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2386 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2388 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2390 task_runner().RunPendingTasks(); // Run posted deadline.
2391 EXPECT_NO_ACTION(client_
);
2392 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2393 EXPECT_TRUE(client_
->needs_begin_frames());
2395 // NotifyReadyToCommit should trigger the commit.
2397 scheduler_
->NotifyBeginMainFrameStarted();
2398 scheduler_
->NotifyReadyToCommit();
2399 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2400 EXPECT_TRUE(client_
->needs_begin_frames());
2403 EXPECT_FALSE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2404 scheduler_
->DidLoseOutputSurface();
2405 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2406 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2407 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2408 EXPECT_TRUE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2410 // Posted BeginRetroFrame is aborted.
2412 task_runner().RunPendingTasks();
2413 EXPECT_NO_ACTION(client_
);
2416 TEST_F(SchedulerTest
, DidLoseOutputSurfaceDuringBeginRetroFrameRunning
) {
2417 scheduler_settings_
.use_external_begin_frame_source
= true;
2418 SetUpScheduler(true);
2420 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2421 scheduler_
->SetNeedsCommit();
2422 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2424 // Create a BeginFrame with a long deadline to avoid race conditions.
2425 // This is the first BeginFrame, which will be handled immediately.
2427 BeginFrameArgs args
=
2428 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
2429 args
.deadline
+= base::TimeDelta::FromHours(1);
2430 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2431 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2432 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2433 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2434 EXPECT_TRUE(client_
->needs_begin_frames());
2436 // Queue BeginFrames while we are still handling the previous BeginFrame.
2437 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2438 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2439 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2440 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2442 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2444 task_runner().RunPendingTasks(); // Run posted deadline.
2445 EXPECT_NO_ACTION(client_
);
2446 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2447 EXPECT_TRUE(client_
->needs_begin_frames());
2449 // NotifyReadyToCommit should trigger the commit.
2451 scheduler_
->NotifyBeginMainFrameStarted();
2452 scheduler_
->NotifyReadyToCommit();
2453 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2454 EXPECT_TRUE(client_
->needs_begin_frames());
2456 // BeginImplFrame should prepare the draw.
2458 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2459 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2460 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2461 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2462 EXPECT_TRUE(client_
->needs_begin_frames());
2465 EXPECT_FALSE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2466 scheduler_
->DidLoseOutputSurface();
2467 EXPECT_NO_ACTION(client_
);
2468 EXPECT_TRUE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2470 // BeginImplFrame deadline should abort drawing.
2472 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2473 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2474 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2475 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2476 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2477 EXPECT_FALSE(client_
->needs_begin_frames());
2479 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
2481 task_runner().RunPendingTasks();
2482 EXPECT_NO_ACTION(client_
);
2485 TEST_F(SchedulerTest
, DidLoseOutputSurfaceWithSyntheticBeginFrameSource
) {
2486 SetUpScheduler(true);
2488 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2489 EXPECT_FALSE(scheduler_
->frame_source().NeedsBeginFrames());
2490 scheduler_
->SetNeedsCommit();
2491 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2495 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2496 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2497 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2498 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2500 // NotifyReadyToCommit should trigger the commit.
2502 scheduler_
->NotifyBeginMainFrameStarted();
2503 scheduler_
->NotifyReadyToCommit();
2504 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2505 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2508 scheduler_
->DidLoseOutputSurface();
2509 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2510 EXPECT_NO_ACTION(client_
);
2511 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2514 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2515 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 2);
2516 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
2517 EXPECT_FALSE(scheduler_
->frame_source().NeedsBeginFrames());
2520 TEST_F(SchedulerTest
, DidLoseOutputSurfaceWhenIdle
) {
2521 scheduler_settings_
.use_external_begin_frame_source
= true;
2522 SetUpScheduler(true);
2524 // SetNeedsCommit should begin the frame.
2525 scheduler_
->SetNeedsCommit();
2526 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2529 EXPECT_SCOPED(AdvanceFrame());
2530 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2531 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2532 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2535 scheduler_
->NotifyBeginMainFrameStarted();
2536 scheduler_
->NotifyReadyToCommit();
2537 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2540 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2541 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2542 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2544 // Idle time between BeginFrames.
2546 scheduler_
->DidLoseOutputSurface();
2547 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2548 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2549 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2552 TEST_F(SchedulerTest
, ScheduledActionActivateAfterBecomingInvisible
) {
2553 scheduler_settings_
.impl_side_painting
= true;
2554 scheduler_settings_
.use_external_begin_frame_source
= true;
2555 SetUpScheduler(true);
2557 // SetNeedsCommit should begin the frame.
2558 scheduler_
->SetNeedsCommit();
2559 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2562 EXPECT_SCOPED(AdvanceFrame());
2563 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2564 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2565 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2568 scheduler_
->NotifyBeginMainFrameStarted();
2569 scheduler_
->NotifyReadyToCommit();
2570 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2571 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2574 scheduler_
->SetVisible(false);
2575 task_runner().RunPendingTasks(); // Run posted deadline.
2577 // Sync tree should be forced to activate.
2578 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 0, 3);
2579 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2580 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2583 // Tests to ensure frame sources can be successfully changed while drawing.
2584 TEST_F(SchedulerTest
, SwitchFrameSourceToUnthrottled
) {
2585 scheduler_settings_
.use_external_begin_frame_source
= true;
2586 SetUpScheduler(true);
2588 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2589 scheduler_
->SetNeedsRedraw();
2590 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2593 EXPECT_SCOPED(AdvanceFrame());
2594 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2595 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2596 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2597 EXPECT_TRUE(client_
->needs_begin_frames());
2599 task_runner().RunPendingTasks(); // Run posted deadline.
2600 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2601 scheduler_
->SetNeedsRedraw();
2603 // Switch to an unthrottled frame source.
2604 scheduler_
->SetThrottleFrameProduction(false);
2607 // Unthrottled frame source will immediately begin a new frame.
2608 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2609 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2610 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2611 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2614 // If we don't swap on the deadline, we wait for the next BeginFrame.
2615 task_runner().RunPendingTasks(); // Run posted deadline.
2616 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2617 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2621 // Tests to ensure frame sources can be successfully changed while a frame
2622 // deadline is pending.
2623 TEST_F(SchedulerTest
, SwitchFrameSourceToUnthrottledBeforeDeadline
) {
2624 scheduler_settings_
.use_external_begin_frame_source
= true;
2625 SetUpScheduler(true);
2627 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2628 scheduler_
->SetNeedsRedraw();
2629 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2632 EXPECT_SCOPED(AdvanceFrame());
2633 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2634 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2636 // Switch to an unthrottled frame source before the frame deadline is hit.
2637 scheduler_
->SetThrottleFrameProduction(false);
2640 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2641 EXPECT_TRUE(client_
->needs_begin_frames());
2644 task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame.
2645 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 2);
2646 // Unthrottled frame source will immediately begin a new frame.
2647 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 2);
2648 scheduler_
->SetNeedsRedraw();
2651 task_runner().RunPendingTasks(); // Run posted deadline.
2652 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2653 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2654 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2658 // Tests to ensure that the active frame source can successfully be changed from
2659 // unthrottled to throttled.
2660 TEST_F(SchedulerTest
, SwitchFrameSourceToThrottled
) {
2661 scheduler_settings_
.throttle_frame_production
= false;
2662 scheduler_settings_
.use_external_begin_frame_source
= true;
2663 SetUpScheduler(true);
2665 scheduler_
->SetNeedsRedraw();
2666 EXPECT_NO_ACTION(client_
);
2669 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2670 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2671 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2672 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2675 task_runner().RunPendingTasks(); // Run posted deadline.
2676 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2677 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2680 // Switch to a throttled frame source.
2681 scheduler_
->SetThrottleFrameProduction(true);
2684 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2685 scheduler_
->SetNeedsRedraw();
2686 task_runner().RunPendingTasks();
2687 EXPECT_NO_ACTION(client_
);
2690 EXPECT_SCOPED(AdvanceFrame());
2691 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2692 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2693 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2694 EXPECT_TRUE(client_
->needs_begin_frames());
2696 task_runner().RunPendingTasks(); // Run posted deadline.
2697 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2700 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
2701 TEST_F(SchedulerTest
, SendBeginMainFrameNotExpectedSoon
) {
2702 scheduler_settings_
.use_external_begin_frame_source
= true;
2703 SetUpScheduler(true);
2705 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2706 scheduler_
->SetNeedsCommit();
2707 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2710 // Trigger a frame draw.
2711 EXPECT_SCOPED(AdvanceFrame());
2712 scheduler_
->NotifyBeginMainFrameStarted();
2713 scheduler_
->NotifyReadyToCommit();
2714 task_runner().RunPendingTasks();
2715 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 5);
2716 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 5);
2717 EXPECT_ACTION("ScheduledActionCommit", client_
, 2, 5);
2718 EXPECT_ACTION("ScheduledActionAnimate", client_
, 3, 5);
2719 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 4, 5);
2722 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2723 // and send a SendBeginMainFrameNotExpectedSoon.
2724 EXPECT_SCOPED(AdvanceFrame());
2725 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
2726 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2729 task_runner().RunPendingTasks(); // Run posted deadline.
2730 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
2731 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
2735 TEST_F(SchedulerTest
, SynchronousCompositorAnimation
) {
2736 scheduler_settings_
.using_synchronous_renderer_compositor
= true;
2737 scheduler_settings_
.use_external_begin_frame_source
= true;
2738 scheduler_settings_
.impl_side_painting
= true;
2739 SetUpScheduler(true);
2741 scheduler_
->SetNeedsAnimate();
2742 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2747 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2748 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
2749 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
2750 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2753 // Continue with animation.
2754 scheduler_
->SetNeedsAnimate();
2755 EXPECT_NO_ACTION(client_
);
2758 scheduler_
->SetNeedsRedraw();
2759 scheduler_
->OnDrawForOutputSurface();
2760 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
2761 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2766 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2767 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
2768 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
2769 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2773 scheduler_
->SetNeedsRedraw();
2774 scheduler_
->OnDrawForOutputSurface();
2775 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
2776 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2779 // Idle on next vsync.
2781 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2782 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2783 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2784 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2788 TEST_F(SchedulerTest
, SynchronousCompositorOnDrawDuringIdle
) {
2789 scheduler_settings_
.using_synchronous_renderer_compositor
= true;
2790 scheduler_settings_
.use_external_begin_frame_source
= true;
2791 scheduler_settings_
.impl_side_painting
= true;
2792 SetUpScheduler(true);
2794 scheduler_
->SetNeedsRedraw();
2795 scheduler_
->OnDrawForOutputSurface();
2796 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_
, 0, 3);
2797 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
2798 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 2, 3);
2799 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2802 // Idle on next vsync.
2804 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2805 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2806 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2807 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2811 TEST_F(SchedulerTest
, SynchronousCompositorCommit
) {
2812 scheduler_settings_
.using_synchronous_renderer_compositor
= true;
2813 scheduler_settings_
.use_external_begin_frame_source
= true;
2814 scheduler_settings_
.impl_side_painting
= true;
2815 SetUpScheduler(true);
2817 scheduler_
->SetNeedsCommit();
2818 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2823 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2824 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2825 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2828 scheduler_
->NotifyBeginMainFrameStarted();
2829 EXPECT_NO_ACTION(client_
);
2833 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
2834 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2837 scheduler_
->NotifyReadyToCommit();
2838 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2841 scheduler_
->NotifyReadyToActivate();
2842 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
2847 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2848 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
2849 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
2850 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2854 scheduler_
->SetNeedsRedraw();
2855 scheduler_
->OnDrawForOutputSurface();
2856 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
2857 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2860 // Idle on next vsync.
2862 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
2863 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2864 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2865 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2869 TEST_F(SchedulerTest
, SynchronousCompositorDoubleCommitWithoutDraw
) {
2870 scheduler_settings_
.using_synchronous_renderer_compositor
= true;
2871 scheduler_settings_
.use_external_begin_frame_source
= true;
2872 scheduler_settings_
.impl_side_painting
= true;
2873 SetUpScheduler(true);
2875 scheduler_
->SetNeedsCommit();
2876 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2881 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2882 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2883 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2886 scheduler_
->NotifyBeginMainFrameStarted();
2887 EXPECT_NO_ACTION(client_
);
2889 scheduler_
->NotifyReadyToCommit();
2890 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2893 scheduler_
->NotifyReadyToActivate();
2894 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
2897 // Ask for another commit.
2898 scheduler_
->SetNeedsCommit();
2901 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 4);
2902 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 4);
2903 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 2, 4);
2904 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 3, 4);
2905 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2908 scheduler_
->NotifyBeginMainFrameStarted();
2909 EXPECT_NO_ACTION(client_
);
2911 // Allow new commit even though previous commit hasn't been drawn.
2912 scheduler_
->NotifyReadyToCommit();
2913 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2917 TEST_F(SchedulerTest
, AuthoritativeVSyncInterval
) {
2918 SetUpScheduler(true);
2919 base::TimeDelta initial_interval
= scheduler_
->BeginImplFrameInterval();
2920 base::TimeDelta authoritative_interval
=
2921 base::TimeDelta::FromMilliseconds(33);
2923 scheduler_
->SetNeedsCommit();
2924 EXPECT_SCOPED(AdvanceFrame());
2926 EXPECT_EQ(initial_interval
, scheduler_
->BeginImplFrameInterval());
2928 scheduler_
->NotifyBeginMainFrameStarted();
2929 scheduler_
->NotifyReadyToCommit();
2930 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2932 scheduler_
->SetAuthoritativeVSyncInterval(authoritative_interval
);
2934 EXPECT_SCOPED(AdvanceFrame());
2936 // At the next BeginFrame, authoritative interval is used instead of previous
2938 EXPECT_NE(initial_interval
, scheduler_
->BeginImplFrameInterval());
2939 EXPECT_EQ(authoritative_interval
, scheduler_
->BeginImplFrameInterval());