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/numerics/safe_conversions.h"
14 #include "base/run_loop.h"
15 #include "base/time/time.h"
16 #include "base/trace_event/trace_event.h"
17 #include "cc/test/begin_frame_args_test.h"
18 #include "cc/test/ordered_simple_task_runner.h"
19 #include "cc/test/scheduler_test_common.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
25 EXPECT_EQ(expected_num_actions, client->num_actions_()); \
26 if (action_index >= 0) { \
27 ASSERT_LT(action_index, client->num_actions_()) << scheduler_.get(); \
28 EXPECT_STREQ(action, client->Action(action_index)); \
30 for (int i = expected_num_actions; i < client->num_actions_(); ++i) \
31 ADD_FAILURE() << "Unexpected action: " << client->Action(i) \
32 << " with state:\n" << client->StateForAction(i); \
35 #define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0)
37 #define EXPECT_SINGLE_ACTION(action, client) \
38 EXPECT_ACTION(action, client, 0, 1)
40 #define EXPECT_SCOPED(statements) \
49 class FakeSchedulerClient
: public SchedulerClient
{
52 : automatic_swap_ack_(true),
60 draw_will_happen_
= true;
61 swap_will_happen_if_draw_happens_
= true;
63 begin_frame_args_sent_to_children_
= BeginFrameArgs();
66 void set_scheduler(TestScheduler
* scheduler
) { scheduler_
= scheduler
; }
68 bool needs_begin_frames() {
69 return scheduler_
->frame_source().NeedsBeginFrames();
71 int num_draws() const { return num_draws_
; }
72 int num_actions_() const { return static_cast<int>(actions_
.size()); }
73 const char* Action(int i
) const { return actions_
[i
]; }
74 std::string
StateForAction(int i
) const { return states_
[i
]->ToString(); }
75 base::TimeTicks
posted_begin_impl_frame_deadline() const {
76 return posted_begin_impl_frame_deadline_
;
79 int ActionIndex(const char* action
) const {
80 for (size_t i
= 0; i
< actions_
.size(); i
++)
81 if (!strcmp(actions_
[i
], action
))
82 return base::checked_cast
<int>(i
);
86 bool HasAction(const char* action
) const {
87 return ActionIndex(action
) >= 0;
90 void SetDrawWillHappen(bool draw_will_happen
) {
91 draw_will_happen_
= draw_will_happen
;
93 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens
) {
94 swap_will_happen_if_draw_happens_
= swap_will_happen_if_draw_happens
;
96 void SetAutomaticSwapAck(bool automatic_swap_ack
) {
97 automatic_swap_ack_
= automatic_swap_ack
;
99 // SchedulerClient implementation.
100 void WillBeginImplFrame(const BeginFrameArgs
& args
) override
{
101 PushAction("WillBeginImplFrame");
103 void DidFinishImplFrame() override
{}
105 void ScheduledActionSendBeginMainFrame() override
{
106 PushAction("ScheduledActionSendBeginMainFrame");
108 void ScheduledActionAnimate() override
{
109 PushAction("ScheduledActionAnimate");
111 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
112 PushAction("ScheduledActionDrawAndSwapIfPossible");
115 draw_will_happen_
? DRAW_SUCCESS
: DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
;
116 bool swap_will_happen
=
117 draw_will_happen_
&& swap_will_happen_if_draw_happens_
;
118 if (swap_will_happen
) {
119 scheduler_
->DidSwapBuffers();
121 if (automatic_swap_ack_
)
122 scheduler_
->DidSwapBuffersComplete();
126 DrawResult
ScheduledActionDrawAndSwapForced() override
{
127 PushAction("ScheduledActionDrawAndSwapForced");
130 void ScheduledActionCommit() override
{
131 PushAction("ScheduledActionCommit");
132 scheduler_
->DidCommit();
134 void ScheduledActionActivateSyncTree() override
{
135 PushAction("ScheduledActionActivateSyncTree");
137 void ScheduledActionBeginOutputSurfaceCreation() override
{
138 PushAction("ScheduledActionBeginOutputSurfaceCreation");
140 void ScheduledActionPrepareTiles() override
{
141 PushAction("ScheduledActionPrepareTiles");
142 scheduler_
->WillPrepareTiles();
143 scheduler_
->DidPrepareTiles();
145 void ScheduledActionInvalidateOutputSurface() override
{
146 actions_
.push_back("ScheduledActionInvalidateOutputSurface");
147 states_
.push_back(scheduler_
->AsValue());
150 void SendBeginFramesToChildren(const BeginFrameArgs
& args
) override
{
151 begin_frame_args_sent_to_children_
= args
;
154 void SendBeginMainFrameNotExpectedSoon() override
{
155 PushAction("SendBeginMainFrameNotExpectedSoon");
158 base::Callback
<bool(void)> ImplFrameDeadlinePending(bool state
) {
159 return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback
,
160 base::Unretained(this),
164 bool begin_frame_is_sent_to_children() const {
165 return begin_frame_args_sent_to_children_
.IsValid();
168 const BeginFrameArgs
& begin_frame_args_sent_to_children() const {
169 return begin_frame_args_sent_to_children_
;
172 void PushAction(const char* description
) {
173 actions_
.push_back(description
);
174 states_
.push_back(scheduler_
->AsValue());
178 bool ImplFrameDeadlinePendingCallback(bool state
) {
179 return scheduler_
->BeginImplFrameDeadlinePending() == state
;
182 bool draw_will_happen_
;
183 bool swap_will_happen_if_draw_happens_
;
184 bool automatic_swap_ack_
;
186 BeginFrameArgs begin_frame_args_sent_to_children_
;
187 base::TimeTicks posted_begin_impl_frame_deadline_
;
188 std::vector
<const char*> actions_
;
189 std::vector
<scoped_refptr
<base::trace_event::ConvertableToTraceFormat
>>
191 TestScheduler
* scheduler_
;
194 class FakeExternalBeginFrameSource
: public BeginFrameSourceBase
{
196 explicit FakeExternalBeginFrameSource(FakeSchedulerClient
* client
)
198 ~FakeExternalBeginFrameSource() override
{}
200 void OnNeedsBeginFramesChange(bool needs_begin_frames
) override
{
201 if (needs_begin_frames
) {
202 client_
->PushAction("SetNeedsBeginFrames(true)");
204 client_
->PushAction("SetNeedsBeginFrames(false)");
208 void TestOnBeginFrame(const BeginFrameArgs
& args
) {
209 return CallOnBeginFrame(args
);
213 FakeSchedulerClient
* client_
;
216 class SchedulerTest
: public testing::Test
{
219 : now_src_(new base::SimpleTestTickClock()),
220 task_runner_(new OrderedSimpleTaskRunner(now_src_
.get(), true)),
221 fake_external_begin_frame_source_(nullptr) {
222 now_src_
->Advance(base::TimeDelta::FromMicroseconds(10000));
223 // A bunch of tests require NowTicks()
224 // to be > BeginFrameArgs::DefaultInterval()
225 now_src_
->Advance(base::TimeDelta::FromMilliseconds(100));
226 // Fail if we need to run 100 tasks in a row.
227 task_runner_
->SetRunTaskLimit(100);
230 ~SchedulerTest() override
{}
233 TestScheduler
* CreateScheduler() {
234 if (scheduler_settings_
.use_external_begin_frame_source
) {
235 fake_external_begin_frame_source_
.reset(
236 new FakeExternalBeginFrameSource(client_
.get()));
239 scoped_ptr
<FakeCompositorTimingHistory
> fake_compositor_timing_history
=
240 FakeCompositorTimingHistory::Create();
241 fake_compositor_timing_history_
= fake_compositor_timing_history
.get();
243 scheduler_
= TestScheduler::Create(
244 now_src_
.get(), client_
.get(), scheduler_settings_
, 0,
245 task_runner_
.get(), fake_external_begin_frame_source_
.get(),
246 fake_compositor_timing_history
.Pass());
248 client_
->set_scheduler(scheduler_
.get());
250 // Use large estimates by default to avoid latency recovery
252 base::TimeDelta slow_duration
= base::TimeDelta::FromSeconds(1);
253 fake_compositor_timing_history_
->SetAllEstimatesTo(slow_duration
);
255 return scheduler_
.get();
258 void CreateSchedulerAndInitSurface() {
260 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit());
263 void SetUpScheduler(bool initSurface
) {
264 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient
), initSurface
);
267 void SetUpScheduler(scoped_ptr
<FakeSchedulerClient
> client
,
269 client_
= client
.Pass();
271 CreateSchedulerAndInitSurface();
276 OrderedSimpleTaskRunner
& task_runner() { return *task_runner_
; }
277 base::SimpleTestTickClock
* now_src() { return now_src_
.get(); }
279 // As this function contains EXPECT macros, to allow debugging it should be
280 // called inside EXPECT_SCOPED like so;
281 // EXPECT_SCOPED(client.InitializeOutputSurfaceAndFirstCommit(scheduler));
282 void InitializeOutputSurfaceAndFirstCommit() {
284 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit");
287 // Check the client doesn't have any actions queued when calling this
289 EXPECT_NO_ACTION(client_
);
290 EXPECT_FALSE(client_
->needs_begin_frames());
292 // Start the initial output surface creation.
293 EXPECT_FALSE(scheduler_
->CanStart());
294 scheduler_
->SetCanStart();
295 scheduler_
->SetVisible(true);
296 scheduler_
->SetCanDraw(true);
297 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
301 // We don't see anything happening until the first impl frame.
302 scheduler_
->DidCreateAndInitializeOutputSurface();
303 scheduler_
->SetNeedsCommit();
304 EXPECT_TRUE(client_
->needs_begin_frames());
305 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
309 SCOPED_TRACE("Do first frame to commit after initialize.");
312 scheduler_
->NotifyBeginMainFrameStarted();
313 scheduler_
->NotifyReadyToCommit();
314 scheduler_
->NotifyReadyToActivate();
316 EXPECT_FALSE(scheduler_
->CommitPending());
318 if (scheduler_settings_
.using_synchronous_renderer_compositor
) {
319 scheduler_
->SetNeedsRedraw();
320 scheduler_
->OnDrawForOutputSurface();
322 // Run the posted deadline task.
323 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
324 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
327 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
334 "Run second frame so Scheduler calls SetNeedsBeginFrame(false).");
337 if (!scheduler_settings_
.using_synchronous_renderer_compositor
) {
338 // Run the posted deadline task.
339 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
340 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
343 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
346 EXPECT_FALSE(client_
->needs_begin_frames());
350 // As this function contains EXPECT macros, to allow debugging it should be
351 // called inside EXPECT_SCOPED like so;
352 // EXPECT_SCOPED(client.AdvanceFrame());
353 void AdvanceFrame() {
354 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
355 "FakeSchedulerClient::AdvanceFrame");
356 // Consume any previous deadline first, if no deadline is currently
357 // pending, ImplFrameDeadlinePending will return false straight away and we
358 // will run no tasks.
359 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
360 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
362 // Send the next BeginFrame message if using an external source, otherwise
363 // it will be already in the task queue.
364 if (scheduler_
->settings().use_external_begin_frame_source
&&
365 scheduler_
->FrameProductionThrottled()) {
366 EXPECT_TRUE(client_
->needs_begin_frames());
367 SendNextBeginFrame();
370 if (!scheduler_
->settings().using_synchronous_renderer_compositor
) {
371 // Then run tasks until new deadline is scheduled.
372 EXPECT_TRUE(task_runner_
->RunTasksWhile(
373 client_
->ImplFrameDeadlinePending(false)));
374 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
378 BeginFrameArgs
SendNextBeginFrame() {
379 DCHECK(scheduler_
->settings().use_external_begin_frame_source
);
380 // Creep the time forward so that any BeginFrameArgs is not equal to the
381 // last one otherwise we violate the BeginFrameSource contract.
382 now_src_
->Advance(BeginFrameArgs::DefaultInterval());
383 BeginFrameArgs args
=
384 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
385 fake_external_begin_frame_source_
->TestOnBeginFrame(args
);
389 FakeExternalBeginFrameSource
* fake_external_begin_frame_source() const {
390 return fake_external_begin_frame_source_
.get();
393 void CheckMainFrameSkippedAfterLateCommit(bool expect_send_begin_main_frame
);
394 void ImplFrameSkippedAfterLateSwapAck(bool swap_ack_before_deadline
);
395 void ImplFrameIsNotSkippedAfterLateSwapAck();
396 void BeginFramesNotFromClient(bool use_external_begin_frame_source
,
397 bool throttle_frame_production
);
398 void BeginFramesNotFromClient_SwapThrottled(
399 bool use_external_begin_frame_source
,
400 bool throttle_frame_production
);
402 scoped_ptr
<base::SimpleTestTickClock
> now_src_
;
403 scoped_refptr
<OrderedSimpleTaskRunner
> task_runner_
;
404 scoped_ptr
<FakeExternalBeginFrameSource
> fake_external_begin_frame_source_
;
405 SchedulerSettings scheduler_settings_
;
406 scoped_ptr
<FakeSchedulerClient
> client_
;
407 scoped_ptr
<TestScheduler
> scheduler_
;
408 FakeCompositorTimingHistory
* fake_compositor_timing_history_
;
411 TEST_F(SchedulerTest
, InitializeOutputSurfaceDoesNotBeginImplFrame
) {
412 scheduler_settings_
.use_external_begin_frame_source
= true;
413 SetUpScheduler(false);
414 scheduler_
->SetCanStart();
415 scheduler_
->SetVisible(true);
416 scheduler_
->SetCanDraw(true);
418 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
420 scheduler_
->DidCreateAndInitializeOutputSurface();
421 EXPECT_NO_ACTION(client_
);
424 TEST_F(SchedulerTest
, SendBeginFramesToChildren
) {
425 scheduler_settings_
.use_external_begin_frame_source
= true;
426 SetUpScheduler(true);
428 EXPECT_FALSE(client_
->begin_frame_is_sent_to_children());
429 scheduler_
->SetNeedsCommit();
430 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
431 EXPECT_TRUE(client_
->needs_begin_frames());
433 scheduler_
->SetChildrenNeedBeginFrames(true);
436 EXPECT_SCOPED(AdvanceFrame());
437 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
438 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
439 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
440 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
441 EXPECT_TRUE(client_
->needs_begin_frames());
444 TEST_F(SchedulerTest
, SendBeginFramesToChildrenWithoutCommit
) {
445 scheduler_settings_
.use_external_begin_frame_source
= true;
446 SetUpScheduler(true);
448 EXPECT_FALSE(client_
->needs_begin_frames());
449 scheduler_
->SetChildrenNeedBeginFrames(true);
450 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
451 EXPECT_TRUE(client_
->needs_begin_frames());
454 EXPECT_SCOPED(AdvanceFrame());
455 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
458 TEST_F(SchedulerTest
, SendBeginFramesToChildrenDeadlineNotAdjusted
) {
459 // Set up client with specified estimates.
460 scheduler_settings_
.use_external_begin_frame_source
= true;
461 SetUpScheduler(true);
463 fake_compositor_timing_history_
->SetBeginMainFrameToCommitDurationEstimate(
464 base::TimeDelta::FromMilliseconds(2));
465 fake_compositor_timing_history_
->SetCommitToReadyToActivateDurationEstimate(
466 base::TimeDelta::FromMilliseconds(4));
467 fake_compositor_timing_history_
->SetDrawDurationEstimate(
468 base::TimeDelta::FromMilliseconds(1));
470 EXPECT_FALSE(client_
->needs_begin_frames());
471 scheduler_
->SetChildrenNeedBeginFrames(true);
472 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
473 EXPECT_TRUE(client_
->needs_begin_frames());
477 BeginFrameArgs frame_args
=
478 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
479 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args
);
481 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
482 EXPECT_EQ(client_
->begin_frame_args_sent_to_children().deadline
,
483 frame_args
.deadline
);
486 TEST_F(SchedulerTest
, VideoNeedsBeginFrames
) {
487 scheduler_settings_
.use_external_begin_frame_source
= true;
488 SetUpScheduler(true);
490 scheduler_
->SetVideoNeedsBeginFrames(true);
491 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
492 EXPECT_TRUE(client_
->needs_begin_frames());
495 EXPECT_SCOPED(AdvanceFrame());
496 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
497 // WillBeginImplFrame is responsible for sending BeginFrames to video.
498 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
501 EXPECT_SCOPED(AdvanceFrame());
502 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
503 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
506 scheduler_
->SetVideoNeedsBeginFrames(false);
507 EXPECT_NO_ACTION(client_
);
510 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
511 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
512 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
513 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
514 EXPECT_FALSE(client_
->needs_begin_frames());
517 TEST_F(SchedulerTest
, RequestCommit
) {
518 scheduler_settings_
.use_external_begin_frame_source
= true;
519 SetUpScheduler(true);
521 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
522 scheduler_
->SetNeedsCommit();
523 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
526 EXPECT_SCOPED(AdvanceFrame());
527 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
528 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
529 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
530 EXPECT_TRUE(client_
->needs_begin_frames());
533 // If we don't swap on the deadline, we wait for the next BeginFrame.
534 task_runner().RunPendingTasks(); // Run posted deadline.
535 EXPECT_NO_ACTION(client_
);
536 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
537 EXPECT_TRUE(client_
->needs_begin_frames());
540 // NotifyReadyToCommit should trigger the commit.
541 scheduler_
->NotifyBeginMainFrameStarted();
542 scheduler_
->NotifyReadyToCommit();
543 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
544 EXPECT_TRUE(client_
->needs_begin_frames());
547 // NotifyReadyToActivate should trigger the activation.
548 scheduler_
->NotifyReadyToActivate();
549 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
550 EXPECT_TRUE(client_
->needs_begin_frames());
553 // BeginImplFrame should prepare the draw.
554 EXPECT_SCOPED(AdvanceFrame());
555 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
556 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
557 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
558 EXPECT_TRUE(client_
->needs_begin_frames());
561 // BeginImplFrame deadline should draw.
562 task_runner().RunPendingTasks(); // Run posted deadline.
563 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
564 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
565 EXPECT_TRUE(client_
->needs_begin_frames());
568 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
569 // to avoid excessive toggles.
570 EXPECT_SCOPED(AdvanceFrame());
571 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
572 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
575 task_runner().RunPendingTasks(); // Run posted deadline.
576 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
577 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
581 TEST_F(SchedulerTest
, RequestCommitAfterSetDeferCommit
) {
582 scheduler_settings_
.use_external_begin_frame_source
= true;
583 SetUpScheduler(true);
585 scheduler_
->SetDeferCommits(true);
587 scheduler_
->SetNeedsCommit();
588 EXPECT_NO_ACTION(client_
);
591 task_runner().RunPendingTasks();
592 // There are no pending tasks or actions.
593 EXPECT_NO_ACTION(client_
);
594 EXPECT_FALSE(client_
->needs_begin_frames());
597 scheduler_
->SetDeferCommits(false);
598 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
600 // Start new BeginMainFrame after defer commit is off.
602 EXPECT_SCOPED(AdvanceFrame());
603 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
604 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
605 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
608 TEST_F(SchedulerTest
, DeferCommitWithRedraw
) {
609 scheduler_settings_
.use_external_begin_frame_source
= true;
610 SetUpScheduler(true);
612 scheduler_
->SetDeferCommits(true);
614 scheduler_
->SetNeedsCommit();
615 EXPECT_NO_ACTION(client_
);
617 // The SetNeedsRedraw will override the SetDeferCommits(true), to allow a
618 // begin frame to be needed.
620 scheduler_
->SetNeedsRedraw();
621 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
625 // BeginMainFrame is not sent during the defer commit is on.
626 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
627 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
630 task_runner().RunPendingTasks(); // Run posted deadline.
631 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
632 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
633 EXPECT_TRUE(client_
->needs_begin_frames());
637 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
640 TEST_F(SchedulerTest
, RequestCommitAfterBeginMainFrameSent
) {
641 scheduler_settings_
.use_external_begin_frame_source
= true;
642 SetUpScheduler(true);
644 // SetNeedsCommit should begin the frame.
645 scheduler_
->SetNeedsCommit();
646 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
649 EXPECT_SCOPED(AdvanceFrame());
650 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
651 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
652 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
654 EXPECT_TRUE(client_
->needs_begin_frames());
657 // Now SetNeedsCommit again. Calling here means we need a second commit.
658 scheduler_
->SetNeedsCommit();
659 EXPECT_EQ(client_
->num_actions_(), 0);
662 // Finish the first commit.
663 scheduler_
->NotifyBeginMainFrameStarted();
664 scheduler_
->NotifyReadyToCommit();
665 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
666 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
670 scheduler_
->NotifyReadyToActivate();
671 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
672 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
675 task_runner().RunPendingTasks(); // Run posted deadline.
676 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
677 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
678 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
680 // Because we just swapped, the Scheduler should also request the next
681 // BeginImplFrame from the OutputSurface.
682 EXPECT_TRUE(client_
->needs_begin_frames());
684 // Since another commit is needed, the next BeginImplFrame should initiate
685 // the second commit.
686 EXPECT_SCOPED(AdvanceFrame());
687 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
688 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
689 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
692 // Finishing the commit before the deadline should post a new deadline task
693 // to trigger the deadline early.
694 scheduler_
->NotifyBeginMainFrameStarted();
695 scheduler_
->NotifyReadyToCommit();
696 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
697 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
699 scheduler_
->NotifyReadyToActivate();
700 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
701 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
703 task_runner().RunPendingTasks(); // Run posted deadline.
704 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
705 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
706 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
707 EXPECT_TRUE(client_
->needs_begin_frames());
710 // On the next BeginImplFrame, verify we go back to a quiescent state and
711 // no longer request BeginImplFrames.
712 EXPECT_SCOPED(AdvanceFrame());
713 task_runner().RunPendingTasks(); // Run posted deadline.
714 EXPECT_FALSE(client_
->needs_begin_frames());
718 class SchedulerClientThatsetNeedsDrawInsideDraw
: public FakeSchedulerClient
{
720 SchedulerClientThatsetNeedsDrawInsideDraw()
721 : FakeSchedulerClient(), request_redraws_(false) {}
723 void SetRequestRedrawsInsideDraw(bool enable
) { request_redraws_
= enable
; }
725 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
726 // Only SetNeedsRedraw the first time this is called
727 if (request_redraws_
) {
728 scheduler_
->SetNeedsRedraw();
730 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
733 DrawResult
ScheduledActionDrawAndSwapForced() override
{
739 bool request_redraws_
;
742 // Tests for two different situations:
743 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
744 // a ScheduledActionDrawAndSwap
745 // 2. the scheduler drawing twice inside a single tick
746 TEST_F(SchedulerTest
, RequestRedrawInsideDraw
) {
747 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
748 new SchedulerClientThatsetNeedsDrawInsideDraw
;
749 scheduler_settings_
.use_external_begin_frame_source
= true;
750 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
751 client
->SetRequestRedrawsInsideDraw(true);
753 scheduler_
->SetNeedsRedraw();
754 EXPECT_TRUE(scheduler_
->RedrawPending());
755 EXPECT_TRUE(client
->needs_begin_frames());
756 EXPECT_EQ(0, client
->num_draws());
758 EXPECT_SCOPED(AdvanceFrame());
759 task_runner().RunPendingTasks(); // Run posted deadline.
760 EXPECT_EQ(1, client
->num_draws());
761 EXPECT_TRUE(scheduler_
->RedrawPending());
762 EXPECT_TRUE(client
->needs_begin_frames());
764 client
->SetRequestRedrawsInsideDraw(false);
766 EXPECT_SCOPED(AdvanceFrame());
767 task_runner().RunPendingTasks(); // Run posted deadline.
768 EXPECT_EQ(2, client_
->num_draws());
769 EXPECT_FALSE(scheduler_
->RedrawPending());
770 EXPECT_TRUE(client
->needs_begin_frames());
772 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
774 EXPECT_SCOPED(AdvanceFrame());
775 task_runner().RunPendingTasks(); // Run posted deadline.
776 EXPECT_EQ(2, client
->num_draws());
777 EXPECT_FALSE(scheduler_
->RedrawPending());
778 EXPECT_FALSE(client
->needs_begin_frames());
781 // Test that requesting redraw inside a failed draw doesn't lose the request.
782 TEST_F(SchedulerTest
, RequestRedrawInsideFailedDraw
) {
783 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
784 new SchedulerClientThatsetNeedsDrawInsideDraw
;
785 scheduler_settings_
.use_external_begin_frame_source
= true;
786 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
788 client
->SetRequestRedrawsInsideDraw(true);
789 client
->SetDrawWillHappen(false);
791 scheduler_
->SetNeedsRedraw();
792 EXPECT_TRUE(scheduler_
->RedrawPending());
793 EXPECT_TRUE(client
->needs_begin_frames());
794 EXPECT_EQ(0, client
->num_draws());
797 EXPECT_SCOPED(AdvanceFrame());
798 task_runner().RunPendingTasks(); // Run posted deadline.
799 EXPECT_EQ(1, client
->num_draws());
801 // We have a commit pending and the draw failed, and we didn't lose the redraw
803 EXPECT_TRUE(scheduler_
->CommitPending());
804 EXPECT_TRUE(scheduler_
->RedrawPending());
805 EXPECT_TRUE(client
->needs_begin_frames());
807 client
->SetRequestRedrawsInsideDraw(false);
809 // Fail the draw again.
810 EXPECT_SCOPED(AdvanceFrame());
811 task_runner().RunPendingTasks(); // Run posted deadline.
812 EXPECT_EQ(2, client
->num_draws());
813 EXPECT_TRUE(scheduler_
->CommitPending());
814 EXPECT_TRUE(scheduler_
->RedrawPending());
815 EXPECT_TRUE(client
->needs_begin_frames());
817 // Draw successfully.
818 client
->SetDrawWillHappen(true);
819 EXPECT_SCOPED(AdvanceFrame());
820 task_runner().RunPendingTasks(); // Run posted deadline.
821 EXPECT_EQ(3, client
->num_draws());
822 EXPECT_TRUE(scheduler_
->CommitPending());
823 EXPECT_FALSE(scheduler_
->RedrawPending());
824 EXPECT_TRUE(client
->needs_begin_frames());
827 class SchedulerClientThatSetNeedsCommitInsideDraw
: public FakeSchedulerClient
{
829 SchedulerClientThatSetNeedsCommitInsideDraw()
830 : set_needs_commit_on_next_draw_(false) {}
832 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
833 // Only SetNeedsCommit the first time this is called
834 if (set_needs_commit_on_next_draw_
) {
835 scheduler_
->SetNeedsCommit();
836 set_needs_commit_on_next_draw_
= false;
838 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
841 DrawResult
ScheduledActionDrawAndSwapForced() override
{
846 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_
= true; }
849 bool set_needs_commit_on_next_draw_
;
852 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
853 // happen inside a ScheduledActionDrawAndSwap
854 TEST_F(SchedulerTest
, RequestCommitInsideDraw
) {
855 SchedulerClientThatSetNeedsCommitInsideDraw
* client
=
856 new SchedulerClientThatSetNeedsCommitInsideDraw
;
858 scheduler_settings_
.use_external_begin_frame_source
= true;
859 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
861 EXPECT_FALSE(client
->needs_begin_frames());
862 scheduler_
->SetNeedsRedraw();
863 EXPECT_TRUE(scheduler_
->RedrawPending());
864 EXPECT_EQ(0, client
->num_draws());
865 EXPECT_TRUE(client
->needs_begin_frames());
867 client
->SetNeedsCommitOnNextDraw();
868 EXPECT_SCOPED(AdvanceFrame());
869 client
->SetNeedsCommitOnNextDraw();
870 task_runner().RunPendingTasks(); // Run posted deadline.
871 EXPECT_EQ(1, client
->num_draws());
872 EXPECT_TRUE(scheduler_
->CommitPending());
873 EXPECT_TRUE(client
->needs_begin_frames());
874 scheduler_
->NotifyBeginMainFrameStarted();
875 scheduler_
->NotifyReadyToCommit();
876 scheduler_
->NotifyReadyToActivate();
878 EXPECT_SCOPED(AdvanceFrame());
879 task_runner().RunPendingTasks(); // Run posted deadline.
880 EXPECT_EQ(2, client
->num_draws());
882 EXPECT_FALSE(scheduler_
->RedrawPending());
883 EXPECT_FALSE(scheduler_
->CommitPending());
884 EXPECT_TRUE(client
->needs_begin_frames());
886 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
888 EXPECT_SCOPED(AdvanceFrame());
889 task_runner().RunPendingTasks(); // Run posted deadline.
890 EXPECT_EQ(2, client
->num_draws());
891 EXPECT_FALSE(scheduler_
->RedrawPending());
892 EXPECT_FALSE(scheduler_
->CommitPending());
893 EXPECT_FALSE(client
->needs_begin_frames());
896 // Tests that when a draw fails then the pending commit should not be dropped.
897 TEST_F(SchedulerTest
, RequestCommitInsideFailedDraw
) {
898 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
899 new SchedulerClientThatsetNeedsDrawInsideDraw
;
900 scheduler_settings_
.use_external_begin_frame_source
= true;
901 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
903 client
->SetDrawWillHappen(false);
905 scheduler_
->SetNeedsRedraw();
906 EXPECT_TRUE(scheduler_
->RedrawPending());
907 EXPECT_TRUE(client
->needs_begin_frames());
908 EXPECT_EQ(0, client
->num_draws());
911 EXPECT_SCOPED(AdvanceFrame());
912 task_runner().RunPendingTasks(); // Run posted deadline.
913 EXPECT_EQ(1, client
->num_draws());
915 // We have a commit pending and the draw failed, and we didn't lose the commit
917 EXPECT_TRUE(scheduler_
->CommitPending());
918 EXPECT_TRUE(scheduler_
->RedrawPending());
919 EXPECT_TRUE(client
->needs_begin_frames());
921 // Fail the draw again.
922 EXPECT_SCOPED(AdvanceFrame());
924 task_runner().RunPendingTasks(); // Run posted deadline.
925 EXPECT_EQ(2, client
->num_draws());
926 EXPECT_TRUE(scheduler_
->CommitPending());
927 EXPECT_TRUE(scheduler_
->RedrawPending());
928 EXPECT_TRUE(client
->needs_begin_frames());
930 // Draw successfully.
931 client
->SetDrawWillHappen(true);
932 EXPECT_SCOPED(AdvanceFrame());
933 task_runner().RunPendingTasks(); // Run posted deadline.
934 EXPECT_EQ(3, client
->num_draws());
935 EXPECT_TRUE(scheduler_
->CommitPending());
936 EXPECT_FALSE(scheduler_
->RedrawPending());
937 EXPECT_TRUE(client
->needs_begin_frames());
940 TEST_F(SchedulerTest
, NoSwapWhenDrawFails
) {
941 SchedulerClientThatSetNeedsCommitInsideDraw
* client
=
942 new SchedulerClientThatSetNeedsCommitInsideDraw
;
943 scheduler_settings_
.use_external_begin_frame_source
= true;
944 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
946 scheduler_
->SetNeedsRedraw();
947 EXPECT_TRUE(scheduler_
->RedrawPending());
948 EXPECT_TRUE(client
->needs_begin_frames());
949 EXPECT_EQ(0, client
->num_draws());
951 // Draw successfully, this starts a new frame.
952 client
->SetNeedsCommitOnNextDraw();
953 EXPECT_SCOPED(AdvanceFrame());
954 task_runner().RunPendingTasks(); // Run posted deadline.
955 EXPECT_EQ(1, client
->num_draws());
957 scheduler_
->SetNeedsRedraw();
958 EXPECT_TRUE(scheduler_
->RedrawPending());
959 EXPECT_TRUE(client
->needs_begin_frames());
961 // Fail to draw, this should not start a frame.
962 client
->SetDrawWillHappen(false);
963 client
->SetNeedsCommitOnNextDraw();
964 EXPECT_SCOPED(AdvanceFrame());
965 task_runner().RunPendingTasks(); // Run posted deadline.
966 EXPECT_EQ(2, client
->num_draws());
969 class SchedulerClientNeedsPrepareTilesInDraw
: public FakeSchedulerClient
{
971 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
972 scheduler_
->SetNeedsPrepareTiles();
973 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
977 // Test prepare tiles is independant of draws.
978 TEST_F(SchedulerTest
, PrepareTiles
) {
979 SchedulerClientNeedsPrepareTilesInDraw
* client
=
980 new SchedulerClientNeedsPrepareTilesInDraw
;
981 scheduler_settings_
.use_external_begin_frame_source
= true;
982 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
984 // Request both draw and prepare tiles. PrepareTiles shouldn't
985 // be trigged until BeginImplFrame.
987 scheduler_
->SetNeedsPrepareTiles();
988 scheduler_
->SetNeedsRedraw();
989 EXPECT_TRUE(scheduler_
->RedrawPending());
990 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
991 EXPECT_TRUE(client
->needs_begin_frames());
992 EXPECT_EQ(0, client
->num_draws());
993 EXPECT_FALSE(client
->HasAction("ScheduledActionPrepareTiles"));
994 EXPECT_FALSE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
996 // We have no immediate actions to perform, so the BeginImplFrame should post
997 // the deadline task.
999 EXPECT_SCOPED(AdvanceFrame());
1000 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1001 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1002 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1004 // On the deadline, he actions should have occured in the right order.
1006 task_runner().RunPendingTasks(); // Run posted deadline.
1007 EXPECT_EQ(1, client
->num_draws());
1008 EXPECT_TRUE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1009 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
1010 EXPECT_LT(client
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1011 client
->ActionIndex("ScheduledActionPrepareTiles"));
1012 EXPECT_FALSE(scheduler_
->RedrawPending());
1013 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1014 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1016 // Request a draw. We don't need a PrepareTiles yet.
1018 scheduler_
->SetNeedsRedraw();
1019 EXPECT_TRUE(scheduler_
->RedrawPending());
1020 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1021 EXPECT_TRUE(client
->needs_begin_frames());
1022 EXPECT_EQ(0, client
->num_draws());
1024 // We have no immediate actions to perform, so the BeginImplFrame should post
1025 // the deadline task.
1027 EXPECT_SCOPED(AdvanceFrame());
1028 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1029 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1030 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1032 // Draw. The draw will trigger SetNeedsPrepareTiles, and
1033 // then the PrepareTiles action will be triggered after the Draw.
1034 // Afterwards, neither a draw nor PrepareTiles are pending.
1036 task_runner().RunPendingTasks(); // Run posted deadline.
1037 EXPECT_EQ(1, client
->num_draws());
1038 EXPECT_TRUE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1039 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
1040 EXPECT_LT(client
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1041 client
->ActionIndex("ScheduledActionPrepareTiles"));
1042 EXPECT_FALSE(scheduler_
->RedrawPending());
1043 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1044 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1046 // We need a BeginImplFrame where we don't swap to go idle.
1048 EXPECT_SCOPED(AdvanceFrame());
1049 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
1050 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1052 task_runner().RunPendingTasks(); // Run posted deadline.
1053 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
1054 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
1055 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1056 EXPECT_EQ(0, client
->num_draws());
1058 // Now trigger a PrepareTiles outside of a draw. We will then need
1059 // a begin-frame for the PrepareTiles, but we don't need a draw.
1061 EXPECT_FALSE(client
->needs_begin_frames());
1062 scheduler_
->SetNeedsPrepareTiles();
1063 EXPECT_TRUE(client
->needs_begin_frames());
1064 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1065 EXPECT_FALSE(scheduler_
->RedrawPending());
1067 // BeginImplFrame. There will be no draw, only PrepareTiles.
1069 EXPECT_SCOPED(AdvanceFrame());
1070 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
1071 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1073 task_runner().RunPendingTasks(); // Run posted deadline.
1074 EXPECT_EQ(0, client
->num_draws());
1075 EXPECT_FALSE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1076 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
1077 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1080 // Test that PrepareTiles only happens once per frame. If an external caller
1081 // initiates it, then the state machine should not PrepareTiles on that frame.
1082 TEST_F(SchedulerTest
, PrepareTilesOncePerFrame
) {
1083 scheduler_settings_
.use_external_begin_frame_source
= true;
1084 SetUpScheduler(true);
1086 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
1088 scheduler_
->SetNeedsPrepareTiles();
1089 scheduler_
->SetNeedsRedraw();
1091 EXPECT_SCOPED(AdvanceFrame());
1092 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1093 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1094 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1096 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1097 scheduler_
->WillPrepareTiles();
1098 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1099 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1102 task_runner().RunPendingTasks(); // Run posted deadline.
1103 EXPECT_EQ(1, client_
->num_draws());
1104 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1105 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1106 EXPECT_FALSE(scheduler_
->RedrawPending());
1107 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1108 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1110 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1111 scheduler_
->SetNeedsPrepareTiles();
1112 scheduler_
->SetNeedsRedraw();
1114 EXPECT_SCOPED(AdvanceFrame());
1115 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1116 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1117 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1120 task_runner().RunPendingTasks(); // Run posted deadline.
1121 EXPECT_EQ(1, client_
->num_draws());
1122 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1123 EXPECT_TRUE(client_
->HasAction("ScheduledActionPrepareTiles"));
1124 EXPECT_LT(client_
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1125 client_
->ActionIndex("ScheduledActionPrepareTiles"));
1126 EXPECT_FALSE(scheduler_
->RedrawPending());
1127 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1128 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1130 // If we get another DidPrepareTiles within the same frame, we should
1131 // not PrepareTiles on the next frame.
1132 scheduler_
->WillPrepareTiles();
1133 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1134 scheduler_
->SetNeedsPrepareTiles();
1135 scheduler_
->SetNeedsRedraw();
1137 EXPECT_SCOPED(AdvanceFrame());
1138 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1139 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1140 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1142 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1145 task_runner().RunPendingTasks(); // Run posted deadline.
1146 EXPECT_EQ(1, client_
->num_draws());
1147 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1148 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1149 EXPECT_FALSE(scheduler_
->RedrawPending());
1150 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1152 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1153 // frame. This verifies we don't alternate calling PrepareTiles once and
1155 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1156 scheduler_
->WillPrepareTiles();
1157 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1158 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1159 scheduler_
->SetNeedsPrepareTiles();
1160 scheduler_
->SetNeedsRedraw();
1162 EXPECT_SCOPED(AdvanceFrame());
1163 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1164 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1165 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1167 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1170 task_runner().RunPendingTasks(); // Run posted deadline.
1171 EXPECT_EQ(1, client_
->num_draws());
1172 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1173 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1174 EXPECT_FALSE(scheduler_
->RedrawPending());
1175 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1177 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1178 scheduler_
->SetNeedsPrepareTiles();
1179 scheduler_
->SetNeedsRedraw();
1181 EXPECT_SCOPED(AdvanceFrame());
1182 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1183 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1184 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1187 task_runner().RunPendingTasks(); // Run posted deadline.
1188 EXPECT_EQ(1, client_
->num_draws());
1189 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1190 EXPECT_TRUE(client_
->HasAction("ScheduledActionPrepareTiles"));
1191 EXPECT_LT(client_
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1192 client_
->ActionIndex("ScheduledActionPrepareTiles"));
1193 EXPECT_FALSE(scheduler_
->RedrawPending());
1194 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1195 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1198 TEST_F(SchedulerTest
, PrepareTilesFunnelResetOnVisibilityChange
) {
1199 scoped_ptr
<SchedulerClientNeedsPrepareTilesInDraw
> client
=
1200 make_scoped_ptr(new SchedulerClientNeedsPrepareTilesInDraw
);
1201 scheduler_settings_
.use_external_begin_frame_source
= true;
1202 SetUpScheduler(client
.Pass(), true);
1204 // Simulate a few visibility changes and associated PrepareTiles.
1205 for (int i
= 0; i
< 10; i
++) {
1206 scheduler_
->SetVisible(false);
1207 scheduler_
->WillPrepareTiles();
1208 scheduler_
->DidPrepareTiles();
1210 scheduler_
->SetVisible(true);
1211 scheduler_
->WillPrepareTiles();
1212 scheduler_
->DidPrepareTiles();
1216 scheduler_
->SetNeedsRedraw();
1217 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1221 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1222 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1223 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1226 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1227 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1228 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 2);
1229 EXPECT_ACTION("ScheduledActionPrepareTiles", client_
, 1, 2);
1232 TEST_F(SchedulerTest
, TriggerBeginFrameDeadlineEarly
) {
1233 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1234 new SchedulerClientNeedsPrepareTilesInDraw
;
1235 scheduler_settings_
.use_external_begin_frame_source
= true;
1236 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1238 scheduler_
->SetNeedsRedraw();
1239 EXPECT_SCOPED(AdvanceFrame());
1241 // The deadline should be zero since there is no work other than drawing
1243 EXPECT_EQ(base::TimeTicks(), client
->posted_begin_impl_frame_deadline());
1246 TEST_F(SchedulerTest
, WaitForReadyToDrawDoNotPostDeadline
) {
1247 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1248 new SchedulerClientNeedsPrepareTilesInDraw
;
1249 scheduler_settings_
.use_external_begin_frame_source
= true;
1250 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1252 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1253 scheduler_
->SetNeedsCommit();
1254 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1258 EXPECT_SCOPED(AdvanceFrame());
1259 scheduler_
->NotifyBeginMainFrameStarted();
1260 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1261 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1264 scheduler_
->NotifyReadyToCommit();
1265 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1268 scheduler_
->NotifyReadyToActivate();
1269 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
1271 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1273 scheduler_
->SetWaitForReadyToDraw();
1275 task_runner().RunPendingTasks(); // Try to run posted deadline.
1276 // There is no posted deadline.
1277 EXPECT_NO_ACTION(client_
);
1279 // Scheduler received ready to draw signal, and posted deadline.
1280 scheduler_
->NotifyReadyToDraw();
1282 task_runner().RunPendingTasks(); // Run posted deadline.
1283 EXPECT_EQ(1, client_
->num_draws());
1284 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1287 TEST_F(SchedulerTest
, WaitForReadyToDrawCancelledWhenLostOutputSurface
) {
1288 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1289 new SchedulerClientNeedsPrepareTilesInDraw
;
1290 scheduler_settings_
.use_external_begin_frame_source
= true;
1291 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1293 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1294 scheduler_
->SetNeedsCommit();
1295 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1299 EXPECT_SCOPED(AdvanceFrame());
1300 scheduler_
->NotifyBeginMainFrameStarted();
1301 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1302 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1305 scheduler_
->NotifyReadyToCommit();
1306 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1309 scheduler_
->NotifyReadyToActivate();
1310 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
1312 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1314 scheduler_
->SetWaitForReadyToDraw();
1316 task_runner().RunPendingTasks(); // Try to run posted deadline.
1317 // There is no posted deadline.
1318 EXPECT_NO_ACTION(client_
);
1320 // Scheduler loses output surface, and stops waiting for ready to draw signal.
1322 scheduler_
->DidLoseOutputSurface();
1323 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1324 task_runner().RunPendingTasks(); // Run posted deadline.
1325 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
1326 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
1327 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
1330 void SchedulerTest::CheckMainFrameSkippedAfterLateCommit(
1331 bool expect_send_begin_main_frame
) {
1332 // Impl thread hits deadline before commit finishes.
1333 scheduler_
->SetNeedsCommit();
1334 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1335 EXPECT_SCOPED(AdvanceFrame());
1336 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1337 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1338 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1339 scheduler_
->NotifyBeginMainFrameStarted();
1340 scheduler_
->NotifyReadyToCommit();
1341 scheduler_
->NotifyReadyToActivate();
1342 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_
, 0, 5);
1343 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 5);
1344 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 2, 5);
1345 EXPECT_ACTION("ScheduledActionCommit", client_
, 3, 5);
1346 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 4, 5);
1347 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1350 scheduler_
->SetNeedsCommit();
1351 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1352 EXPECT_SCOPED(AdvanceFrame());
1353 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1354 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1355 EXPECT_EQ(expect_send_begin_main_frame
,
1356 scheduler_
->MainThreadIsInHighLatencyMode());
1357 EXPECT_EQ(expect_send_begin_main_frame
,
1358 client_
->HasAction("ScheduledActionSendBeginMainFrame"));
1361 TEST_F(SchedulerTest
, MainFrameSkippedAfterLateCommit
) {
1362 scheduler_settings_
.use_external_begin_frame_source
= true;
1363 SetUpScheduler(true);
1365 auto fast_duration
= base::TimeDelta::FromMilliseconds(1);
1366 fake_compositor_timing_history_
->SetAllEstimatesTo(fast_duration
);
1368 bool expect_send_begin_main_frame
= false;
1370 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame
));
1373 TEST_F(SchedulerTest
,
1374 MainFrameNotSkippedAfterLateCommitInPreferImplLatencyMode
) {
1375 scheduler_settings_
.use_external_begin_frame_source
= true;
1376 SetUpScheduler(true);
1377 scheduler_
->SetImplLatencyTakesPriority(true);
1379 auto fast_duration
= base::TimeDelta::FromMilliseconds(1);
1380 fake_compositor_timing_history_
->SetAllEstimatesTo(fast_duration
);
1382 bool expect_send_begin_main_frame
= true;
1384 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame
));
1387 TEST_F(SchedulerTest
,
1388 MainFrameNotSkippedAfterLateCommit_CommitEstimateTooLong
) {
1389 scheduler_settings_
.use_external_begin_frame_source
= true;
1390 SetUpScheduler(true);
1391 auto fast_duration
= base::TimeDelta::FromMilliseconds(1);
1392 fake_compositor_timing_history_
->SetAllEstimatesTo(fast_duration
);
1393 auto slow_duration
= base::TimeDelta::FromSeconds(1);
1394 fake_compositor_timing_history_
->SetBeginMainFrameToCommitDurationEstimate(
1397 bool expect_send_begin_main_frame
= true;
1399 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame
));
1402 TEST_F(SchedulerTest
,
1403 MainFrameNotSkippedAfterLateCommit_ReadyToActivateEstimateTooLong
) {
1404 scheduler_settings_
.use_external_begin_frame_source
= true;
1405 SetUpScheduler(true);
1406 auto fast_duration
= base::TimeDelta::FromMilliseconds(1);
1407 fake_compositor_timing_history_
->SetAllEstimatesTo(fast_duration
);
1408 auto slow_duration
= base::TimeDelta::FromSeconds(1);
1409 fake_compositor_timing_history_
->SetCommitToReadyToActivateDurationEstimate(
1412 bool expect_send_begin_main_frame
= true;
1414 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame
));
1417 TEST_F(SchedulerTest
,
1418 MainFrameNotSkippedAfterLateCommit_ActivateEstimateTooLong
) {
1419 scheduler_settings_
.use_external_begin_frame_source
= true;
1420 SetUpScheduler(true);
1421 auto fast_duration
= base::TimeDelta::FromMilliseconds(1);
1422 fake_compositor_timing_history_
->SetAllEstimatesTo(fast_duration
);
1423 auto slow_duration
= base::TimeDelta::FromSeconds(1);
1424 fake_compositor_timing_history_
->SetActivateDurationEstimate(slow_duration
);
1426 bool expect_send_begin_main_frame
= true;
1428 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame
));
1431 TEST_F(SchedulerTest
, MainFrameNotSkippedAfterLateCommit_DrawEstimateTooLong
) {
1432 scheduler_settings_
.use_external_begin_frame_source
= true;
1433 SetUpScheduler(true);
1434 auto fast_duration
= base::TimeDelta::FromMilliseconds(1);
1435 fake_compositor_timing_history_
->SetAllEstimatesTo(fast_duration
);
1436 auto slow_duration
= base::TimeDelta::FromSeconds(1);
1437 fake_compositor_timing_history_
->SetDrawDurationEstimate(slow_duration
);
1439 bool expect_send_begin_main_frame
= true;
1441 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame
));
1444 void SchedulerTest::ImplFrameSkippedAfterLateSwapAck(
1445 bool swap_ack_before_deadline
) {
1446 // To get into a high latency state, this test disables automatic swap acks.
1447 scheduler_
->SetMaxSwapsPending(1);
1448 client_
->SetAutomaticSwapAck(false);
1450 // Draw and swap for first BeginFrame
1452 scheduler_
->SetNeedsCommit();
1453 scheduler_
->SetNeedsRedraw();
1454 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1455 SendNextBeginFrame();
1456 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_
, 0, 4);
1457 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 4);
1458 EXPECT_ACTION("ScheduledActionAnimate", client_
, 2, 4);
1459 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 3, 4);
1462 scheduler_
->NotifyBeginMainFrameStarted();
1463 scheduler_
->NotifyReadyToCommit();
1464 scheduler_
->NotifyReadyToActivate();
1465 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1466 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1467 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 4);
1468 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 1, 4);
1469 EXPECT_ACTION("ScheduledActionAnimate", client_
, 2, 4);
1470 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 3, 4);
1472 // Verify we skip every other frame if the swap ack consistently
1474 for (int i
= 0; i
< 10; i
++) {
1475 // Not calling scheduler_->DidSwapBuffersComplete() until after next
1476 // BeginImplFrame puts the impl thread in high latency mode.
1478 scheduler_
->SetNeedsCommit();
1479 scheduler_
->SetNeedsRedraw();
1480 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1481 SendNextBeginFrame();
1482 // Verify that we skip the BeginImplFrame
1483 EXPECT_NO_ACTION(client_
);
1484 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1485 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1487 // Verify that we do not perform any actions after we are no longer
1490 if (swap_ack_before_deadline
) {
1491 // It shouldn't matter if the swap ack comes back before the deadline...
1492 scheduler_
->DidSwapBuffersComplete();
1493 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1495 // ... or after the deadline.
1496 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1497 scheduler_
->DidSwapBuffersComplete();
1499 EXPECT_NO_ACTION(client_
);
1501 // Verify that we start the next BeginImplFrame and continue normally
1502 // after having just skipped a BeginImplFrame.
1504 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1505 SendNextBeginFrame();
1506 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
1507 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
1508 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 2, 3);
1511 scheduler_
->NotifyBeginMainFrameStarted();
1512 scheduler_
->NotifyReadyToCommit();
1513 scheduler_
->NotifyReadyToActivate();
1514 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1515 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 4);
1516 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 1, 4);
1517 EXPECT_ACTION("ScheduledActionAnimate", client_
, 2, 4);
1518 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 3, 4);
1522 TEST_F(SchedulerTest
,
1523 ImplFrameSkippedAfterLateSwapAck_FastEstimates_SwapAckThenDeadline
) {
1524 scheduler_settings_
.use_external_begin_frame_source
= true;
1525 SetUpScheduler(true);
1527 auto fast_duration
= base::TimeDelta::FromMilliseconds(1);
1528 fake_compositor_timing_history_
->SetAllEstimatesTo(fast_duration
);
1530 bool swap_ack_before_deadline
= true;
1531 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline
));
1534 TEST_F(SchedulerTest
,
1535 ImplFrameSkippedAfterLateSwapAck_FastEstimates_DeadlineThenSwapAck
) {
1536 scheduler_settings_
.use_external_begin_frame_source
= true;
1537 SetUpScheduler(true);
1539 auto fast_duration
= base::TimeDelta::FromMilliseconds(1);
1540 fake_compositor_timing_history_
->SetAllEstimatesTo(fast_duration
);
1542 bool swap_ack_before_deadline
= false;
1543 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline
));
1546 TEST_F(SchedulerTest
,
1547 ImplFrameSkippedAfterLateSwapAck_ImplLatencyTakesPriority
) {
1548 scheduler_settings_
.use_external_begin_frame_source
= true;
1549 SetUpScheduler(true);
1551 // Even if every estimate related to the main thread is slow, we should
1552 // still expect to recover impl thread latency if the draw is fast and we
1553 // are in impl latency takes priority.
1554 scheduler_
->SetImplLatencyTakesPriority(true);
1555 auto slow_duration
= base::TimeDelta::FromSeconds(1);
1556 fake_compositor_timing_history_
->SetAllEstimatesTo(slow_duration
);
1557 auto fast_duration
= base::TimeDelta::FromMilliseconds(1);
1558 fake_compositor_timing_history_
->SetDrawDurationEstimate(fast_duration
);
1560 bool swap_ack_before_deadline
= false;
1561 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline
));
1564 TEST_F(SchedulerTest
,
1565 ImplFrameSkippedAfterLateSwapAck_OnlyImplSideUpdatesExpected
) {
1566 // This tests that we recover impl thread latency when there are no commits.
1567 scheduler_settings_
.use_external_begin_frame_source
= true;
1568 SetUpScheduler(true);
1570 // To get into a high latency state, this test disables automatic swap acks.
1571 scheduler_
->SetMaxSwapsPending(1);
1572 client_
->SetAutomaticSwapAck(false);
1574 // Even if every estimate related to the main thread is slow, we should
1575 // still expect to recover impl thread latency if there are no commits from
1577 auto slow_duration
= base::TimeDelta::FromSeconds(1);
1578 fake_compositor_timing_history_
->SetAllEstimatesTo(slow_duration
);
1579 auto fast_duration
= base::TimeDelta::FromMilliseconds(1);
1580 fake_compositor_timing_history_
->SetDrawDurationEstimate(fast_duration
);
1582 // Draw and swap for first BeginFrame
1584 scheduler_
->SetNeedsRedraw();
1585 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1586 SendNextBeginFrame();
1587 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_
, 0, 3);
1588 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 3);
1589 EXPECT_ACTION("ScheduledActionAnimate", client_
, 2, 3);
1592 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1593 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1594 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
1596 // Verify we skip every other frame if the swap ack consistently
1598 for (int i
= 0; i
< 10; i
++) {
1599 // Not calling scheduler_->DidSwapBuffersComplete() until after next
1600 // BeginImplFrame puts the impl thread in high latency mode.
1602 scheduler_
->SetNeedsRedraw();
1603 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1604 SendNextBeginFrame();
1605 // Verify that we skip the BeginImplFrame
1606 EXPECT_NO_ACTION(client_
);
1607 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1608 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1610 // Verify that we do not perform any actions after we are no longer
1613 scheduler_
->DidSwapBuffersComplete();
1614 EXPECT_NO_ACTION(client_
);
1616 // Verify that we start the next BeginImplFrame and continue normally
1617 // after having just skipped a BeginImplFrame.
1619 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1620 SendNextBeginFrame();
1621 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1622 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1625 // Deadline should be immediate.
1626 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1627 task_runner().RunUntilTime(now_src_
->NowTicks());
1628 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1629 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
1633 void SchedulerTest::ImplFrameIsNotSkippedAfterLateSwapAck() {
1634 // To get into a high latency state, this test disables automatic swap acks.
1635 scheduler_
->SetMaxSwapsPending(1);
1636 client_
->SetAutomaticSwapAck(false);
1638 // Draw and swap for first BeginFrame
1640 scheduler_
->SetNeedsCommit();
1641 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1642 SendNextBeginFrame();
1643 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_
, 0, 3);
1644 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 3);
1645 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 2, 3);
1648 scheduler_
->NotifyBeginMainFrameStarted();
1649 scheduler_
->NotifyReadyToCommit();
1650 scheduler_
->NotifyReadyToActivate();
1651 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1652 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1653 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 4);
1654 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 1, 4);
1655 EXPECT_ACTION("ScheduledActionAnimate", client_
, 2, 4);
1656 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 3, 4);
1658 // Verify impl thread consistently operates in high latency mode
1659 // without skipping any frames.
1660 for (int i
= 0; i
< 10; i
++) {
1661 // Not calling scheduler_->DidSwapBuffersComplete() until after next frame
1662 // puts the impl thread in high latency mode.
1664 scheduler_
->SetNeedsCommit();
1665 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1666 SendNextBeginFrame();
1667 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
1668 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1669 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1672 scheduler_
->DidSwapBuffersComplete();
1673 scheduler_
->NotifyBeginMainFrameStarted();
1674 scheduler_
->NotifyReadyToCommit();
1675 scheduler_
->NotifyReadyToActivate();
1676 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1678 // Verify that we don't skip the actions of the BeginImplFrame
1679 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 0, 5);
1680 EXPECT_ACTION("ScheduledActionCommit", client_
, 1, 5);
1681 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 2, 5);
1682 EXPECT_ACTION("ScheduledActionAnimate", client_
, 3, 5);
1683 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 4, 5);
1687 TEST_F(SchedulerTest
,
1688 ImplFrameIsNotSkippedAfterLateSwapAck_CommitEstimateTooLong
) {
1689 scheduler_settings_
.use_external_begin_frame_source
= true;
1690 SetUpScheduler(true);
1691 auto fast_duration
= base::TimeDelta::FromMilliseconds(1);
1692 fake_compositor_timing_history_
->SetAllEstimatesTo(fast_duration
);
1693 auto slow_duration
= base::TimeDelta::FromSeconds(1);
1694 fake_compositor_timing_history_
->SetBeginMainFrameToCommitDurationEstimate(
1696 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck());
1699 TEST_F(SchedulerTest
,
1700 ImplFrameIsNotSkippedAfterLateSwapAck_ReadyToActivateEstimateTooLong
) {
1701 scheduler_settings_
.use_external_begin_frame_source
= true;
1702 SetUpScheduler(true);
1703 auto fast_duration
= base::TimeDelta::FromMilliseconds(1);
1704 fake_compositor_timing_history_
->SetAllEstimatesTo(fast_duration
);
1705 auto slow_duration
= base::TimeDelta::FromSeconds(1);
1706 fake_compositor_timing_history_
->SetCommitToReadyToActivateDurationEstimate(
1708 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck());
1711 TEST_F(SchedulerTest
,
1712 ImplFrameIsNotSkippedAfterLateSwapAck_ActivateEstimateTooLong
) {
1713 scheduler_settings_
.use_external_begin_frame_source
= true;
1714 SetUpScheduler(true);
1715 auto fast_duration
= base::TimeDelta::FromMilliseconds(1);
1716 fake_compositor_timing_history_
->SetAllEstimatesTo(fast_duration
);
1717 auto slow_duration
= base::TimeDelta::FromSeconds(1);
1718 fake_compositor_timing_history_
->SetActivateDurationEstimate(slow_duration
);
1719 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck());
1722 TEST_F(SchedulerTest
,
1723 ImplFrameIsNotSkippedAfterLateSwapAck_DrawEstimateTooLong
) {
1724 scheduler_settings_
.use_external_begin_frame_source
= true;
1725 SetUpScheduler(true);
1726 auto fast_duration
= base::TimeDelta::FromMilliseconds(1);
1727 fake_compositor_timing_history_
->SetAllEstimatesTo(fast_duration
);
1728 auto slow_duration
= base::TimeDelta::FromSeconds(1);
1729 fake_compositor_timing_history_
->SetDrawDurationEstimate(slow_duration
);
1730 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck());
1733 TEST_F(SchedulerTest
,
1734 MainFrameThenImplFrameSkippedAfterLateCommitAndLateSwapAck
) {
1735 // Set up client with custom estimates.
1736 // This test starts off with expensive estimates to prevent latency recovery
1737 // initially, then lowers the estimates to enable it once both the main
1738 // and impl threads are in a high latency mode.
1739 scheduler_settings_
.use_external_begin_frame_source
= true;
1740 SetUpScheduler(true);
1742 auto slow_duration
= base::TimeDelta::FromSeconds(1);
1743 fake_compositor_timing_history_
->SetAllEstimatesTo(slow_duration
);
1745 // To get into a high latency state, this test disables automatic swap acks.
1746 scheduler_
->SetMaxSwapsPending(1);
1747 client_
->SetAutomaticSwapAck(false);
1749 // Impl thread hits deadline before commit finishes to make
1750 // MainThreadIsInHighLatencyMode true
1752 scheduler_
->SetNeedsCommit();
1753 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1754 EXPECT_SCOPED(AdvanceFrame());
1755 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1756 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1757 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1758 scheduler_
->NotifyBeginMainFrameStarted();
1759 scheduler_
->NotifyReadyToCommit();
1760 scheduler_
->NotifyReadyToActivate();
1761 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1763 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_
, 0, 5);
1764 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 5);
1765 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 2, 5);
1766 EXPECT_ACTION("ScheduledActionCommit", client_
, 3, 5);
1767 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 4, 5);
1769 // Draw and swap for first commit, start second commit.
1771 scheduler_
->SetNeedsCommit();
1772 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1773 EXPECT_SCOPED(AdvanceFrame());
1774 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1775 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1776 scheduler_
->NotifyBeginMainFrameStarted();
1777 scheduler_
->NotifyReadyToCommit();
1778 scheduler_
->NotifyReadyToActivate();
1780 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 6);
1781 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 6);
1782 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 2, 6);
1783 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 3, 6);
1784 EXPECT_ACTION("ScheduledActionCommit", client_
, 4, 6);
1785 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 5, 6);
1787 // Don't call scheduler_->DidSwapBuffersComplete() until after next frame
1788 // to put the impl thread in a high latency mode.
1790 scheduler_
->SetNeedsCommit();
1791 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1792 EXPECT_TRUE(scheduler_
->SwapThrottled());
1793 EXPECT_SCOPED(AdvanceFrame());
1794 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1795 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1797 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1798 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1799 // Note: BeginMainFrame and swap are skipped here because of
1800 // swap ack backpressure, not because of latency recovery.
1801 EXPECT_FALSE(client_
->HasAction("ScheduledActionSendBeginMainFrame"));
1802 EXPECT_FALSE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1803 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1805 // Lower estimates so that the scheduler will attempt latency recovery.
1806 auto fast_duration
= base::TimeDelta::FromMilliseconds(1);
1807 fake_compositor_timing_history_
->SetAllEstimatesTo(fast_duration
);
1809 // Now that both threads are in a high latency mode, make sure we
1810 // skip the BeginMainFrame, then the BeginImplFrame, but not both
1811 // at the same time.
1813 // Verify we skip BeginMainFrame first.
1815 // Previous commit request is still outstanding.
1816 EXPECT_TRUE(scheduler_
->NeedsCommit());
1817 EXPECT_TRUE(scheduler_
->SwapThrottled());
1818 SendNextBeginFrame();
1819 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1820 scheduler_
->DidSwapBuffersComplete();
1821 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1823 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1824 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
1825 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
1826 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 2, 3);
1828 // Verify we skip the BeginImplFrame second.
1830 // Previous commit request is still outstanding.
1831 EXPECT_TRUE(scheduler_
->NeedsCommit());
1832 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1833 SendNextBeginFrame();
1834 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1835 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1836 scheduler_
->DidSwapBuffersComplete();
1837 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1839 EXPECT_NO_ACTION(client_
);
1841 // Then verify we operate in a low latency mode.
1843 // Previous commit request is still outstanding.
1844 EXPECT_TRUE(scheduler_
->NeedsCommit());
1845 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1846 SendNextBeginFrame();
1847 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1848 scheduler_
->NotifyBeginMainFrameStarted();
1849 scheduler_
->NotifyReadyToCommit();
1850 scheduler_
->NotifyReadyToActivate();
1851 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1852 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1853 scheduler_
->DidSwapBuffersComplete();
1854 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1856 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 6);
1857 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 6);
1858 EXPECT_ACTION("ScheduledActionCommit", client_
, 2, 6);
1859 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 3, 6);
1860 EXPECT_ACTION("ScheduledActionAnimate", client_
, 4, 6);
1861 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 5, 6);
1866 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw
) {
1867 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1868 // thread. This prevents the scheduler from receiving any pending swap acks.
1870 scheduler_settings_
.use_external_begin_frame_source
= true;
1871 scheduler_settings_
.main_frame_while_swap_throttled_enabled
= true;
1872 SetUpScheduler(true);
1874 // Disables automatic swap acks so this test can force swap ack throttling
1875 // to simulate a blocked Browser ui thread.
1876 scheduler_
->SetMaxSwapsPending(1);
1877 client_
->SetAutomaticSwapAck(false);
1879 // Get a new active tree in main-thread high latency mode and put us
1880 // in a swap throttled state.
1882 EXPECT_FALSE(scheduler_
->CommitPending());
1883 scheduler_
->SetNeedsCommit();
1884 scheduler_
->SetNeedsRedraw();
1885 EXPECT_SCOPED(AdvanceFrame());
1886 EXPECT_TRUE(scheduler_
->CommitPending());
1887 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1888 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1889 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1890 scheduler_
->NotifyBeginMainFrameStarted();
1891 scheduler_
->NotifyReadyToCommit();
1892 scheduler_
->NotifyReadyToActivate();
1893 EXPECT_FALSE(scheduler_
->CommitPending());
1894 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_
, 0, 7);
1895 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 7);
1896 EXPECT_ACTION("ScheduledActionAnimate", client_
, 2, 7);
1897 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 3, 7);
1898 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 4, 7);
1899 EXPECT_ACTION("ScheduledActionCommit", client_
, 5, 7);
1900 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 6, 7);
1902 // Make sure that we can finish the next commit even while swap throttled.
1904 EXPECT_FALSE(scheduler_
->CommitPending());
1905 scheduler_
->SetNeedsCommit();
1906 EXPECT_SCOPED(AdvanceFrame());
1907 scheduler_
->NotifyBeginMainFrameStarted();
1908 scheduler_
->NotifyReadyToCommit();
1909 scheduler_
->NotifyReadyToActivate();
1910 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1911 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1912 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1913 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 5);
1914 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 5);
1915 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 2, 5);
1916 EXPECT_ACTION("ScheduledActionCommit", client_
, 3, 5);
1917 EXPECT_ACTION("ScheduledActionAnimate", client_
, 4, 5);
1919 // Make sure we do not send a BeginMainFrame while swap throttled and
1920 // we have both a pending tree and an active tree.
1922 EXPECT_FALSE(scheduler_
->CommitPending());
1923 scheduler_
->SetNeedsCommit();
1924 EXPECT_SCOPED(AdvanceFrame());
1925 EXPECT_FALSE(scheduler_
->CommitPending());
1926 task_runner().RunPendingTasks(); // Run posted deadline.
1927 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1928 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1931 TEST_F(SchedulerTest
,
1932 Deadlock_NoBeginMainFrameWhileSwapTrottledAndPipelineFull
) {
1933 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1934 // thread. This prevents the scheduler from receiving any pending swap acks.
1936 // This particular test makes sure we do not send a BeginMainFrame while
1937 // swap trottled and we have a pending tree and active tree that
1938 // still needs to be drawn for the first time.
1940 scheduler_settings_
.use_external_begin_frame_source
= true;
1941 scheduler_settings_
.main_frame_while_swap_throttled_enabled
= true;
1942 scheduler_settings_
.main_frame_before_activation_enabled
= true;
1943 SetUpScheduler(true);
1945 // Disables automatic swap acks so this test can force swap ack throttling
1946 // to simulate a blocked Browser ui thread.
1947 scheduler_
->SetMaxSwapsPending(1);
1948 client_
->SetAutomaticSwapAck(false);
1950 // Start a new commit in main-thread high latency mode and hold off on
1953 EXPECT_FALSE(scheduler_
->CommitPending());
1954 scheduler_
->SetNeedsCommit();
1955 scheduler_
->SetNeedsRedraw();
1956 EXPECT_SCOPED(AdvanceFrame());
1957 EXPECT_TRUE(scheduler_
->CommitPending());
1958 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1959 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1960 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1961 scheduler_
->DidSwapBuffersComplete();
1962 scheduler_
->NotifyBeginMainFrameStarted();
1963 scheduler_
->NotifyReadyToCommit();
1964 EXPECT_FALSE(scheduler_
->CommitPending());
1965 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_
, 0, 6);
1966 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 6);
1967 EXPECT_ACTION("ScheduledActionAnimate", client_
, 2, 6);
1968 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 3, 6);
1969 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 4, 6);
1970 EXPECT_ACTION("ScheduledActionCommit", client_
, 5, 6);
1972 // Start another commit while we still have aa pending tree.
1973 // Enter a swap throttled state.
1975 EXPECT_FALSE(scheduler_
->CommitPending());
1976 scheduler_
->SetNeedsCommit();
1977 scheduler_
->SetNeedsRedraw();
1978 EXPECT_SCOPED(AdvanceFrame());
1979 EXPECT_TRUE(scheduler_
->CommitPending());
1980 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1981 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1982 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1983 scheduler_
->NotifyBeginMainFrameStarted();
1984 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 4);
1985 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 4);
1986 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 2, 4);
1987 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 3, 4);
1989 // Can't commit yet because there's still a pending tree.
1991 scheduler_
->NotifyReadyToCommit();
1992 EXPECT_NO_ACTION(client_
);
1994 // Activate the pending tree, which also unblocks the commit immediately.
1996 scheduler_
->NotifyReadyToActivate();
1997 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 0, 2);
1998 EXPECT_ACTION("ScheduledActionCommit", client_
, 1, 2);
2000 // Make sure we do not send a BeginMainFrame while swap throttled and
2001 // we have both a pending tree and an active tree that still needs
2004 EXPECT_FALSE(scheduler_
->CommitPending());
2005 scheduler_
->SetNeedsCommit();
2006 EXPECT_SCOPED(AdvanceFrame());
2007 EXPECT_FALSE(scheduler_
->CommitPending());
2008 task_runner().RunPendingTasks(); // Run posted deadline.
2009 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2010 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2015 CommitMakesProgressWhenIdleAndHasPendingTreeAndActiveTreeNeedsFirstDraw
) {
2016 // This verifies we don't block commits longer than we need to
2017 // for performance reasons - not deadlock reasons.
2019 // Since we are simulating a long commit, set up a client with draw duration
2020 // estimates that prevent skipping main frames to get to low latency mode.
2021 scheduler_settings_
.use_external_begin_frame_source
= true;
2022 scheduler_settings_
.main_frame_while_swap_throttled_enabled
= true;
2023 scheduler_settings_
.main_frame_before_activation_enabled
= true;
2024 SetUpScheduler(true);
2026 // Disables automatic swap acks so this test can force swap ack throttling
2027 // to simulate a blocked Browser ui thread.
2028 scheduler_
->SetMaxSwapsPending(1);
2029 client_
->SetAutomaticSwapAck(false);
2031 // Start a new commit in main-thread high latency mode and hold off on
2034 EXPECT_FALSE(scheduler_
->CommitPending());
2035 scheduler_
->SetNeedsCommit();
2036 scheduler_
->SetNeedsRedraw();
2037 EXPECT_SCOPED(AdvanceFrame());
2038 EXPECT_TRUE(scheduler_
->CommitPending());
2039 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2040 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2041 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2042 scheduler_
->DidSwapBuffersComplete();
2043 scheduler_
->NotifyBeginMainFrameStarted();
2044 scheduler_
->NotifyReadyToCommit();
2045 EXPECT_FALSE(scheduler_
->CommitPending());
2046 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_
, 0, 6);
2047 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 6);
2048 EXPECT_ACTION("ScheduledActionAnimate", client_
, 2, 6);
2049 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 3, 6);
2050 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 4, 6);
2051 EXPECT_ACTION("ScheduledActionCommit", client_
, 5, 6);
2053 // Start another commit while we still have an active tree.
2055 EXPECT_FALSE(scheduler_
->CommitPending());
2056 scheduler_
->SetNeedsCommit();
2057 scheduler_
->SetNeedsRedraw();
2058 EXPECT_SCOPED(AdvanceFrame());
2059 EXPECT_TRUE(scheduler_
->CommitPending());
2060 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2061 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2062 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2063 scheduler_
->DidSwapBuffersComplete();
2064 scheduler_
->NotifyBeginMainFrameStarted();
2065 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 4);
2066 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 4);
2067 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 2, 4);
2068 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 3, 4);
2070 // Can't commit yet because there's still a pending tree.
2072 scheduler_
->NotifyReadyToCommit();
2073 EXPECT_NO_ACTION(client_
);
2075 // Activate the pending tree, which also unblocks the commit immediately
2076 // while we are in an idle state.
2078 scheduler_
->NotifyReadyToActivate();
2079 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 0, 2);
2080 EXPECT_ACTION("ScheduledActionCommit", client_
, 1, 2);
2083 TEST_F(SchedulerTest
, BeginRetroFrame
) {
2084 scheduler_settings_
.use_external_begin_frame_source
= true;
2085 SetUpScheduler(true);
2087 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2088 scheduler_
->SetNeedsCommit();
2089 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2092 // Create a BeginFrame with a long deadline to avoid race conditions.
2093 // This is the first BeginFrame, which will be handled immediately.
2094 BeginFrameArgs args
=
2095 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
2096 args
.deadline
+= base::TimeDelta::FromHours(1);
2097 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2098 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2099 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2100 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2101 EXPECT_TRUE(client_
->needs_begin_frames());
2104 // Queue BeginFrames while we are still handling the previous BeginFrame.
2105 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2106 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2107 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2108 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2110 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2111 task_runner().RunPendingTasks(); // Run posted deadline.
2112 EXPECT_NO_ACTION(client_
);
2113 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2114 EXPECT_TRUE(client_
->needs_begin_frames());
2117 // NotifyReadyToCommit should trigger the commit.
2118 scheduler_
->NotifyBeginMainFrameStarted();
2119 scheduler_
->NotifyReadyToCommit();
2120 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2121 EXPECT_TRUE(client_
->needs_begin_frames());
2124 // NotifyReadyToActivate should trigger the activation.
2125 scheduler_
->NotifyReadyToActivate();
2126 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
2127 EXPECT_TRUE(client_
->needs_begin_frames());
2130 // BeginImplFrame should prepare the draw.
2131 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2132 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2133 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2134 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2135 EXPECT_TRUE(client_
->needs_begin_frames());
2138 // BeginImplFrame deadline should draw.
2139 task_runner().RunPendingTasks(); // Run posted deadline.
2140 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2141 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2142 EXPECT_TRUE(client_
->needs_begin_frames());
2145 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2146 // to avoid excessive toggles.
2147 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2148 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
2149 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2152 task_runner().RunPendingTasks(); // Run posted deadline.
2153 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
2154 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
2158 TEST_F(SchedulerTest
, BeginRetroFrame_SwapThrottled
) {
2159 scheduler_settings_
.use_external_begin_frame_source
= true;
2160 SetUpScheduler(true);
2162 scheduler_
->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
2164 // To test swap ack throttling, this test disables automatic swap acks.
2165 scheduler_
->SetMaxSwapsPending(1);
2166 client_
->SetAutomaticSwapAck(false);
2168 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2170 scheduler_
->SetNeedsCommit();
2171 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2174 EXPECT_SCOPED(AdvanceFrame());
2175 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2176 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2177 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2178 EXPECT_TRUE(client_
->needs_begin_frames());
2181 // Queue BeginFrame while we are still handling the previous BeginFrame.
2182 SendNextBeginFrame();
2183 EXPECT_NO_ACTION(client_
);
2184 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2185 EXPECT_TRUE(client_
->needs_begin_frames());
2188 // NotifyReadyToCommit should trigger the pending commit.
2189 scheduler_
->NotifyBeginMainFrameStarted();
2190 scheduler_
->NotifyReadyToCommit();
2191 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2192 EXPECT_TRUE(client_
->needs_begin_frames());
2195 // NotifyReadyToActivate should trigger the activation and draw.
2196 scheduler_
->NotifyReadyToActivate();
2197 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
2198 EXPECT_TRUE(client_
->needs_begin_frames());
2201 // Swapping will put us into a swap throttled state.
2202 // Run posted deadline.
2203 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2204 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2205 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2206 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2207 EXPECT_TRUE(client_
->needs_begin_frames());
2210 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
2211 // but not a BeginMainFrame or draw.
2212 scheduler_
->SetNeedsCommit();
2213 scheduler_
->SetNeedsRedraw();
2214 // Run posted BeginRetroFrame.
2215 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false));
2216 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2217 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2218 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2219 EXPECT_TRUE(client_
->needs_begin_frames());
2222 // Let time pass sufficiently beyond the regular deadline but not beyond the
2224 now_src()->Advance(BeginFrameArgs::DefaultInterval() -
2225 base::TimeDelta::FromMicroseconds(1));
2226 task_runner().RunUntilTime(now_src()->NowTicks());
2227 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2229 // Take us out of a swap throttled state.
2230 scheduler_
->DidSwapBuffersComplete();
2231 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_
);
2232 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2233 EXPECT_TRUE(client_
->needs_begin_frames());
2236 // Verify that the deadline was rescheduled.
2237 task_runner().RunUntilTime(now_src()->NowTicks());
2238 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
2239 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2240 EXPECT_TRUE(client_
->needs_begin_frames());
2244 TEST_F(SchedulerTest
, RetroFrameDoesNotExpireTooEarly
) {
2245 scheduler_settings_
.use_external_begin_frame_source
= true;
2246 SetUpScheduler(true);
2248 scheduler_
->SetNeedsCommit();
2249 EXPECT_TRUE(client_
->needs_begin_frames());
2250 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2253 EXPECT_SCOPED(AdvanceFrame());
2254 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2255 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2256 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2259 scheduler_
->NotifyBeginMainFrameStarted();
2262 BeginFrameArgs retro_frame_args
= SendNextBeginFrame();
2263 // This BeginFrame is queued up as a retro frame.
2264 EXPECT_NO_ACTION(client_
);
2265 // The previous deadline is still pending.
2266 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2269 // This main frame activating should schedule the (previous) deadline to
2270 // trigger immediately.
2271 scheduler_
->NotifyReadyToCommit();
2272 scheduler_
->NotifyReadyToActivate();
2273 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 2);
2274 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 1, 2);
2277 // The deadline task should trigger causing a draw.
2278 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2279 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2280 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2281 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2285 scheduler_
->SetNeedsAnimate();
2286 scheduler_
->SetNeedsRedraw();
2287 EXPECT_NO_ACTION(client_
);
2289 // Let's advance to the retro frame's deadline.
2290 now_src()->Advance(retro_frame_args
.deadline
- now_src()->NowTicks());
2292 // The retro frame hasn't expired yet.
2293 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false));
2294 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2295 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2296 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2298 // This is an immediate deadline case.
2300 task_runner().RunPendingTasks();
2301 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2302 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
2305 TEST_F(SchedulerTest
, RetroFrameExpiresOnTime
) {
2306 scheduler_settings_
.use_external_begin_frame_source
= true;
2307 SetUpScheduler(true);
2309 scheduler_
->SetNeedsCommit();
2310 EXPECT_TRUE(client_
->needs_begin_frames());
2311 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2314 EXPECT_SCOPED(AdvanceFrame());
2315 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2316 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2317 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2320 scheduler_
->NotifyBeginMainFrameStarted();
2323 BeginFrameArgs retro_frame_args
= SendNextBeginFrame();
2324 // This BeginFrame is queued up as a retro frame.
2325 EXPECT_NO_ACTION(client_
);
2326 // The previous deadline is still pending.
2327 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2330 // This main frame activating should schedule the (previous) deadline to
2331 // trigger immediately.
2332 scheduler_
->NotifyReadyToCommit();
2333 scheduler_
->NotifyReadyToActivate();
2334 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 2);
2335 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 1, 2);
2338 // The deadline task should trigger causing a draw.
2339 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2340 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2341 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2342 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2346 scheduler_
->SetNeedsAnimate();
2347 scheduler_
->SetNeedsRedraw();
2348 EXPECT_NO_ACTION(client_
);
2350 // Let's advance sufficiently past the retro frame's deadline.
2351 now_src()->Advance(retro_frame_args
.deadline
- now_src()->NowTicks() +
2352 base::TimeDelta::FromMicroseconds(1));
2354 // The retro frame should've expired.
2355 EXPECT_NO_ACTION(client_
);
2358 TEST_F(SchedulerTest
, MissedFrameDoesNotExpireTooEarly
) {
2359 scheduler_settings_
.use_external_begin_frame_source
= true;
2360 SetUpScheduler(true);
2362 scheduler_
->SetNeedsCommit();
2363 EXPECT_TRUE(client_
->needs_begin_frames());
2364 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2366 BeginFrameArgs missed_frame_args
=
2367 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
2368 missed_frame_args
.type
= BeginFrameArgs::MISSED
;
2370 // Advance to the deadline.
2371 now_src()->Advance(missed_frame_args
.deadline
- now_src()->NowTicks());
2373 // Missed frame is handled because it's on time.
2375 fake_external_begin_frame_source_
->TestOnBeginFrame(missed_frame_args
);
2377 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false)));
2378 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2379 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2380 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2383 TEST_F(SchedulerTest
, MissedFrameExpiresOnTime
) {
2384 scheduler_settings_
.use_external_begin_frame_source
= true;
2385 SetUpScheduler(true);
2387 scheduler_
->SetNeedsCommit();
2388 EXPECT_TRUE(client_
->needs_begin_frames());
2389 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2391 BeginFrameArgs missed_frame_args
=
2392 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
2393 missed_frame_args
.type
= BeginFrameArgs::MISSED
;
2395 // Advance sufficiently past the deadline.
2396 now_src()->Advance(missed_frame_args
.deadline
- now_src()->NowTicks() +
2397 base::TimeDelta::FromMicroseconds(1));
2399 // Missed frame is dropped because it's too late.
2401 fake_external_begin_frame_source_
->TestOnBeginFrame(missed_frame_args
);
2403 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false)));
2404 EXPECT_NO_ACTION(client_
);
2405 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2408 void SchedulerTest::BeginFramesNotFromClient(
2409 bool use_external_begin_frame_source
,
2410 bool throttle_frame_production
) {
2411 scheduler_settings_
.use_external_begin_frame_source
=
2412 use_external_begin_frame_source
;
2413 scheduler_settings_
.throttle_frame_production
= throttle_frame_production
;
2414 SetUpScheduler(true);
2416 // SetNeedsCommit should begin the frame on the next BeginImplFrame
2417 // without calling SetNeedsBeginFrame.
2418 scheduler_
->SetNeedsCommit();
2419 EXPECT_NO_ACTION(client_
);
2422 // When the client-driven BeginFrame are disabled, the scheduler posts it's
2423 // own BeginFrame tasks.
2424 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2425 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2426 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2427 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2430 // If we don't swap on the deadline, we wait for the next BeginFrame.
2431 task_runner().RunPendingTasks(); // Run posted deadline.
2432 EXPECT_NO_ACTION(client_
);
2433 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2436 // NotifyReadyToCommit should trigger the commit.
2437 scheduler_
->NotifyBeginMainFrameStarted();
2438 scheduler_
->NotifyReadyToCommit();
2439 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2442 // NotifyReadyToActivate should trigger the activation.
2443 scheduler_
->NotifyReadyToActivate();
2444 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
2447 // BeginImplFrame should prepare the draw.
2448 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2449 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2450 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2451 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2454 // BeginImplFrame deadline should draw.
2455 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2456 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2457 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2460 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2461 // to avoid excessive toggles.
2462 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2463 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
2464 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2467 // Make sure SetNeedsBeginFrame isn't called on the client
2468 // when the BeginFrame is no longer needed.
2469 task_runner().RunPendingTasks(); // Run posted deadline.
2470 EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_
);
2474 TEST_F(SchedulerTest
, SyntheticBeginFrames
) {
2475 bool use_external_begin_frame_source
= false;
2476 bool throttle_frame_production
= true;
2477 BeginFramesNotFromClient(use_external_begin_frame_source
,
2478 throttle_frame_production
);
2481 TEST_F(SchedulerTest
, VSyncThrottlingDisabled
) {
2482 bool use_external_begin_frame_source
= true;
2483 bool throttle_frame_production
= false;
2484 BeginFramesNotFromClient(use_external_begin_frame_source
,
2485 throttle_frame_production
);
2488 TEST_F(SchedulerTest
, SyntheticBeginFrames_And_VSyncThrottlingDisabled
) {
2489 bool use_external_begin_frame_source
= false;
2490 bool throttle_frame_production
= false;
2491 BeginFramesNotFromClient(use_external_begin_frame_source
,
2492 throttle_frame_production
);
2495 void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
2496 bool use_external_begin_frame_source
,
2497 bool throttle_frame_production
) {
2498 scheduler_settings_
.use_external_begin_frame_source
=
2499 use_external_begin_frame_source
;
2500 scheduler_settings_
.throttle_frame_production
= throttle_frame_production
;
2501 SetUpScheduler(true);
2503 scheduler_
->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
2505 // To test swap ack throttling, this test disables automatic swap acks.
2506 scheduler_
->SetMaxSwapsPending(1);
2507 client_
->SetAutomaticSwapAck(false);
2509 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2511 scheduler_
->SetNeedsCommit();
2512 EXPECT_NO_ACTION(client_
);
2515 // Trigger the first BeginImplFrame and BeginMainFrame
2516 EXPECT_SCOPED(AdvanceFrame());
2517 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2518 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2519 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2522 // NotifyReadyToCommit should trigger the pending commit.
2523 scheduler_
->NotifyBeginMainFrameStarted();
2524 scheduler_
->NotifyReadyToCommit();
2525 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2528 // NotifyReadyToActivate should trigger the activation and draw.
2529 scheduler_
->NotifyReadyToActivate();
2530 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
2533 // Swapping will put us into a swap throttled state.
2534 // Run posted deadline.
2535 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2536 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2537 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2538 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2541 // While swap throttled, BeginFrames should trigger BeginImplFrames,
2542 // but not a BeginMainFrame or draw.
2543 scheduler_
->SetNeedsCommit();
2544 scheduler_
->SetNeedsRedraw();
2545 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
2546 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2547 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2548 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2551 // Let time pass sufficiently beyond the regular deadline but not beyond the
2553 now_src()->Advance(BeginFrameArgs::DefaultInterval() -
2554 base::TimeDelta::FromMicroseconds(1));
2555 task_runner().RunUntilTime(now_src()->NowTicks());
2556 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2558 // Take us out of a swap throttled state.
2559 scheduler_
->DidSwapBuffersComplete();
2560 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_
);
2561 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2564 // Verify that the deadline was rescheduled.
2565 // We can't use RunUntilTime(now) here because the next frame is also
2566 // scheduled if throttle_frame_production = false.
2567 base::TimeTicks before_deadline
= now_src()->NowTicks();
2568 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2569 base::TimeTicks after_deadline
= now_src()->NowTicks();
2570 EXPECT_EQ(after_deadline
, before_deadline
);
2571 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2575 TEST_F(SchedulerTest
, SyntheticBeginFrames_SwapThrottled
) {
2576 bool use_external_begin_frame_source
= false;
2577 bool throttle_frame_production
= true;
2578 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
2579 throttle_frame_production
);
2582 TEST_F(SchedulerTest
, VSyncThrottlingDisabled_SwapThrottled
) {
2583 bool use_external_begin_frame_source
= true;
2584 bool throttle_frame_production
= false;
2585 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
2586 throttle_frame_production
);
2589 TEST_F(SchedulerTest
,
2590 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled
) {
2591 bool use_external_begin_frame_source
= false;
2592 bool throttle_frame_production
= false;
2593 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
2594 throttle_frame_production
);
2597 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized
) {
2598 scheduler_settings_
.use_external_begin_frame_source
= true;
2599 SetUpScheduler(false);
2601 scheduler_
->SetCanStart();
2602 scheduler_
->SetVisible(true);
2603 scheduler_
->SetCanDraw(true);
2605 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
2607 scheduler_
->DidCreateAndInitializeOutputSurface();
2608 EXPECT_NO_ACTION(client_
);
2610 scheduler_
->DidLoseOutputSurface();
2611 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
2614 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterBeginFrameStarted
) {
2615 scheduler_settings_
.use_external_begin_frame_source
= true;
2616 SetUpScheduler(true);
2618 // SetNeedsCommit should begin the frame.
2619 scheduler_
->SetNeedsCommit();
2620 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2623 EXPECT_SCOPED(AdvanceFrame());
2624 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2625 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2626 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2629 scheduler_
->DidLoseOutputSurface();
2630 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2631 EXPECT_NO_ACTION(client_
);
2634 scheduler_
->NotifyBeginMainFrameStarted();
2635 scheduler_
->NotifyReadyToCommit();
2636 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 2);
2637 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 1, 2);
2640 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2641 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2642 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2643 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2646 TEST_F(SchedulerTest
,
2647 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency
) {
2648 scheduler_settings_
.use_external_begin_frame_source
= true;
2649 SetUpScheduler(true);
2651 // SetNeedsCommit should begin the frame.
2652 scheduler_
->SetNeedsCommit();
2653 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2656 EXPECT_SCOPED(AdvanceFrame());
2657 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2658 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2659 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2662 scheduler_
->DidLoseOutputSurface();
2663 // Do nothing when impl frame is in deadine pending state.
2664 EXPECT_NO_ACTION(client_
);
2667 // Run posted deadline.
2668 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2669 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2670 // OnBeginImplFrameDeadline didn't schedule output surface creation because
2671 // main frame is not yet completed.
2672 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
2673 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
2674 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2676 // BeginImplFrame is not started.
2678 task_runner().RunUntilTime(now_src()->NowTicks() +
2679 base::TimeDelta::FromMilliseconds(10));
2680 EXPECT_NO_ACTION(client_
);
2681 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2684 scheduler_
->NotifyBeginMainFrameStarted();
2685 scheduler_
->NotifyReadyToCommit();
2686 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 3);
2687 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 1, 3);
2688 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 2, 3);
2691 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommit
) {
2692 scheduler_settings_
.use_external_begin_frame_source
= true;
2693 SetUpScheduler(true);
2695 // SetNeedsCommit should begin the frame.
2696 scheduler_
->SetNeedsCommit();
2697 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2700 EXPECT_SCOPED(AdvanceFrame());
2701 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2702 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2703 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2706 scheduler_
->NotifyBeginMainFrameStarted();
2707 scheduler_
->NotifyReadyToCommit();
2708 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2711 scheduler_
->DidLoseOutputSurface();
2712 // Sync tree should be forced to activate.
2713 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
2715 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2717 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2718 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2719 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2720 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2723 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles
) {
2724 scheduler_settings_
.use_external_begin_frame_source
= true;
2725 SetUpScheduler(true);
2727 scheduler_
->SetNeedsPrepareTiles();
2728 scheduler_
->SetNeedsRedraw();
2729 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2732 EXPECT_SCOPED(AdvanceFrame());
2733 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2734 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2735 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2738 scheduler_
->DidLoseOutputSurface();
2739 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2740 EXPECT_NO_ACTION(client_
);
2743 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2744 EXPECT_ACTION("ScheduledActionPrepareTiles", client_
, 0, 4);
2745 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 1, 4);
2746 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 2, 4);
2747 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 3, 4);
2750 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterBeginRetroFramePosted
) {
2751 scheduler_settings_
.use_external_begin_frame_source
= true;
2752 SetUpScheduler(true);
2754 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2755 scheduler_
->SetNeedsCommit();
2756 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2758 // Create a BeginFrame with a long deadline to avoid race conditions.
2759 // This is the first BeginFrame, which will be handled immediately.
2761 BeginFrameArgs args
=
2762 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
2763 args
.deadline
+= base::TimeDelta::FromHours(1);
2764 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2765 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2766 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2767 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2768 EXPECT_TRUE(client_
->needs_begin_frames());
2770 // Queue BeginFrames while we are still handling the previous BeginFrame.
2771 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2772 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2773 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2774 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2776 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2778 task_runner().RunPendingTasks(); // Run posted deadline.
2779 EXPECT_NO_ACTION(client_
);
2780 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2781 EXPECT_TRUE(client_
->needs_begin_frames());
2783 // NotifyReadyToCommit should trigger the commit.
2785 scheduler_
->NotifyBeginMainFrameStarted();
2786 scheduler_
->NotifyReadyToCommit();
2787 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2788 EXPECT_TRUE(client_
->needs_begin_frames());
2790 // NotifyReadyToActivate should trigger the activation.
2792 scheduler_
->NotifyReadyToActivate();
2793 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
2794 EXPECT_TRUE(client_
->needs_begin_frames());
2797 EXPECT_FALSE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2798 scheduler_
->DidLoseOutputSurface();
2799 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2800 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2801 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2802 EXPECT_TRUE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2804 // Posted BeginRetroFrame is aborted.
2806 task_runner().RunPendingTasks();
2807 EXPECT_NO_ACTION(client_
);
2810 TEST_F(SchedulerTest
, DidLoseOutputSurfaceDuringBeginRetroFrameRunning
) {
2811 scheduler_settings_
.use_external_begin_frame_source
= true;
2812 SetUpScheduler(true);
2814 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2815 scheduler_
->SetNeedsCommit();
2816 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2818 // Create a BeginFrame with a long deadline to avoid race conditions.
2819 // This is the first BeginFrame, which will be handled immediately.
2821 BeginFrameArgs args
=
2822 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
2823 args
.deadline
+= base::TimeDelta::FromHours(1);
2824 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2825 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2826 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2827 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2828 EXPECT_TRUE(client_
->needs_begin_frames());
2830 // Queue BeginFrames while we are still handling the previous BeginFrame.
2831 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2832 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2833 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2834 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2836 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2838 task_runner().RunPendingTasks(); // Run posted deadline.
2839 EXPECT_NO_ACTION(client_
);
2840 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2841 EXPECT_TRUE(client_
->needs_begin_frames());
2843 // NotifyReadyToCommit should trigger the commit.
2845 scheduler_
->NotifyBeginMainFrameStarted();
2846 scheduler_
->NotifyReadyToCommit();
2847 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2848 EXPECT_TRUE(client_
->needs_begin_frames());
2850 // NotifyReadyToActivate should trigger the activation.
2852 scheduler_
->NotifyReadyToActivate();
2853 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
2854 EXPECT_TRUE(client_
->needs_begin_frames());
2856 // BeginImplFrame should prepare the draw.
2858 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2859 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2860 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2861 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2862 EXPECT_TRUE(client_
->needs_begin_frames());
2865 EXPECT_FALSE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2866 scheduler_
->DidLoseOutputSurface();
2867 EXPECT_NO_ACTION(client_
);
2868 EXPECT_TRUE(scheduler_
->IsBeginRetroFrameArgsEmpty());
2870 // BeginImplFrame deadline should abort drawing.
2872 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2873 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2874 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2875 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2876 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2877 EXPECT_FALSE(client_
->needs_begin_frames());
2879 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
2881 task_runner().RunPendingTasks();
2882 EXPECT_NO_ACTION(client_
);
2885 TEST_F(SchedulerTest
, DidLoseOutputSurfaceWithSyntheticBeginFrameSource
) {
2886 SetUpScheduler(true);
2888 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2889 EXPECT_FALSE(scheduler_
->frame_source().NeedsBeginFrames());
2890 scheduler_
->SetNeedsCommit();
2891 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2895 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2896 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2897 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2898 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2900 // NotifyReadyToCommit should trigger the commit.
2902 scheduler_
->NotifyBeginMainFrameStarted();
2903 scheduler_
->NotifyReadyToCommit();
2904 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2905 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2907 // NotifyReadyToActivate should trigger the activation.
2909 scheduler_
->NotifyReadyToActivate();
2910 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
2911 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2914 scheduler_
->DidLoseOutputSurface();
2915 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2916 EXPECT_NO_ACTION(client_
);
2917 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2920 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2921 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 2);
2922 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
2923 EXPECT_FALSE(scheduler_
->frame_source().NeedsBeginFrames());
2926 TEST_F(SchedulerTest
, DidLoseOutputSurfaceWhenIdle
) {
2927 scheduler_settings_
.use_external_begin_frame_source
= true;
2928 SetUpScheduler(true);
2930 // SetNeedsCommit should begin the frame.
2931 scheduler_
->SetNeedsCommit();
2932 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2935 EXPECT_SCOPED(AdvanceFrame());
2936 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2937 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2938 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2941 scheduler_
->NotifyBeginMainFrameStarted();
2942 scheduler_
->NotifyReadyToCommit();
2943 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2946 scheduler_
->NotifyReadyToActivate();
2947 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
2950 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
2951 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2952 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2954 // Idle time between BeginFrames.
2956 scheduler_
->DidLoseOutputSurface();
2957 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 3);
2958 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2959 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2962 TEST_F(SchedulerTest
, ScheduledActionActivateAfterBecomingInvisible
) {
2963 scheduler_settings_
.use_external_begin_frame_source
= true;
2964 SetUpScheduler(true);
2966 // SetNeedsCommit should begin the frame.
2967 scheduler_
->SetNeedsCommit();
2968 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2971 EXPECT_SCOPED(AdvanceFrame());
2972 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2973 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2974 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2977 scheduler_
->NotifyBeginMainFrameStarted();
2978 scheduler_
->NotifyReadyToCommit();
2979 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2980 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2983 scheduler_
->SetVisible(false);
2984 task_runner().RunPendingTasks(); // Run posted deadline.
2986 // Sync tree should be forced to activate.
2987 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 0, 3);
2988 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
2989 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
2992 // Tests to ensure frame sources can be successfully changed while drawing.
2993 TEST_F(SchedulerTest
, SwitchFrameSourceToUnthrottled
) {
2994 scheduler_settings_
.use_external_begin_frame_source
= true;
2995 SetUpScheduler(true);
2997 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2998 scheduler_
->SetNeedsRedraw();
2999 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
3002 EXPECT_SCOPED(AdvanceFrame());
3003 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
3004 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
3005 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
3006 EXPECT_TRUE(client_
->needs_begin_frames());
3008 task_runner().RunPendingTasks(); // Run posted deadline.
3009 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
3010 scheduler_
->SetNeedsRedraw();
3012 // Switch to an unthrottled frame source.
3013 scheduler_
->SetThrottleFrameProduction(false);
3016 // Unthrottled frame source will immediately begin a new frame.
3017 task_runner().RunPendingTasks(); // Run posted BeginFrame.
3018 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
3019 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
3020 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
3023 // If we don't swap on the deadline, we wait for the next BeginFrame.
3024 task_runner().RunPendingTasks(); // Run posted deadline.
3025 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
3026 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3030 // Tests to ensure frame sources can be successfully changed while a frame
3031 // deadline is pending.
3032 TEST_F(SchedulerTest
, SwitchFrameSourceToUnthrottledBeforeDeadline
) {
3033 scheduler_settings_
.use_external_begin_frame_source
= true;
3034 SetUpScheduler(true);
3036 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
3037 scheduler_
->SetNeedsRedraw();
3038 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
3041 EXPECT_SCOPED(AdvanceFrame());
3042 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
3043 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
3045 // Switch to an unthrottled frame source before the frame deadline is hit.
3046 scheduler_
->SetThrottleFrameProduction(false);
3049 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
3050 EXPECT_TRUE(client_
->needs_begin_frames());
3053 task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame.
3054 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 2);
3055 // Unthrottled frame source will immediately begin a new frame.
3056 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 2);
3057 scheduler_
->SetNeedsRedraw();
3060 task_runner().RunPendingTasks(); // Run posted deadline.
3061 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
3062 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
3063 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3067 // Tests to ensure that the active frame source can successfully be changed from
3068 // unthrottled to throttled.
3069 TEST_F(SchedulerTest
, SwitchFrameSourceToThrottled
) {
3070 scheduler_settings_
.throttle_frame_production
= false;
3071 scheduler_settings_
.use_external_begin_frame_source
= true;
3072 SetUpScheduler(true);
3074 scheduler_
->SetNeedsRedraw();
3075 EXPECT_NO_ACTION(client_
);
3078 task_runner().RunPendingTasks(); // Run posted BeginFrame.
3079 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
3080 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
3081 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
3084 task_runner().RunPendingTasks(); // Run posted deadline.
3085 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
3086 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3089 // Switch to a throttled frame source.
3090 scheduler_
->SetThrottleFrameProduction(true);
3093 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
3094 scheduler_
->SetNeedsRedraw();
3095 task_runner().RunPendingTasks();
3096 EXPECT_NO_ACTION(client_
);
3099 EXPECT_SCOPED(AdvanceFrame());
3100 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
3101 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
3102 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
3103 EXPECT_TRUE(client_
->needs_begin_frames());
3105 task_runner().RunPendingTasks(); // Run posted deadline.
3106 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
3109 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
3110 TEST_F(SchedulerTest
, SendBeginMainFrameNotExpectedSoon
) {
3111 scheduler_settings_
.use_external_begin_frame_source
= true;
3112 SetUpScheduler(true);
3114 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
3115 scheduler_
->SetNeedsCommit();
3116 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
3119 // Trigger a frame draw.
3120 EXPECT_SCOPED(AdvanceFrame());
3121 scheduler_
->NotifyBeginMainFrameStarted();
3122 scheduler_
->NotifyReadyToCommit();
3123 scheduler_
->NotifyReadyToActivate();
3124 task_runner().RunPendingTasks();
3125 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 6);
3126 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 6);
3127 EXPECT_ACTION("ScheduledActionCommit", client_
, 2, 6);
3128 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 3, 6);
3129 EXPECT_ACTION("ScheduledActionAnimate", client_
, 4, 6);
3130 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 5, 6);
3133 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
3134 // and send a SendBeginMainFrameNotExpectedSoon.
3135 EXPECT_SCOPED(AdvanceFrame());
3136 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
3137 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
3140 task_runner().RunPendingTasks(); // Run posted deadline.
3141 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
3142 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 1, 2);
3146 TEST_F(SchedulerTest
, SynchronousCompositorAnimation
) {
3147 scheduler_settings_
.using_synchronous_renderer_compositor
= true;
3148 scheduler_settings_
.use_external_begin_frame_source
= true;
3149 SetUpScheduler(true);
3151 scheduler_
->SetNeedsAnimate();
3152 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
3157 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
3158 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
3159 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
3160 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3163 // Continue with animation.
3164 scheduler_
->SetNeedsAnimate();
3165 EXPECT_NO_ACTION(client_
);
3168 scheduler_
->SetNeedsRedraw();
3169 scheduler_
->OnDrawForOutputSurface();
3170 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
3171 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3176 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
3177 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
3178 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
3179 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3183 scheduler_
->SetNeedsRedraw();
3184 scheduler_
->OnDrawForOutputSurface();
3185 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
3186 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3189 // Idle on next vsync.
3191 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
3192 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
3193 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
3194 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3198 TEST_F(SchedulerTest
, SynchronousCompositorOnDrawDuringIdle
) {
3199 scheduler_settings_
.using_synchronous_renderer_compositor
= true;
3200 scheduler_settings_
.use_external_begin_frame_source
= true;
3201 SetUpScheduler(true);
3203 scheduler_
->SetNeedsRedraw();
3204 scheduler_
->OnDrawForOutputSurface();
3205 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_
, 0, 3);
3206 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
3207 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 2, 3);
3208 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3211 // Idle on next vsync.
3213 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
3214 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
3215 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
3216 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3220 TEST_F(SchedulerTest
, SynchronousCompositorCommit
) {
3221 scheduler_settings_
.using_synchronous_renderer_compositor
= true;
3222 scheduler_settings_
.use_external_begin_frame_source
= true;
3223 SetUpScheduler(true);
3225 scheduler_
->SetNeedsCommit();
3226 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
3231 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
3232 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
3233 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3236 scheduler_
->NotifyBeginMainFrameStarted();
3237 EXPECT_NO_ACTION(client_
);
3241 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
3242 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3245 scheduler_
->NotifyReadyToCommit();
3246 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
3249 scheduler_
->NotifyReadyToActivate();
3250 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
3255 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
3256 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
3257 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
3258 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3262 scheduler_
->SetNeedsRedraw();
3263 scheduler_
->OnDrawForOutputSurface();
3264 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
3265 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3268 // Idle on next vsync.
3270 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
3271 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
3272 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
3273 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3277 TEST_F(SchedulerTest
, SynchronousCompositorDoubleCommitWithoutDraw
) {
3278 scheduler_settings_
.using_synchronous_renderer_compositor
= true;
3279 scheduler_settings_
.use_external_begin_frame_source
= true;
3280 SetUpScheduler(true);
3282 scheduler_
->SetNeedsCommit();
3283 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
3288 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
3289 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
3290 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3293 scheduler_
->NotifyBeginMainFrameStarted();
3294 EXPECT_NO_ACTION(client_
);
3296 scheduler_
->NotifyReadyToCommit();
3297 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
3300 scheduler_
->NotifyReadyToActivate();
3301 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
3304 // Ask for another commit.
3305 scheduler_
->SetNeedsCommit();
3308 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 4);
3309 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 4);
3310 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 2, 4);
3311 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 3, 4);
3312 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3315 scheduler_
->NotifyBeginMainFrameStarted();
3316 EXPECT_NO_ACTION(client_
);
3318 // Allow new commit even though previous commit hasn't been drawn.
3319 scheduler_
->NotifyReadyToCommit();
3320 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
3324 class SchedulerClientSetNeedsPrepareTilesOnDraw
: public FakeSchedulerClient
{
3326 SchedulerClientSetNeedsPrepareTilesOnDraw() : FakeSchedulerClient() {}
3329 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
3330 scheduler_
->SetNeedsPrepareTiles();
3331 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
3335 TEST_F(SchedulerTest
, SynchronousCompositorPrepareTilesOnDraw
) {
3336 scheduler_settings_
.using_synchronous_renderer_compositor
= true;
3337 scheduler_settings_
.use_external_begin_frame_source
= true;
3339 scoped_ptr
<FakeSchedulerClient
> client
=
3340 make_scoped_ptr(new SchedulerClientSetNeedsPrepareTilesOnDraw
);
3341 SetUpScheduler(client
.Pass(), true);
3343 scheduler_
->SetNeedsRedraw();
3344 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
3348 EXPECT_SCOPED(AdvanceFrame());
3349 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
3350 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
3351 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
3355 scheduler_
->SetNeedsRedraw();
3356 scheduler_
->OnDrawForOutputSurface();
3357 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 2);
3358 EXPECT_ACTION("ScheduledActionPrepareTiles", client_
, 1, 2);
3359 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3360 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
3364 scheduler_
->SetNeedsRedraw();
3365 scheduler_
->OnDrawForOutputSurface();
3366 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 2);
3367 EXPECT_ACTION("ScheduledActionPrepareTiles", client_
, 1, 2);
3368 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3369 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
3373 EXPECT_SCOPED(AdvanceFrame());
3374 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
3375 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
3376 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 3);
3377 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_
, 2, 3);
3378 EXPECT_FALSE(client_
->needs_begin_frames());
3382 TEST_F(SchedulerTest
, SynchronousCompositorSendBeginMainFrameWhileIdle
) {
3383 scheduler_settings_
.using_synchronous_renderer_compositor
= true;
3384 scheduler_settings_
.use_external_begin_frame_source
= true;
3386 SetUpScheduler(true);
3388 scheduler_
->SetNeedsRedraw();
3389 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
3393 EXPECT_SCOPED(AdvanceFrame());
3394 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
3395 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
3396 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
3400 scheduler_
->SetNeedsRedraw();
3401 scheduler_
->OnDrawForOutputSurface();
3402 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
3403 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3404 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
3407 // Simulate SetNeedsCommit due to input event.
3408 scheduler_
->SetNeedsCommit();
3409 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_
);
3412 scheduler_
->NotifyBeginMainFrameStarted();
3413 scheduler_
->NotifyReadyToCommit();
3414 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
3417 scheduler_
->NotifyReadyToActivate();
3418 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_
);
3422 EXPECT_SCOPED(AdvanceFrame());
3423 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 3);
3424 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 3);
3425 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_
, 2, 3);
3429 scheduler_
->SetNeedsRedraw();
3430 scheduler_
->OnDrawForOutputSurface();
3431 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
3432 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
3433 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
3436 // Simulate SetNeedsCommit due to input event.
3437 scheduler_
->SetNeedsCommit();
3438 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_
);
3442 TEST_F(SchedulerTest
, AuthoritativeVSyncInterval
) {
3443 SetUpScheduler(true);
3444 base::TimeDelta initial_interval
= scheduler_
->BeginImplFrameInterval();
3445 base::TimeDelta authoritative_interval
=
3446 base::TimeDelta::FromMilliseconds(33);
3448 scheduler_
->SetNeedsCommit();
3449 EXPECT_SCOPED(AdvanceFrame());
3451 EXPECT_EQ(initial_interval
, scheduler_
->BeginImplFrameInterval());
3453 scheduler_
->NotifyBeginMainFrameStarted();
3454 scheduler_
->NotifyReadyToCommit();
3455 scheduler_
->NotifyReadyToActivate();
3456 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
3458 scheduler_
->SetAuthoritativeVSyncInterval(authoritative_interval
);
3460 EXPECT_SCOPED(AdvanceFrame());
3462 // At the next BeginFrame, authoritative interval is used instead of previous
3464 EXPECT_NE(initial_interval
, scheduler_
->BeginImplFrameInterval());
3465 EXPECT_EQ(authoritative_interval
, scheduler_
->BeginImplFrameInterval());
3468 TEST_F(SchedulerTest
, ImplLatencyTakesPriority
) {
3469 SetUpScheduler(true);
3470 scheduler_
->SetImplLatencyTakesPriority(true);
3471 EXPECT_TRUE(scheduler_
->ImplLatencyTakesPriority());
3473 scheduler_
->SetImplLatencyTakesPriority(false);
3474 EXPECT_FALSE(scheduler_
->ImplLatencyTakesPriority());
3477 TEST_F(SchedulerTest
, BeginFrameArgs_OnCriticalPath
) {
3478 scheduler_settings_
.use_external_begin_frame_source
= true;
3479 SetUpScheduler(true);
3481 scheduler_
->SetImplLatencyTakesPriority(false);
3482 scheduler_
->SetChildrenNeedBeginFrames(true);
3484 EXPECT_SCOPED(AdvanceFrame());
3485 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
3486 EXPECT_TRUE(client_
->begin_frame_args_sent_to_children().on_critical_path
);
3489 TEST_F(SchedulerTest
, BeginFrameArgs_NotOnCriticalPath
) {
3490 scheduler_settings_
.use_external_begin_frame_source
= true;
3491 SetUpScheduler(true);
3493 scheduler_
->SetImplLatencyTakesPriority(true);
3494 scheduler_
->SetChildrenNeedBeginFrames(true);
3496 EXPECT_SCOPED(AdvanceFrame());
3497 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
3498 EXPECT_FALSE(client_
->begin_frame_args_sent_to_children().on_critical_path
);