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/power_monitor/power_monitor.h"
14 #include "base/power_monitor/power_monitor_source.h"
15 #include "base/run_loop.h"
16 #include "base/time/time.h"
17 #include "base/trace_event/trace_event.h"
18 #include "cc/test/begin_frame_args_test.h"
19 #include "cc/test/ordered_simple_task_runner.h"
20 #include "cc/test/scheduler_test_common.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
26 EXPECT_EQ(expected_num_actions, client->num_actions_()); \
27 if (action_index >= 0) { \
28 ASSERT_LT(action_index, client->num_actions_()) << scheduler_.get(); \
29 EXPECT_STREQ(action, client->Action(action_index)); \
31 for (int i = expected_num_actions; i < client->num_actions_(); ++i) \
32 ADD_FAILURE() << "Unexpected action: " << client->Action(i) \
33 << " with state:\n" << client->StateForAction(i); \
36 #define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0)
38 #define EXPECT_SINGLE_ACTION(action, client) \
39 EXPECT_ACTION(action, client, 0, 1)
41 #define EXPECT_SCOPED(statements) \
50 class FakeSchedulerClient
: public SchedulerClient
{
53 : automatic_swap_ack_(true),
54 begin_frame_is_sent_to_children_(false),
62 draw_will_happen_
= true;
63 swap_will_happen_if_draw_happens_
= true;
65 log_anticipated_draw_time_change_
= false;
66 begin_frame_is_sent_to_children_
= false;
69 void set_scheduler(TestScheduler
* scheduler
) { scheduler_
= scheduler
; }
71 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
73 void set_log_anticipated_draw_time_change(bool log
) {
74 log_anticipated_draw_time_change_
= log
;
76 bool needs_begin_frames() {
77 return scheduler_
->frame_source().NeedsBeginFrames();
79 int num_draws() const { return num_draws_
; }
80 int num_actions_() const { return static_cast<int>(actions_
.size()); }
81 const char* Action(int i
) const { return actions_
[i
]; }
82 std::string
StateForAction(int i
) const { return states_
[i
]->ToString(); }
83 base::TimeTicks
posted_begin_impl_frame_deadline() const {
84 return posted_begin_impl_frame_deadline_
;
87 int ActionIndex(const char* action
) const {
88 for (size_t i
= 0; i
< actions_
.size(); i
++)
89 if (!strcmp(actions_
[i
], action
))
94 bool HasAction(const char* action
) const {
95 return ActionIndex(action
) >= 0;
98 void SetDrawWillHappen(bool draw_will_happen
) {
99 draw_will_happen_
= draw_will_happen
;
101 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens
) {
102 swap_will_happen_if_draw_happens_
= swap_will_happen_if_draw_happens
;
104 void SetAutomaticSwapAck(bool automatic_swap_ack
) {
105 automatic_swap_ack_
= automatic_swap_ack
;
107 // SchedulerClient implementation.
108 void WillBeginImplFrame(const BeginFrameArgs
& args
) override
{
109 PushAction("WillBeginImplFrame");
111 void ScheduledActionSendBeginMainFrame() override
{
112 PushAction("ScheduledActionSendBeginMainFrame");
114 void ScheduledActionAnimate() override
{
115 PushAction("ScheduledActionAnimate");
117 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
118 PushAction("ScheduledActionDrawAndSwapIfPossible");
121 draw_will_happen_
? DRAW_SUCCESS
: DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
;
122 bool swap_will_happen
=
123 draw_will_happen_
&& swap_will_happen_if_draw_happens_
;
124 if (swap_will_happen
) {
125 scheduler_
->DidSwapBuffers();
127 if (automatic_swap_ack_
)
128 scheduler_
->DidSwapBuffersComplete();
132 DrawResult
ScheduledActionDrawAndSwapForced() override
{
133 PushAction("ScheduledActionDrawAndSwapForced");
136 void ScheduledActionCommit() override
{ PushAction("ScheduledActionCommit"); }
137 void ScheduledActionActivateSyncTree() override
{
138 PushAction("ScheduledActionActivateSyncTree");
140 void ScheduledActionBeginOutputSurfaceCreation() override
{
141 PushAction("ScheduledActionBeginOutputSurfaceCreation");
143 void ScheduledActionPrepareTiles() override
{
144 PushAction("ScheduledActionPrepareTiles");
146 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{
147 if (log_anticipated_draw_time_change_
)
148 PushAction("DidAnticipatedDrawTimeChange");
150 base::TimeDelta
DrawDurationEstimate() override
{ return base::TimeDelta(); }
151 base::TimeDelta
BeginMainFrameToCommitDurationEstimate() override
{
152 return base::TimeDelta();
154 base::TimeDelta
CommitToActivateDurationEstimate() override
{
155 return base::TimeDelta();
158 void DidBeginImplFrameDeadline() override
{}
160 void SendBeginFramesToChildren(const BeginFrameArgs
& args
) override
{
161 begin_frame_is_sent_to_children_
= true;
164 base::Callback
<bool(void)> ImplFrameDeadlinePending(bool state
) {
165 return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback
,
166 base::Unretained(this),
170 bool begin_frame_is_sent_to_children() const {
171 return begin_frame_is_sent_to_children_
;
174 void PushAction(const char* description
) {
175 actions_
.push_back(description
);
176 states_
.push_back(scheduler_
->AsValue());
180 bool ImplFrameDeadlinePendingCallback(bool state
) {
181 return scheduler_
->BeginImplFrameDeadlinePending() == state
;
184 bool draw_will_happen_
;
185 bool swap_will_happen_if_draw_happens_
;
186 bool automatic_swap_ack_
;
188 bool log_anticipated_draw_time_change_
;
189 bool begin_frame_is_sent_to_children_
;
190 base::TimeTicks posted_begin_impl_frame_deadline_
;
191 std::vector
<const char*> actions_
;
192 std::vector
<scoped_refptr
<base::debug::ConvertableToTraceFormat
>> states_
;
193 TestScheduler
* scheduler_
;
196 class FakePowerMonitorSource
: public base::PowerMonitorSource
{
198 FakePowerMonitorSource() {}
199 ~FakePowerMonitorSource() override
{}
200 void GeneratePowerStateEvent(bool on_battery_power
) {
201 on_battery_power_impl_
= on_battery_power
;
202 ProcessPowerEvent(POWER_STATE_EVENT
);
203 base::MessageLoop::current()->RunUntilIdle();
205 bool IsOnBatteryPowerImpl() override
{ return on_battery_power_impl_
; }
208 bool on_battery_power_impl_
;
211 class FakeExternalBeginFrameSource
: public BeginFrameSourceMixIn
{
213 explicit FakeExternalBeginFrameSource(FakeSchedulerClient
* client
)
215 ~FakeExternalBeginFrameSource() override
{}
217 void OnNeedsBeginFramesChange(bool needs_begin_frames
) override
{
218 if (needs_begin_frames
) {
219 client_
->PushAction("SetNeedsBeginFrames(true)");
221 client_
->PushAction("SetNeedsBeginFrames(false)");
225 void TestOnBeginFrame(const BeginFrameArgs
& args
) {
226 return CallOnBeginFrame(args
);
230 FakeSchedulerClient
* client_
;
233 class SchedulerTest
: public testing::Test
{
236 : now_src_(TestNowSource::Create()),
237 task_runner_(new OrderedSimpleTaskRunner(now_src_
, true)),
238 fake_external_begin_frame_source_(nullptr),
239 fake_power_monitor_source_(new FakePowerMonitorSource
),
240 power_monitor_(make_scoped_ptr
<base::PowerMonitorSource
>(
241 fake_power_monitor_source_
)) {
242 // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval()
243 now_src_
->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
244 // Fail if we need to run 100 tasks in a row.
245 task_runner_
->SetRunTaskLimit(100);
248 ~SchedulerTest() override
{}
251 TestScheduler
* CreateScheduler() {
252 scoped_ptr
<FakeExternalBeginFrameSource
> fake_external_begin_frame_source
;
253 if (scheduler_settings_
.use_external_begin_frame_source
) {
254 fake_external_begin_frame_source
.reset(
255 new FakeExternalBeginFrameSource(client_
.get()));
256 fake_external_begin_frame_source_
=
257 fake_external_begin_frame_source
.get();
259 scheduler_
= TestScheduler::Create(
260 now_src_
, client_
.get(), scheduler_settings_
, 0, task_runner_
,
261 &power_monitor_
, fake_external_begin_frame_source
.Pass());
263 client_
->set_scheduler(scheduler_
.get());
264 return scheduler_
.get();
267 void CreateSchedulerAndInitSurface() {
269 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit());
272 void SetUpScheduler(bool initSurface
) {
273 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient
), initSurface
);
276 void SetUpScheduler(scoped_ptr
<FakeSchedulerClient
> client
,
278 client_
= client
.Pass();
280 CreateSchedulerAndInitSurface();
285 OrderedSimpleTaskRunner
& task_runner() { return *task_runner_
; }
286 TestNowSource
* now_src() { return now_src_
.get(); }
288 // As this function contains EXPECT macros, to allow debugging it should be
289 // called inside EXPECT_SCOPED like so;
290 // EXPECT_SCOPED(client.InitializeOutputSurfaceAndFirstCommit(scheduler));
291 void InitializeOutputSurfaceAndFirstCommit() {
293 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit");
296 // Check the client doesn't have any actions queued when calling this
298 EXPECT_NO_ACTION(client_
);
299 EXPECT_FALSE(client_
->needs_begin_frames());
301 // Start the initial output surface creation.
302 EXPECT_FALSE(scheduler_
->CanStart());
303 scheduler_
->SetCanStart();
304 scheduler_
->SetVisible(true);
305 scheduler_
->SetCanDraw(true);
306 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
310 // We don't see anything happening until the first impl frame.
311 scheduler_
->DidCreateAndInitializeOutputSurface();
312 scheduler_
->SetNeedsCommit();
313 EXPECT_TRUE(client_
->needs_begin_frames());
314 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
318 SCOPED_TRACE("Do first frame to commit after initialize.");
321 scheduler_
->NotifyBeginMainFrameStarted();
322 scheduler_
->NotifyReadyToCommitThenActivateIfNeeded();
324 // Run the posted deadline task.
325 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
326 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
327 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
329 EXPECT_FALSE(scheduler_
->CommitPending());
336 "Run second frame so Scheduler calls SetNeedsBeginFrame(false).");
339 // Run the posted deadline task.
340 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
341 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
342 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
345 EXPECT_FALSE(client_
->needs_begin_frames());
349 // As this function contains EXPECT macros, to allow debugging it should be
350 // called inside EXPECT_SCOPED like so;
351 // EXPECT_SCOPED(client.AdvanceFrame());
352 void AdvanceFrame() {
353 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
354 "FakeSchedulerClient::AdvanceFrame");
355 // Consume any previous deadline first, if no deadline is currently
356 // pending, ImplFrameDeadlinePending will return false straight away and we
357 // will run no tasks.
358 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
359 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
361 // Send the next BeginFrame message if using an external source, otherwise
362 // it will be already in the task queue.
363 if (scheduler_
->settings().use_external_begin_frame_source
&&
364 scheduler_
->FrameProductionThrottled()) {
365 SendNextBeginFrame();
366 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
369 // Then run tasks until new deadline is scheduled.
371 task_runner_
->RunTasksWhile(client_
->ImplFrameDeadlinePending(false)));
372 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
375 void SendNextBeginFrame() {
376 DCHECK(scheduler_
->settings().use_external_begin_frame_source
);
377 // Creep the time forward so that any BeginFrameArgs is not equal to the
378 // last one otherwise we violate the BeginFrameSource contract.
379 now_src_
->AdvanceNow(BeginFrameArgs::DefaultInterval());
380 fake_external_begin_frame_source_
->TestOnBeginFrame(
381 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src()));
384 base::PowerMonitor
* PowerMonitor() { return &power_monitor_
; }
385 FakePowerMonitorSource
* PowerMonitorSource() {
386 return fake_power_monitor_source_
;
389 FakeExternalBeginFrameSource
* fake_external_begin_frame_source() const {
390 return fake_external_begin_frame_source_
;
393 void MainFrameInHighLatencyMode(
394 int64 begin_main_frame_to_commit_estimate_in_ms
,
395 int64 commit_to_activate_estimate_in_ms
,
396 bool impl_latency_takes_priority
,
397 bool should_send_begin_main_frame
);
398 void BeginFramesNotFromClient(bool use_external_begin_frame_source
,
399 bool throttle_frame_production
);
400 void BeginFramesNotFromClient_SwapThrottled(
401 bool use_external_begin_frame_source
,
402 bool throttle_frame_production
);
403 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
404 bool impl_side_painting
);
405 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting
);
407 scoped_refptr
<TestNowSource
> now_src_
;
408 scoped_refptr
<OrderedSimpleTaskRunner
> task_runner_
;
409 FakeExternalBeginFrameSource
* fake_external_begin_frame_source_
;
410 FakePowerMonitorSource
* fake_power_monitor_source_
;
411 base::PowerMonitor power_monitor_
;
412 SchedulerSettings scheduler_settings_
;
413 scoped_ptr
<FakeSchedulerClient
> client_
;
414 scoped_ptr
<TestScheduler
> scheduler_
;
417 TEST_F(SchedulerTest
, InitializeOutputSurfaceDoesNotBeginImplFrame
) {
418 scheduler_settings_
.use_external_begin_frame_source
= true;
419 SetUpScheduler(false);
420 scheduler_
->SetCanStart();
421 scheduler_
->SetVisible(true);
422 scheduler_
->SetCanDraw(true);
424 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
426 scheduler_
->DidCreateAndInitializeOutputSurface();
427 EXPECT_NO_ACTION(client_
);
430 TEST_F(SchedulerTest
, SendBeginFramesToChildren
) {
431 scheduler_settings_
.use_external_begin_frame_source
= true;
432 scheduler_settings_
.forward_begin_frames_to_children
= true;
433 SetUpScheduler(true);
435 EXPECT_FALSE(client_
->begin_frame_is_sent_to_children());
436 scheduler_
->SetNeedsCommit();
437 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
438 EXPECT_TRUE(client_
->needs_begin_frames());
440 scheduler_
->SetChildrenNeedBeginFrames(true);
443 EXPECT_SCOPED(AdvanceFrame());
444 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
445 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
446 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
447 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
448 EXPECT_TRUE(client_
->needs_begin_frames());
451 TEST_F(SchedulerTest
, SendBeginFramesToChildrenWithoutCommit
) {
452 scheduler_settings_
.use_external_begin_frame_source
= true;
453 scheduler_settings_
.forward_begin_frames_to_children
= true;
454 SetUpScheduler(true);
456 EXPECT_FALSE(client_
->needs_begin_frames());
457 scheduler_
->SetChildrenNeedBeginFrames(true);
458 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
459 EXPECT_TRUE(client_
->needs_begin_frames());
462 EXPECT_SCOPED(AdvanceFrame());
463 EXPECT_TRUE(client_
->begin_frame_is_sent_to_children());
466 TEST_F(SchedulerTest
, RequestCommit
) {
467 scheduler_settings_
.use_external_begin_frame_source
= true;
468 SetUpScheduler(true);
470 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
471 scheduler_
->SetNeedsCommit();
472 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
475 EXPECT_SCOPED(AdvanceFrame());
476 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
477 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
478 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
479 EXPECT_TRUE(client_
->needs_begin_frames());
482 // If we don't swap on the deadline, we wait for the next BeginFrame.
483 task_runner().RunPendingTasks(); // Run posted deadline.
484 EXPECT_NO_ACTION(client_
);
485 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
486 EXPECT_TRUE(client_
->needs_begin_frames());
489 // NotifyReadyToCommit should trigger the commit.
490 scheduler_
->NotifyBeginMainFrameStarted();
491 scheduler_
->NotifyReadyToCommit();
492 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
493 EXPECT_TRUE(client_
->needs_begin_frames());
496 // BeginImplFrame should prepare the draw.
497 EXPECT_SCOPED(AdvanceFrame());
498 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
499 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
500 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
501 EXPECT_TRUE(client_
->needs_begin_frames());
504 // BeginImplFrame deadline should draw.
505 task_runner().RunPendingTasks(); // Run posted deadline.
506 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
507 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
508 EXPECT_TRUE(client_
->needs_begin_frames());
511 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
512 // to avoid excessive toggles.
513 EXPECT_SCOPED(AdvanceFrame());
514 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
515 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
518 task_runner().RunPendingTasks(); // Run posted deadline.
519 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client_
);
523 TEST_F(SchedulerTest
, RequestCommitAfterBeginMainFrameSent
) {
524 scheduler_settings_
.use_external_begin_frame_source
= true;
525 SetUpScheduler(true);
527 // SetNeedsCommit should begin the frame.
528 scheduler_
->SetNeedsCommit();
529 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
532 EXPECT_SCOPED(AdvanceFrame());
533 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
534 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
535 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
537 EXPECT_TRUE(client_
->needs_begin_frames());
540 // Now SetNeedsCommit again. Calling here means we need a second commit.
541 scheduler_
->SetNeedsCommit();
542 EXPECT_EQ(client_
->num_actions_(), 0);
545 // Finish the first commit.
546 scheduler_
->NotifyBeginMainFrameStarted();
547 scheduler_
->NotifyReadyToCommit();
548 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
549 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
551 task_runner().RunPendingTasks(); // Run posted deadline.
552 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
553 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
554 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
556 // Because we just swapped, the Scheduler should also request the next
557 // BeginImplFrame from the OutputSurface.
558 EXPECT_TRUE(client_
->needs_begin_frames());
560 // Since another commit is needed, the next BeginImplFrame should initiate
561 // the second commit.
562 EXPECT_SCOPED(AdvanceFrame());
563 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
564 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
565 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
568 // Finishing the commit before the deadline should post a new deadline task
569 // to trigger the deadline early.
570 scheduler_
->NotifyBeginMainFrameStarted();
571 scheduler_
->NotifyReadyToCommit();
572 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
573 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
575 task_runner().RunPendingTasks(); // Run posted deadline.
576 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
577 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
578 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
579 EXPECT_TRUE(client_
->needs_begin_frames());
582 // On the next BeginImplFrame, verify we go back to a quiescent state and
583 // no longer request BeginImplFrames.
584 EXPECT_SCOPED(AdvanceFrame());
585 task_runner().RunPendingTasks(); // Run posted deadline.
586 EXPECT_FALSE(client_
->needs_begin_frames());
590 class SchedulerClientThatsetNeedsDrawInsideDraw
: public FakeSchedulerClient
{
592 SchedulerClientThatsetNeedsDrawInsideDraw()
593 : FakeSchedulerClient(), request_redraws_(false) {}
595 void ScheduledActionSendBeginMainFrame() override
{}
597 void SetRequestRedrawsInsideDraw(bool enable
) { request_redraws_
= enable
; }
599 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
600 // Only SetNeedsRedraw the first time this is called
601 if (request_redraws_
) {
602 scheduler_
->SetNeedsRedraw();
604 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
607 DrawResult
ScheduledActionDrawAndSwapForced() override
{
612 void ScheduledActionCommit() override
{}
613 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{}
616 bool request_redraws_
;
619 // Tests for two different situations:
620 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
621 // a ScheduledActionDrawAndSwap
622 // 2. the scheduler drawing twice inside a single tick
623 TEST_F(SchedulerTest
, RequestRedrawInsideDraw
) {
624 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
625 new SchedulerClientThatsetNeedsDrawInsideDraw
;
626 scheduler_settings_
.use_external_begin_frame_source
= true;
627 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
628 client
->SetRequestRedrawsInsideDraw(true);
630 scheduler_
->SetNeedsRedraw();
631 EXPECT_TRUE(scheduler_
->RedrawPending());
632 EXPECT_TRUE(client
->needs_begin_frames());
633 EXPECT_EQ(0, client
->num_draws());
635 EXPECT_SCOPED(AdvanceFrame());
636 task_runner().RunPendingTasks(); // Run posted deadline.
637 EXPECT_EQ(1, client
->num_draws());
638 EXPECT_TRUE(scheduler_
->RedrawPending());
639 EXPECT_TRUE(client
->needs_begin_frames());
641 client
->SetRequestRedrawsInsideDraw(false);
643 EXPECT_SCOPED(AdvanceFrame());
644 task_runner().RunPendingTasks(); // Run posted deadline.
645 EXPECT_EQ(2, client_
->num_draws());
646 EXPECT_FALSE(scheduler_
->RedrawPending());
647 EXPECT_TRUE(client
->needs_begin_frames());
649 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
651 EXPECT_SCOPED(AdvanceFrame());
652 task_runner().RunPendingTasks(); // Run posted deadline.
653 EXPECT_EQ(2, client
->num_draws());
654 EXPECT_FALSE(scheduler_
->RedrawPending());
655 EXPECT_FALSE(client
->needs_begin_frames());
658 // Test that requesting redraw inside a failed draw doesn't lose the request.
659 TEST_F(SchedulerTest
, RequestRedrawInsideFailedDraw
) {
660 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
661 new SchedulerClientThatsetNeedsDrawInsideDraw
;
662 scheduler_settings_
.use_external_begin_frame_source
= true;
663 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
665 client
->SetRequestRedrawsInsideDraw(true);
666 client
->SetDrawWillHappen(false);
668 scheduler_
->SetNeedsRedraw();
669 EXPECT_TRUE(scheduler_
->RedrawPending());
670 EXPECT_TRUE(client
->needs_begin_frames());
671 EXPECT_EQ(0, client
->num_draws());
674 EXPECT_SCOPED(AdvanceFrame());
675 task_runner().RunPendingTasks(); // Run posted deadline.
676 EXPECT_EQ(1, client
->num_draws());
678 // We have a commit pending and the draw failed, and we didn't lose the redraw
680 EXPECT_TRUE(scheduler_
->CommitPending());
681 EXPECT_TRUE(scheduler_
->RedrawPending());
682 EXPECT_TRUE(client
->needs_begin_frames());
684 client
->SetRequestRedrawsInsideDraw(false);
686 // Fail the draw again.
687 EXPECT_SCOPED(AdvanceFrame());
688 task_runner().RunPendingTasks(); // Run posted deadline.
689 EXPECT_EQ(2, client
->num_draws());
690 EXPECT_TRUE(scheduler_
->CommitPending());
691 EXPECT_TRUE(scheduler_
->RedrawPending());
692 EXPECT_TRUE(client
->needs_begin_frames());
694 // Draw successfully.
695 client
->SetDrawWillHappen(true);
696 EXPECT_SCOPED(AdvanceFrame());
697 task_runner().RunPendingTasks(); // Run posted deadline.
698 EXPECT_EQ(3, client
->num_draws());
699 EXPECT_TRUE(scheduler_
->CommitPending());
700 EXPECT_FALSE(scheduler_
->RedrawPending());
701 EXPECT_TRUE(client
->needs_begin_frames());
704 class SchedulerClientThatSetNeedsCommitInsideDraw
: public FakeSchedulerClient
{
706 SchedulerClientThatSetNeedsCommitInsideDraw()
707 : set_needs_commit_on_next_draw_(false) {}
709 void ScheduledActionSendBeginMainFrame() override
{}
710 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
711 // Only SetNeedsCommit the first time this is called
712 if (set_needs_commit_on_next_draw_
) {
713 scheduler_
->SetNeedsCommit();
714 set_needs_commit_on_next_draw_
= false;
716 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
719 DrawResult
ScheduledActionDrawAndSwapForced() override
{
724 void ScheduledActionCommit() override
{}
725 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{}
727 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_
= true; }
730 bool set_needs_commit_on_next_draw_
;
733 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
734 // happen inside a ScheduledActionDrawAndSwap
735 TEST_F(SchedulerTest
, RequestCommitInsideDraw
) {
736 SchedulerClientThatSetNeedsCommitInsideDraw
* client
=
737 new SchedulerClientThatSetNeedsCommitInsideDraw
;
739 scheduler_settings_
.use_external_begin_frame_source
= true;
740 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
742 EXPECT_FALSE(client
->needs_begin_frames());
743 scheduler_
->SetNeedsRedraw();
744 EXPECT_TRUE(scheduler_
->RedrawPending());
745 EXPECT_EQ(0, client
->num_draws());
746 EXPECT_TRUE(client
->needs_begin_frames());
748 client
->SetNeedsCommitOnNextDraw();
749 EXPECT_SCOPED(AdvanceFrame());
750 client
->SetNeedsCommitOnNextDraw();
751 task_runner().RunPendingTasks(); // Run posted deadline.
752 EXPECT_EQ(1, client
->num_draws());
753 EXPECT_TRUE(scheduler_
->CommitPending());
754 EXPECT_TRUE(client
->needs_begin_frames());
755 scheduler_
->NotifyBeginMainFrameStarted();
756 scheduler_
->NotifyReadyToCommit();
758 EXPECT_SCOPED(AdvanceFrame());
759 task_runner().RunPendingTasks(); // Run posted deadline.
760 EXPECT_EQ(2, client
->num_draws());
762 EXPECT_FALSE(scheduler_
->RedrawPending());
763 EXPECT_FALSE(scheduler_
->CommitPending());
764 EXPECT_TRUE(client
->needs_begin_frames());
766 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
768 EXPECT_SCOPED(AdvanceFrame());
769 task_runner().RunPendingTasks(); // Run posted deadline.
770 EXPECT_EQ(2, client
->num_draws());
771 EXPECT_FALSE(scheduler_
->RedrawPending());
772 EXPECT_FALSE(scheduler_
->CommitPending());
773 EXPECT_FALSE(client
->needs_begin_frames());
776 // Tests that when a draw fails then the pending commit should not be dropped.
777 TEST_F(SchedulerTest
, RequestCommitInsideFailedDraw
) {
778 SchedulerClientThatsetNeedsDrawInsideDraw
* client
=
779 new SchedulerClientThatsetNeedsDrawInsideDraw
;
780 scheduler_settings_
.use_external_begin_frame_source
= true;
781 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
783 client
->SetDrawWillHappen(false);
785 scheduler_
->SetNeedsRedraw();
786 EXPECT_TRUE(scheduler_
->RedrawPending());
787 EXPECT_TRUE(client
->needs_begin_frames());
788 EXPECT_EQ(0, client
->num_draws());
791 EXPECT_SCOPED(AdvanceFrame());
792 task_runner().RunPendingTasks(); // Run posted deadline.
793 EXPECT_EQ(1, client
->num_draws());
795 // We have a commit pending and the draw failed, and we didn't lose the commit
797 EXPECT_TRUE(scheduler_
->CommitPending());
798 EXPECT_TRUE(scheduler_
->RedrawPending());
799 EXPECT_TRUE(client
->needs_begin_frames());
801 // Fail the draw again.
802 EXPECT_SCOPED(AdvanceFrame());
804 task_runner().RunPendingTasks(); // Run posted deadline.
805 EXPECT_EQ(2, client
->num_draws());
806 EXPECT_TRUE(scheduler_
->CommitPending());
807 EXPECT_TRUE(scheduler_
->RedrawPending());
808 EXPECT_TRUE(client
->needs_begin_frames());
810 // Draw successfully.
811 client
->SetDrawWillHappen(true);
812 EXPECT_SCOPED(AdvanceFrame());
813 task_runner().RunPendingTasks(); // Run posted deadline.
814 EXPECT_EQ(3, client
->num_draws());
815 EXPECT_TRUE(scheduler_
->CommitPending());
816 EXPECT_FALSE(scheduler_
->RedrawPending());
817 EXPECT_TRUE(client
->needs_begin_frames());
820 TEST_F(SchedulerTest
, NoSwapWhenDrawFails
) {
821 SchedulerClientThatSetNeedsCommitInsideDraw
* client
=
822 new SchedulerClientThatSetNeedsCommitInsideDraw
;
823 scheduler_settings_
.use_external_begin_frame_source
= true;
824 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
826 scheduler_
->SetNeedsRedraw();
827 EXPECT_TRUE(scheduler_
->RedrawPending());
828 EXPECT_TRUE(client
->needs_begin_frames());
829 EXPECT_EQ(0, client
->num_draws());
831 // Draw successfully, this starts a new frame.
832 client
->SetNeedsCommitOnNextDraw();
833 EXPECT_SCOPED(AdvanceFrame());
834 task_runner().RunPendingTasks(); // Run posted deadline.
835 EXPECT_EQ(1, client
->num_draws());
837 scheduler_
->SetNeedsRedraw();
838 EXPECT_TRUE(scheduler_
->RedrawPending());
839 EXPECT_TRUE(client
->needs_begin_frames());
841 // Fail to draw, this should not start a frame.
842 client
->SetDrawWillHappen(false);
843 client
->SetNeedsCommitOnNextDraw();
844 EXPECT_SCOPED(AdvanceFrame());
845 task_runner().RunPendingTasks(); // Run posted deadline.
846 EXPECT_EQ(2, client
->num_draws());
849 class SchedulerClientNeedsPrepareTilesInDraw
: public FakeSchedulerClient
{
851 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
852 scheduler_
->SetNeedsPrepareTiles();
853 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
857 // Test prepare tiles is independant of draws.
858 TEST_F(SchedulerTest
, PrepareTiles
) {
859 SchedulerClientNeedsPrepareTilesInDraw
* client
=
860 new SchedulerClientNeedsPrepareTilesInDraw
;
861 scheduler_settings_
.use_external_begin_frame_source
= true;
862 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
864 // Request both draw and prepare tiles. PrepareTiles shouldn't
865 // be trigged until BeginImplFrame.
867 scheduler_
->SetNeedsPrepareTiles();
868 scheduler_
->SetNeedsRedraw();
869 EXPECT_TRUE(scheduler_
->RedrawPending());
870 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
871 EXPECT_TRUE(client
->needs_begin_frames());
872 EXPECT_EQ(0, client
->num_draws());
873 EXPECT_FALSE(client
->HasAction("ScheduledActionPrepareTiles"));
874 EXPECT_FALSE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
876 // We have no immediate actions to perform, so the BeginImplFrame should post
877 // the deadline task.
879 EXPECT_SCOPED(AdvanceFrame());
880 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
881 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
882 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
884 // On the deadline, he actions should have occured in the right order.
886 task_runner().RunPendingTasks(); // Run posted deadline.
887 EXPECT_EQ(1, client
->num_draws());
888 EXPECT_TRUE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
889 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
890 EXPECT_LT(client
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
891 client
->ActionIndex("ScheduledActionPrepareTiles"));
892 EXPECT_FALSE(scheduler_
->RedrawPending());
893 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
894 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
896 // Request a draw. We don't need a PrepareTiles yet.
898 scheduler_
->SetNeedsRedraw();
899 EXPECT_TRUE(scheduler_
->RedrawPending());
900 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
901 EXPECT_TRUE(client
->needs_begin_frames());
902 EXPECT_EQ(0, client
->num_draws());
904 // We have no immediate actions to perform, so the BeginImplFrame should post
905 // the deadline task.
907 EXPECT_SCOPED(AdvanceFrame());
908 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
909 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
910 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
912 // Draw. The draw will trigger SetNeedsPrepareTiles, and
913 // then the PrepareTiles action will be triggered after the Draw.
914 // Afterwards, neither a draw nor PrepareTiles are pending.
916 task_runner().RunPendingTasks(); // Run posted deadline.
917 EXPECT_EQ(1, client
->num_draws());
918 EXPECT_TRUE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
919 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
920 EXPECT_LT(client
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
921 client
->ActionIndex("ScheduledActionPrepareTiles"));
922 EXPECT_FALSE(scheduler_
->RedrawPending());
923 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
924 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
926 // We need a BeginImplFrame where we don't swap to go idle.
928 EXPECT_SCOPED(AdvanceFrame());
929 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
930 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
932 task_runner().RunPendingTasks(); // Run posted deadline.
933 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client
);
934 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
935 EXPECT_EQ(0, client
->num_draws());
937 // Now trigger a PrepareTiles outside of a draw. We will then need
938 // a begin-frame for the PrepareTiles, but we don't need a draw.
940 EXPECT_FALSE(client
->needs_begin_frames());
941 scheduler_
->SetNeedsPrepareTiles();
942 EXPECT_TRUE(client
->needs_begin_frames());
943 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
944 EXPECT_FALSE(scheduler_
->RedrawPending());
946 // BeginImplFrame. There will be no draw, only PrepareTiles.
948 EXPECT_SCOPED(AdvanceFrame());
949 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
950 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
952 task_runner().RunPendingTasks(); // Run posted deadline.
953 EXPECT_EQ(0, client
->num_draws());
954 EXPECT_FALSE(client
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
955 EXPECT_TRUE(client
->HasAction("ScheduledActionPrepareTiles"));
956 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
959 // Test that PrepareTiles only happens once per frame. If an external caller
960 // initiates it, then the state machine should not PrepareTiles on that frame.
961 TEST_F(SchedulerTest
, PrepareTilesOncePerFrame
) {
962 scheduler_settings_
.use_external_begin_frame_source
= true;
963 SetUpScheduler(true);
965 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
967 scheduler_
->SetNeedsPrepareTiles();
968 scheduler_
->SetNeedsRedraw();
970 EXPECT_SCOPED(AdvanceFrame());
971 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
972 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
973 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
975 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
976 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
977 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
980 task_runner().RunPendingTasks(); // Run posted deadline.
981 EXPECT_EQ(1, client_
->num_draws());
982 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
983 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
984 EXPECT_FALSE(scheduler_
->RedrawPending());
985 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
986 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
988 // Next frame without DidPrepareTiles should PrepareTiles with draw.
989 scheduler_
->SetNeedsPrepareTiles();
990 scheduler_
->SetNeedsRedraw();
992 EXPECT_SCOPED(AdvanceFrame());
993 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
994 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
995 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
998 task_runner().RunPendingTasks(); // Run posted deadline.
999 EXPECT_EQ(1, client_
->num_draws());
1000 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1001 EXPECT_TRUE(client_
->HasAction("ScheduledActionPrepareTiles"));
1002 EXPECT_LT(client_
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1003 client_
->ActionIndex("ScheduledActionPrepareTiles"));
1004 EXPECT_FALSE(scheduler_
->RedrawPending());
1005 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1006 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1007 scheduler_
->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1009 // If we get another DidPrepareTiles within the same frame, we should
1010 // not PrepareTiles on the next frame.
1011 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1012 scheduler_
->SetNeedsPrepareTiles();
1013 scheduler_
->SetNeedsRedraw();
1015 EXPECT_SCOPED(AdvanceFrame());
1016 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1017 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1018 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1020 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1023 task_runner().RunPendingTasks(); // Run posted deadline.
1024 EXPECT_EQ(1, client_
->num_draws());
1025 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1026 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1027 EXPECT_FALSE(scheduler_
->RedrawPending());
1028 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1030 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1031 // frame. This verifies we don't alternate calling PrepareTiles once and
1033 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1034 scheduler_
->DidPrepareTiles(); // An explicit PrepareTiles.
1035 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1036 scheduler_
->SetNeedsPrepareTiles();
1037 scheduler_
->SetNeedsRedraw();
1039 EXPECT_SCOPED(AdvanceFrame());
1040 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1041 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1042 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1044 EXPECT_TRUE(scheduler_
->PrepareTilesPending());
1047 task_runner().RunPendingTasks(); // Run posted deadline.
1048 EXPECT_EQ(1, client_
->num_draws());
1049 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1050 EXPECT_FALSE(client_
->HasAction("ScheduledActionPrepareTiles"));
1051 EXPECT_FALSE(scheduler_
->RedrawPending());
1052 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1054 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1055 scheduler_
->SetNeedsPrepareTiles();
1056 scheduler_
->SetNeedsRedraw();
1058 EXPECT_SCOPED(AdvanceFrame());
1059 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1060 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1061 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1064 task_runner().RunPendingTasks(); // Run posted deadline.
1065 EXPECT_EQ(1, client_
->num_draws());
1066 EXPECT_TRUE(client_
->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1067 EXPECT_TRUE(client_
->HasAction("ScheduledActionPrepareTiles"));
1068 EXPECT_LT(client_
->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1069 client_
->ActionIndex("ScheduledActionPrepareTiles"));
1070 EXPECT_FALSE(scheduler_
->RedrawPending());
1071 EXPECT_FALSE(scheduler_
->PrepareTilesPending());
1072 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1073 scheduler_
->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1076 TEST_F(SchedulerTest
, TriggerBeginFrameDeadlineEarly
) {
1077 SchedulerClientNeedsPrepareTilesInDraw
* client
=
1078 new SchedulerClientNeedsPrepareTilesInDraw
;
1079 scheduler_settings_
.use_external_begin_frame_source
= true;
1080 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1082 scheduler_
->SetNeedsRedraw();
1083 EXPECT_SCOPED(AdvanceFrame());
1085 // The deadline should be zero since there is no work other than drawing
1087 EXPECT_EQ(base::TimeTicks(), client
->posted_begin_impl_frame_deadline());
1090 class SchedulerClientWithFixedEstimates
: public FakeSchedulerClient
{
1092 SchedulerClientWithFixedEstimates(
1093 base::TimeDelta draw_duration
,
1094 base::TimeDelta begin_main_frame_to_commit_duration
,
1095 base::TimeDelta commit_to_activate_duration
)
1096 : draw_duration_(draw_duration
),
1097 begin_main_frame_to_commit_duration_(
1098 begin_main_frame_to_commit_duration
),
1099 commit_to_activate_duration_(commit_to_activate_duration
) {}
1101 base::TimeDelta
DrawDurationEstimate() override
{ return draw_duration_
; }
1102 base::TimeDelta
BeginMainFrameToCommitDurationEstimate() override
{
1103 return begin_main_frame_to_commit_duration_
;
1105 base::TimeDelta
CommitToActivateDurationEstimate() override
{
1106 return commit_to_activate_duration_
;
1110 base::TimeDelta draw_duration_
;
1111 base::TimeDelta begin_main_frame_to_commit_duration_
;
1112 base::TimeDelta commit_to_activate_duration_
;
1115 void SchedulerTest::MainFrameInHighLatencyMode(
1116 int64 begin_main_frame_to_commit_estimate_in_ms
,
1117 int64 commit_to_activate_estimate_in_ms
,
1118 bool impl_latency_takes_priority
,
1119 bool should_send_begin_main_frame
) {
1120 // Set up client with specified estimates (draw duration is set to 1).
1121 SchedulerClientWithFixedEstimates
* client
=
1122 new SchedulerClientWithFixedEstimates(
1123 base::TimeDelta::FromMilliseconds(1),
1124 base::TimeDelta::FromMilliseconds(
1125 begin_main_frame_to_commit_estimate_in_ms
),
1126 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms
));
1128 scheduler_settings_
.use_external_begin_frame_source
= true;
1129 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1131 scheduler_
->SetImplLatencyTakesPriority(impl_latency_takes_priority
);
1133 // Impl thread hits deadline before commit finishes.
1134 scheduler_
->SetNeedsCommit();
1135 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1136 EXPECT_SCOPED(AdvanceFrame());
1137 EXPECT_FALSE(scheduler_
->MainThreadIsInHighLatencyMode());
1138 task_runner().RunPendingTasks(); // Run posted deadline.
1139 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1140 scheduler_
->NotifyBeginMainFrameStarted();
1141 scheduler_
->NotifyReadyToCommit();
1142 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1143 EXPECT_TRUE(client
->HasAction("ScheduledActionSendBeginMainFrame"));
1146 scheduler_
->SetNeedsCommit();
1147 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1148 EXPECT_SCOPED(AdvanceFrame());
1149 EXPECT_TRUE(scheduler_
->MainThreadIsInHighLatencyMode());
1150 task_runner().RunPendingTasks(); // Run posted deadline.
1151 EXPECT_EQ(scheduler_
->MainThreadIsInHighLatencyMode(),
1152 should_send_begin_main_frame
);
1153 EXPECT_EQ(client
->HasAction("ScheduledActionSendBeginMainFrame"),
1154 should_send_begin_main_frame
);
1157 TEST_F(SchedulerTest
,
1158 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline
) {
1159 // Set up client so that estimates indicate that we can commit and activate
1160 // before the deadline (~8ms by default).
1161 MainFrameInHighLatencyMode(1, 1, false, false);
1164 TEST_F(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong
) {
1165 // Set up client so that estimates indicate that the commit cannot finish
1166 // before the deadline (~8ms by default).
1167 MainFrameInHighLatencyMode(10, 1, false, true);
1170 TEST_F(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong
) {
1171 // Set up client so that estimates indicate that the activate cannot finish
1172 // before the deadline (~8ms by default).
1173 MainFrameInHighLatencyMode(1, 10, false, true);
1176 TEST_F(SchedulerTest
, NotSkipMainFrameInPreferImplLatencyMode
) {
1177 // Set up client so that estimates indicate that we can commit and activate
1178 // before the deadline (~8ms by default), but also enable impl latency takes
1180 MainFrameInHighLatencyMode(1, 1, true, true);
1183 TEST_F(SchedulerTest
, PollForCommitCompletion
) {
1184 // Since we are simulating a long commit, set up a client with draw duration
1185 // estimates that prevent skipping main frames to get to low latency mode.
1186 SchedulerClientWithFixedEstimates
* client
=
1187 new SchedulerClientWithFixedEstimates(
1188 base::TimeDelta::FromMilliseconds(1),
1189 base::TimeDelta::FromMilliseconds(32),
1190 base::TimeDelta::FromMilliseconds(32));
1191 scheduler_settings_
.use_external_begin_frame_source
= true;
1192 SetUpScheduler(make_scoped_ptr(client
).Pass(), true);
1194 client
->set_log_anticipated_draw_time_change(true);
1196 BeginFrameArgs frame_args
=
1197 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1198 frame_args
.interval
= base::TimeDelta::FromMilliseconds(1000);
1200 // At this point, we've drawn a frame. Start another commit, but hold off on
1201 // the NotifyReadyToCommit for now.
1202 EXPECT_FALSE(scheduler_
->CommitPending());
1203 scheduler_
->SetNeedsCommit();
1204 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args
);
1205 EXPECT_TRUE(scheduler_
->CommitPending());
1207 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1208 // blocking on the renderer.
1209 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1210 task_runner().RunPendingTasks(); // Run posted deadline.
1211 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1212 scheduler_
->DidSwapBuffers();
1214 // Spin the event loop a few times and make sure we get more
1215 // DidAnticipateDrawTimeChange calls every time.
1216 int actions_so_far
= client
->num_actions_();
1218 // Does three iterations to make sure that the timer is properly repeating.
1219 for (int i
= 0; i
< 3; ++i
) {
1220 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1221 task_runner().DelayToNextTaskTime().InMicroseconds())
1222 << scheduler_
->AsValue()->ToString();
1223 task_runner().RunPendingTasks();
1224 EXPECT_GT(client
->num_actions_(), actions_so_far
);
1225 EXPECT_STREQ(client
->Action(client
->num_actions_() - 1),
1226 "DidAnticipatedDrawTimeChange");
1227 actions_so_far
= client
->num_actions_();
1230 // Do the same thing after BeginMainFrame starts but still before activation.
1231 scheduler_
->NotifyBeginMainFrameStarted();
1232 for (int i
= 0; i
< 3; ++i
) {
1233 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1234 task_runner().DelayToNextTaskTime().InMicroseconds())
1235 << scheduler_
->AsValue()->ToString();
1236 task_runner().RunPendingTasks();
1237 EXPECT_GT(client
->num_actions_(), actions_so_far
);
1238 EXPECT_STREQ(client
->Action(client
->num_actions_() - 1),
1239 "DidAnticipatedDrawTimeChange");
1240 actions_so_far
= client
->num_actions_();
1244 TEST_F(SchedulerTest
, BeginRetroFrame
) {
1245 scheduler_settings_
.use_external_begin_frame_source
= true;
1246 SetUpScheduler(true);
1248 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1249 scheduler_
->SetNeedsCommit();
1250 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1253 // Create a BeginFrame with a long deadline to avoid race conditions.
1254 // This is the first BeginFrame, which will be handled immediately.
1255 BeginFrameArgs args
=
1256 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1257 args
.deadline
+= base::TimeDelta::FromHours(1);
1258 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1259 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1260 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1261 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1262 EXPECT_TRUE(client_
->needs_begin_frames());
1265 // Queue BeginFrames while we are still handling the previous BeginFrame.
1266 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1267 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1268 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1269 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1271 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1272 task_runner().RunPendingTasks(); // Run posted deadline.
1273 EXPECT_NO_ACTION(client_
);
1274 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1275 EXPECT_TRUE(client_
->needs_begin_frames());
1278 // NotifyReadyToCommit should trigger the commit.
1279 scheduler_
->NotifyBeginMainFrameStarted();
1280 scheduler_
->NotifyReadyToCommit();
1281 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1282 EXPECT_TRUE(client_
->needs_begin_frames());
1285 // BeginImplFrame should prepare the draw.
1286 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1287 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1288 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1289 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1290 EXPECT_TRUE(client_
->needs_begin_frames());
1293 // BeginImplFrame deadline should draw.
1294 task_runner().RunPendingTasks(); // Run posted deadline.
1295 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
1296 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1297 EXPECT_TRUE(client_
->needs_begin_frames());
1300 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1301 // to avoid excessive toggles.
1302 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1303 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
1304 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1307 task_runner().RunPendingTasks(); // Run posted deadline.
1308 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client_
);
1312 TEST_F(SchedulerTest
, BeginRetroFrame_SwapThrottled
) {
1313 scheduler_settings_
.use_external_begin_frame_source
= true;
1314 SetUpScheduler(true);
1316 scheduler_
->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1318 // To test swap ack throttling, this test disables automatic swap acks.
1319 scheduler_
->SetMaxSwapsPending(1);
1320 client_
->SetAutomaticSwapAck(false);
1322 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1324 scheduler_
->SetNeedsCommit();
1325 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1328 EXPECT_SCOPED(AdvanceFrame());
1329 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1330 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1331 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1332 EXPECT_TRUE(client_
->needs_begin_frames());
1335 // Queue BeginFrame while we are still handling the previous BeginFrame.
1336 SendNextBeginFrame();
1337 EXPECT_NO_ACTION(client_
);
1338 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1339 EXPECT_TRUE(client_
->needs_begin_frames());
1342 // NotifyReadyToCommit should trigger the pending commit and draw.
1343 scheduler_
->NotifyBeginMainFrameStarted();
1344 scheduler_
->NotifyReadyToCommit();
1345 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1346 EXPECT_TRUE(client_
->needs_begin_frames());
1349 // Swapping will put us into a swap throttled state.
1350 // Run posted deadline.
1351 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1352 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1353 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1354 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1355 EXPECT_TRUE(client_
->needs_begin_frames());
1358 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1359 // but not a BeginMainFrame or draw.
1360 scheduler_
->SetNeedsCommit();
1361 scheduler_
->SetNeedsRedraw();
1362 // Run posted BeginRetroFrame.
1363 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false));
1364 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1365 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1366 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1367 EXPECT_TRUE(client_
->needs_begin_frames());
1370 // Let time pass sufficiently beyond the regular deadline but not beyond the
1372 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1373 base::TimeDelta::FromMicroseconds(1));
1374 task_runner().RunUntilTime(now_src()->Now());
1375 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1377 // Take us out of a swap throttled state.
1378 scheduler_
->DidSwapBuffersComplete();
1379 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_
);
1380 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1381 EXPECT_TRUE(client_
->needs_begin_frames());
1384 // Verify that the deadline was rescheduled.
1385 task_runner().RunUntilTime(now_src()->Now());
1386 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
1387 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1388 EXPECT_TRUE(client_
->needs_begin_frames());
1392 TEST_F(SchedulerTest
, RetroFrameDoesNotExpireTooEarly
) {
1393 scheduler_settings_
.use_external_begin_frame_source
= true;
1394 SetUpScheduler(true);
1396 scheduler_
->SetNeedsCommit();
1397 EXPECT_TRUE(client_
->needs_begin_frames());
1398 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1401 EXPECT_SCOPED(AdvanceFrame());
1402 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1403 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1404 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1407 scheduler_
->NotifyBeginMainFrameStarted();
1410 SendNextBeginFrame();
1411 // This BeginFrame is queued up as a retro frame.
1412 EXPECT_NO_ACTION(client_
);
1413 // The previous deadline is still pending.
1414 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1417 // This commit should schedule the (previous) deadline to trigger immediately.
1418 scheduler_
->NotifyReadyToCommit();
1419 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1422 // The deadline task should trigger causing a draw.
1423 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1424 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1425 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1426 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1430 scheduler_
->SetNeedsAnimate();
1431 scheduler_
->SetNeedsRedraw();
1432 EXPECT_NO_ACTION(client_
);
1434 // Let's advance sufficiently past the next frame's deadline.
1435 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1436 BeginFrameArgs::DefaultEstimatedParentDrawTime() +
1437 base::TimeDelta::FromMicroseconds(1));
1439 // The retro frame hasn't expired yet.
1440 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(false));
1441 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1442 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1443 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1445 // This is an immediate deadline case.
1447 task_runner().RunPendingTasks();
1448 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1449 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
);
1452 TEST_F(SchedulerTest
, RetroFrameDoesNotExpireTooLate
) {
1453 scheduler_settings_
.use_external_begin_frame_source
= true;
1454 SetUpScheduler(true);
1456 scheduler_
->SetNeedsCommit();
1457 EXPECT_TRUE(client_
->needs_begin_frames());
1458 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1461 EXPECT_SCOPED(AdvanceFrame());
1462 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1463 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1464 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1467 scheduler_
->NotifyBeginMainFrameStarted();
1470 SendNextBeginFrame();
1471 // This BeginFrame is queued up as a retro frame.
1472 EXPECT_NO_ACTION(client_
);
1473 // The previous deadline is still pending.
1474 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1477 // This commit should schedule the (previous) deadline to trigger immediately.
1478 scheduler_
->NotifyReadyToCommit();
1479 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1482 // The deadline task should trigger causing a draw.
1483 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1484 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1485 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1486 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1490 scheduler_
->SetNeedsAnimate();
1491 scheduler_
->SetNeedsRedraw();
1492 EXPECT_NO_ACTION(client_
);
1494 // Let's advance sufficiently past the next frame's deadline.
1495 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() +
1496 base::TimeDelta::FromMicroseconds(1));
1498 // The retro frame should've expired.
1499 EXPECT_NO_ACTION(client_
);
1502 void SchedulerTest::BeginFramesNotFromClient(
1503 bool use_external_begin_frame_source
,
1504 bool throttle_frame_production
) {
1505 scheduler_settings_
.use_external_begin_frame_source
=
1506 use_external_begin_frame_source
;
1507 scheduler_settings_
.throttle_frame_production
= throttle_frame_production
;
1508 SetUpScheduler(true);
1510 // SetNeedsCommit should begin the frame on the next BeginImplFrame
1511 // without calling SetNeedsBeginFrame.
1512 scheduler_
->SetNeedsCommit();
1513 EXPECT_NO_ACTION(client_
);
1516 // When the client-driven BeginFrame are disabled, the scheduler posts it's
1517 // own BeginFrame tasks.
1518 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1519 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1520 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1521 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1524 // If we don't swap on the deadline, we wait for the next BeginFrame.
1525 task_runner().RunPendingTasks(); // Run posted deadline.
1526 EXPECT_NO_ACTION(client_
);
1527 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1530 // NotifyReadyToCommit should trigger the commit.
1531 scheduler_
->NotifyBeginMainFrameStarted();
1532 scheduler_
->NotifyReadyToCommit();
1533 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1536 // BeginImplFrame should prepare the draw.
1537 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1538 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1539 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1540 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1543 // BeginImplFrame deadline should draw.
1544 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1545 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
1546 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1549 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1550 // to avoid excessive toggles.
1551 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1552 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_
);
1553 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1556 // Make sure SetNeedsBeginFrame isn't called on the client
1557 // when the BeginFrame is no longer needed.
1558 task_runner().RunPendingTasks(); // Run posted deadline.
1559 EXPECT_NO_ACTION(client_
);
1563 TEST_F(SchedulerTest
, SyntheticBeginFrames
) {
1564 bool use_external_begin_frame_source
= false;
1565 bool throttle_frame_production
= true;
1566 BeginFramesNotFromClient(use_external_begin_frame_source
,
1567 throttle_frame_production
);
1570 TEST_F(SchedulerTest
, VSyncThrottlingDisabled
) {
1571 bool use_external_begin_frame_source
= true;
1572 bool throttle_frame_production
= false;
1573 BeginFramesNotFromClient(use_external_begin_frame_source
,
1574 throttle_frame_production
);
1577 TEST_F(SchedulerTest
, SyntheticBeginFrames_And_VSyncThrottlingDisabled
) {
1578 bool use_external_begin_frame_source
= false;
1579 bool throttle_frame_production
= false;
1580 BeginFramesNotFromClient(use_external_begin_frame_source
,
1581 throttle_frame_production
);
1584 void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
1585 bool use_external_begin_frame_source
,
1586 bool throttle_frame_production
) {
1587 scheduler_settings_
.use_external_begin_frame_source
=
1588 use_external_begin_frame_source
;
1589 scheduler_settings_
.throttle_frame_production
= throttle_frame_production
;
1590 SetUpScheduler(true);
1592 scheduler_
->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1594 // To test swap ack throttling, this test disables automatic swap acks.
1595 scheduler_
->SetMaxSwapsPending(1);
1596 client_
->SetAutomaticSwapAck(false);
1598 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1600 scheduler_
->SetNeedsCommit();
1601 EXPECT_NO_ACTION(client_
);
1604 // Trigger the first BeginImplFrame and BeginMainFrame
1605 EXPECT_SCOPED(AdvanceFrame());
1606 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1607 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1608 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1611 // NotifyReadyToCommit should trigger the pending commit and draw.
1612 scheduler_
->NotifyBeginMainFrameStarted();
1613 scheduler_
->NotifyReadyToCommit();
1614 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1617 // Swapping will put us into a swap throttled state.
1618 // Run posted deadline.
1619 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1620 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
1621 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
1622 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1625 // While swap throttled, BeginFrames should trigger BeginImplFrames,
1626 // but not a BeginMainFrame or draw.
1627 scheduler_
->SetNeedsCommit();
1628 scheduler_
->SetNeedsRedraw();
1629 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
1630 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1631 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1632 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1635 // Let time pass sufficiently beyond the regular deadline but not beyond the
1637 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1638 base::TimeDelta::FromMicroseconds(1));
1639 task_runner().RunUntilTime(now_src()->Now());
1640 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1642 // Take us out of a swap throttled state.
1643 scheduler_
->DidSwapBuffersComplete();
1644 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_
);
1645 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1648 // Verify that the deadline was rescheduled.
1649 // We can't use RunUntilTime(now) here because the next frame is also
1650 // scheduled if throttle_frame_production = false.
1651 base::TimeTicks before_deadline
= now_src()->Now();
1652 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1653 base::TimeTicks after_deadline
= now_src()->Now();
1654 EXPECT_EQ(after_deadline
, before_deadline
);
1655 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1659 TEST_F(SchedulerTest
, SyntheticBeginFrames_SwapThrottled
) {
1660 bool use_external_begin_frame_source
= false;
1661 bool throttle_frame_production
= true;
1662 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1663 throttle_frame_production
);
1666 TEST_F(SchedulerTest
, VSyncThrottlingDisabled_SwapThrottled
) {
1667 bool use_external_begin_frame_source
= true;
1668 bool throttle_frame_production
= false;
1669 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1670 throttle_frame_production
);
1673 TEST_F(SchedulerTest
,
1674 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled
) {
1675 bool use_external_begin_frame_source
= false;
1676 bool throttle_frame_production
= false;
1677 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1678 throttle_frame_production
);
1681 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized
) {
1682 scheduler_settings_
.use_external_begin_frame_source
= true;
1683 SetUpScheduler(false);
1685 scheduler_
->SetCanStart();
1686 scheduler_
->SetVisible(true);
1687 scheduler_
->SetCanDraw(true);
1689 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
1691 scheduler_
->DidCreateAndInitializeOutputSurface();
1692 EXPECT_NO_ACTION(client_
);
1694 scheduler_
->DidLoseOutputSurface();
1695 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
1698 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterBeginFrameStarted
) {
1699 scheduler_settings_
.use_external_begin_frame_source
= true;
1700 SetUpScheduler(true);
1702 // SetNeedsCommit should begin the frame.
1703 scheduler_
->SetNeedsCommit();
1704 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1707 EXPECT_SCOPED(AdvanceFrame());
1708 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1709 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1710 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1713 scheduler_
->DidLoseOutputSurface();
1714 // Do nothing when impl frame is in deadine pending state.
1715 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client_
);
1718 scheduler_
->NotifyBeginMainFrameStarted();
1719 scheduler_
->NotifyReadyToCommit();
1720 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 1);
1723 task_runner().RunPendingTasks(); // Run posted deadline.
1724 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
1727 void SchedulerTest::DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
1728 bool impl_side_painting
) {
1729 scheduler_settings_
.impl_side_painting
= impl_side_painting
;
1730 scheduler_settings_
.use_external_begin_frame_source
= true;
1731 SetUpScheduler(true);
1733 // SetNeedsCommit should begin the frame.
1734 scheduler_
->SetNeedsCommit();
1735 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1738 EXPECT_SCOPED(AdvanceFrame());
1739 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1740 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1741 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1744 scheduler_
->DidLoseOutputSurface();
1745 // Do nothing when impl frame is in deadine pending state.
1746 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client_
);
1749 // Run posted deadline.
1750 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1751 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true));
1752 // OnBeginImplFrameDeadline didn't schedule any actions because main frame is
1753 // not yet completed.
1754 EXPECT_NO_ACTION(client_
);
1755 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1757 // BeginImplFrame is not started.
1758 task_runner().RunUntilTime(now_src()->Now() +
1759 base::TimeDelta::FromMilliseconds(10));
1760 EXPECT_NO_ACTION(client_
);
1761 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1764 scheduler_
->NotifyBeginMainFrameStarted();
1765 scheduler_
->NotifyReadyToCommit();
1766 if (impl_side_painting
) {
1767 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 3);
1768 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 1, 3);
1769 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 2, 3);
1771 EXPECT_ACTION("ScheduledActionCommit", client_
, 0, 2);
1772 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 1, 2);
1776 TEST_F(SchedulerTest
,
1777 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency
) {
1778 bool impl_side_painting
= false;
1779 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
1782 TEST_F(SchedulerTest
,
1783 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint
) {
1784 bool impl_side_painting
= true;
1785 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
1788 void SchedulerTest::DidLoseOutputSurfaceAfterReadyToCommit(
1789 bool impl_side_painting
) {
1790 scheduler_settings_
.impl_side_painting
= impl_side_painting
;
1791 scheduler_settings_
.use_external_begin_frame_source
= true;
1792 SetUpScheduler(true);
1794 // SetNeedsCommit should begin the frame.
1795 scheduler_
->SetNeedsCommit();
1796 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1799 EXPECT_SCOPED(AdvanceFrame());
1800 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1801 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1802 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1805 scheduler_
->NotifyBeginMainFrameStarted();
1806 scheduler_
->NotifyReadyToCommit();
1807 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1810 scheduler_
->DidLoseOutputSurface();
1811 if (impl_side_painting
) {
1812 // Sync tree should be forced to activate.
1813 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 0, 2);
1814 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 2);
1816 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client_
);
1820 task_runner().RunPendingTasks(); // Run posted deadline.
1821 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
1824 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommit
) {
1825 DidLoseOutputSurfaceAfterReadyToCommit(false);
1828 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting
) {
1829 DidLoseOutputSurfaceAfterReadyToCommit(true);
1832 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles
) {
1833 scheduler_settings_
.use_external_begin_frame_source
= true;
1834 SetUpScheduler(true);
1836 scheduler_
->SetNeedsPrepareTiles();
1837 scheduler_
->SetNeedsRedraw();
1838 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1841 EXPECT_SCOPED(AdvanceFrame());
1842 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1843 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1844 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1847 scheduler_
->DidLoseOutputSurface();
1848 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client_
);
1851 task_runner().RunPendingTasks(); // Run posted deadline.
1852 EXPECT_ACTION("ScheduledActionPrepareTiles", client_
, 0, 2);
1853 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 1, 2);
1856 TEST_F(SchedulerTest
, DidLoseOutputSurfaceAfterBeginRetroFramePosted
) {
1857 scheduler_settings_
.use_external_begin_frame_source
= true;
1858 SetUpScheduler(true);
1860 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1861 scheduler_
->SetNeedsCommit();
1862 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1864 // Create a BeginFrame with a long deadline to avoid race conditions.
1865 // This is the first BeginFrame, which will be handled immediately.
1867 BeginFrameArgs args
=
1868 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1869 args
.deadline
+= base::TimeDelta::FromHours(1);
1870 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1871 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1872 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1873 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1874 EXPECT_TRUE(client_
->needs_begin_frames());
1876 // Queue BeginFrames while we are still handling the previous BeginFrame.
1877 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1878 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1879 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1880 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1882 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1884 task_runner().RunPendingTasks(); // Run posted deadline.
1885 EXPECT_NO_ACTION(client_
);
1886 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1887 EXPECT_TRUE(client_
->needs_begin_frames());
1889 // NotifyReadyToCommit should trigger the commit.
1891 scheduler_
->NotifyBeginMainFrameStarted();
1892 scheduler_
->NotifyReadyToCommit();
1893 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1894 EXPECT_TRUE(client_
->needs_begin_frames());
1897 EXPECT_FALSE(scheduler_
->IsBeginRetroFrameArgsEmpty());
1898 scheduler_
->DidLoseOutputSurface();
1899 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
, 0, 2);
1900 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 1, 2);
1901 EXPECT_TRUE(scheduler_
->IsBeginRetroFrameArgsEmpty());
1903 // Posted BeginRetroFrame is aborted.
1905 task_runner().RunPendingTasks();
1906 EXPECT_NO_ACTION(client_
);
1909 TEST_F(SchedulerTest
, DidLoseOutputSurfaceDuringBeginRetroFrameRunning
) {
1910 scheduler_settings_
.use_external_begin_frame_source
= true;
1911 SetUpScheduler(true);
1913 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1914 scheduler_
->SetNeedsCommit();
1915 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
1917 // Create a BeginFrame with a long deadline to avoid race conditions.
1918 // This is the first BeginFrame, which will be handled immediately.
1920 BeginFrameArgs args
=
1921 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src());
1922 args
.deadline
+= base::TimeDelta::FromHours(1);
1923 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1924 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1925 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1926 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1927 EXPECT_TRUE(client_
->needs_begin_frames());
1929 // Queue BeginFrames while we are still handling the previous BeginFrame.
1930 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1931 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1932 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1933 fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1935 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1937 task_runner().RunPendingTasks(); // Run posted deadline.
1938 EXPECT_NO_ACTION(client_
);
1939 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1940 EXPECT_TRUE(client_
->needs_begin_frames());
1942 // NotifyReadyToCommit should trigger the commit.
1944 scheduler_
->NotifyBeginMainFrameStarted();
1945 scheduler_
->NotifyReadyToCommit();
1946 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1947 EXPECT_TRUE(client_
->needs_begin_frames());
1949 // BeginImplFrame should prepare the draw.
1951 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1952 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1953 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
1954 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1955 EXPECT_TRUE(client_
->needs_begin_frames());
1958 EXPECT_FALSE(scheduler_
->IsBeginRetroFrameArgsEmpty());
1959 scheduler_
->DidLoseOutputSurface();
1960 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client_
);
1961 EXPECT_TRUE(scheduler_
->IsBeginRetroFrameArgsEmpty());
1963 // BeginImplFrame deadline should abort drawing.
1965 task_runner().RunPendingTasks(); // Run posted deadline.
1966 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
1967 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
1968 EXPECT_FALSE(client_
->needs_begin_frames());
1970 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
1972 task_runner().RunPendingTasks();
1973 EXPECT_NO_ACTION(client_
);
1976 TEST_F(SchedulerTest
,
1977 StopBeginFrameAfterDidLoseOutputSurfaceWithSyntheticBeginFrameSource
) {
1978 SetUpScheduler(true);
1980 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1981 EXPECT_FALSE(scheduler_
->frame_source().NeedsBeginFrames());
1982 scheduler_
->SetNeedsCommit();
1983 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
1986 task_runner().RunPendingTasks(); // Run posted Tick.
1987 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
1988 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
1989 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
1990 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
1992 // NotifyReadyToCommit should trigger the commit.
1994 scheduler_
->NotifyBeginMainFrameStarted();
1995 scheduler_
->NotifyReadyToCommit();
1996 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
1997 EXPECT_TRUE(scheduler_
->frame_source().NeedsBeginFrames());
2000 scheduler_
->DidLoseOutputSurface();
2001 EXPECT_NO_ACTION(client_
);
2002 EXPECT_FALSE(scheduler_
->frame_source().NeedsBeginFrames());
2005 task_runner().RunPendingTasks(); // Run posted deadline.
2006 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_
);
2007 EXPECT_FALSE(scheduler_
->frame_source().NeedsBeginFrames());
2010 TEST_F(SchedulerTest
, ScheduledActionActivateAfterBecomingInvisible
) {
2011 scheduler_settings_
.impl_side_painting
= true;
2012 scheduler_settings_
.use_external_begin_frame_source
= true;
2013 SetUpScheduler(true);
2015 // SetNeedsCommit should begin the frame.
2016 scheduler_
->SetNeedsCommit();
2017 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2020 EXPECT_SCOPED(AdvanceFrame());
2021 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2022 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_
, 1, 2);
2023 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2026 scheduler_
->NotifyBeginMainFrameStarted();
2027 scheduler_
->NotifyReadyToCommit();
2028 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_
);
2031 scheduler_
->SetVisible(false);
2032 // Sync tree should be forced to activate.
2033 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_
, 0, 2);
2034 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_
, 1, 2);
2037 TEST_F(SchedulerTest
, SchedulerPowerMonitoring
) {
2038 scheduler_settings_
.disable_hi_res_timer_tasks_on_battery
= true;
2039 SetUpScheduler(true);
2041 base::TimeTicks before_deadline
, after_deadline
;
2043 scheduler_
->SetNeedsCommit();
2044 scheduler_
->SetNeedsRedraw();
2047 // On non-battery power
2048 EXPECT_FALSE(PowerMonitor()->IsOnBatteryPower());
2050 EXPECT_SCOPED(AdvanceFrame());
2053 before_deadline
= now_src()->Now();
2055 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true)));
2056 after_deadline
= now_src()->Now();
2058 // We post a non-zero deadline task when not on battery
2059 EXPECT_LT(before_deadline
, after_deadline
);
2061 // Switch to battery power
2062 PowerMonitorSource()->GeneratePowerStateEvent(true);
2063 EXPECT_TRUE(PowerMonitor()->IsOnBatteryPower());
2065 EXPECT_SCOPED(AdvanceFrame());
2066 scheduler_
->SetNeedsCommit();
2067 scheduler_
->SetNeedsRedraw();
2070 before_deadline
= now_src()->Now();
2072 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true)));
2073 after_deadline
= now_src()->Now();
2075 // We post a zero deadline task when on battery
2076 EXPECT_EQ(before_deadline
, after_deadline
);
2078 // Switch to non-battery power
2079 PowerMonitorSource()->GeneratePowerStateEvent(false);
2080 EXPECT_FALSE(PowerMonitor()->IsOnBatteryPower());
2082 EXPECT_SCOPED(AdvanceFrame());
2083 scheduler_
->SetNeedsCommit();
2084 scheduler_
->SetNeedsRedraw();
2088 before_deadline
= now_src()->Now();
2090 task_runner().RunTasksWhile(client_
->ImplFrameDeadlinePending(true)));
2091 after_deadline
= now_src()->Now();
2094 TEST_F(SchedulerTest
,
2095 SimulateWindowsLowResolutionTimerOnBattery_PrioritizeImplLatencyOff
) {
2096 scheduler_settings_
.use_external_begin_frame_source
= true;
2097 SetUpScheduler(true);
2099 // Set needs commit so that the scheduler tries to wait for the main thread
2100 scheduler_
->SetNeedsCommit();
2101 // Set needs redraw so that the scheduler doesn't wait too long
2102 scheduler_
->SetNeedsRedraw();
2105 // Switch to battery power
2106 PowerMonitorSource()->GeneratePowerStateEvent(true);
2107 EXPECT_TRUE(PowerMonitor()->IsOnBatteryPower());
2109 EXPECT_SCOPED(AdvanceFrame());
2110 scheduler_
->SetNeedsCommit();
2111 scheduler_
->SetNeedsRedraw();
2114 // Disable auto-advancing of now_src
2115 task_runner().SetAutoAdvanceNowToPendingTasks(false);
2117 // Deadline task is pending
2118 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2119 task_runner().RunPendingTasks();
2120 // Deadline task is still pending
2121 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2123 // Advance now by 15 ms - same as windows low res timer
2124 now_src()->AdvanceNowMicroseconds(15000);
2125 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2126 task_runner().RunPendingTasks();
2127 // Deadline task finally completes
2128 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2131 TEST_F(SchedulerTest
,
2132 SimulateWindowsLowResolutionTimerOnBattery_PrioritizeImplLatencyOn
) {
2133 scheduler_settings_
.disable_hi_res_timer_tasks_on_battery
= true;
2134 scheduler_settings_
.use_external_begin_frame_source
= true;
2135 SetUpScheduler(true);
2137 // Set needs commit so that the scheduler tries to wait for the main thread
2138 scheduler_
->SetNeedsCommit();
2139 // Set needs redraw so that the scheduler doesn't wait too long
2140 scheduler_
->SetNeedsRedraw();
2143 // Switch to battery power
2144 PowerMonitorSource()->GeneratePowerStateEvent(true);
2145 EXPECT_TRUE(PowerMonitor()->IsOnBatteryPower());
2147 EXPECT_SCOPED(AdvanceFrame());
2148 scheduler_
->SetNeedsCommit();
2149 scheduler_
->SetNeedsRedraw();
2152 // Disable auto-advancing of now_src
2153 task_runner().SetAutoAdvanceNowToPendingTasks(false);
2155 // Deadline task is pending
2156 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2157 task_runner().RunPendingTasks();
2158 // Deadline task runs immediately
2159 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2162 // Tests to ensure frame sources can be successfully changed while drawing.
2163 TEST_F(SchedulerTest
, SwitchFrameSourceToUnthrottled
) {
2164 scheduler_settings_
.use_external_begin_frame_source
= true;
2165 SetUpScheduler(true);
2167 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2168 scheduler_
->SetNeedsRedraw();
2169 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2172 EXPECT_SCOPED(AdvanceFrame());
2173 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2174 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2175 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2176 EXPECT_TRUE(client_
->needs_begin_frames());
2178 task_runner().RunPendingTasks(); // Run posted deadline.
2179 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2180 scheduler_
->SetNeedsRedraw();
2182 // Switch to an unthrottled frame source.
2183 scheduler_
->SetThrottleFrameProduction(false);
2186 // Unthrottled frame source will immediately begin a new frame.
2187 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2188 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2189 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2190 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2193 // If we don't swap on the deadline, we wait for the next BeginFrame.
2194 task_runner().RunPendingTasks(); // Run posted deadline.
2195 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2196 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2200 // Tests to ensure frame sources can be successfully changed while a frame
2201 // deadline is pending.
2202 TEST_F(SchedulerTest
, SwitchFrameSourceToUnthrottledBeforeDeadline
) {
2203 scheduler_settings_
.use_external_begin_frame_source
= true;
2204 SetUpScheduler(true);
2206 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2207 scheduler_
->SetNeedsRedraw();
2208 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_
);
2211 EXPECT_SCOPED(AdvanceFrame());
2212 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2213 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2215 // Switch to an unthrottled frame source before the frame deadline is hit.
2216 scheduler_
->SetThrottleFrameProduction(false);
2219 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2220 EXPECT_TRUE(client_
->needs_begin_frames());
2223 task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame.
2224 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 2);
2225 // Unthrottled frame source will immediately begin a new frame.
2226 EXPECT_ACTION("WillBeginImplFrame", client_
, 1, 2);
2227 scheduler_
->SetNeedsRedraw();
2230 task_runner().RunPendingTasks(); // Run posted deadline.
2231 EXPECT_ACTION("ScheduledActionAnimate", client_
, 0, 2);
2232 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 1, 2);
2233 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2237 // Tests to ensure that the active frame source can successfully be changed from
2238 // unthrottled to throttled.
2239 TEST_F(SchedulerTest
, SwitchFrameSourceToThrottled
) {
2240 scheduler_settings_
.throttle_frame_production
= false;
2241 scheduler_settings_
.use_external_begin_frame_source
= true;
2242 SetUpScheduler(true);
2244 scheduler_
->SetNeedsRedraw();
2245 EXPECT_NO_ACTION(client_
);
2248 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2249 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2250 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2251 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2254 task_runner().RunPendingTasks(); // Run posted deadline.
2255 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);
2256 EXPECT_FALSE(scheduler_
->BeginImplFrameDeadlinePending());
2259 // Switch to a throttled frame source.
2260 scheduler_
->SetThrottleFrameProduction(true);
2263 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2264 scheduler_
->SetNeedsRedraw();
2265 task_runner().RunPendingTasks();
2266 EXPECT_NO_ACTION(client_
);
2269 EXPECT_SCOPED(AdvanceFrame());
2270 EXPECT_ACTION("WillBeginImplFrame", client_
, 0, 2);
2271 EXPECT_ACTION("ScheduledActionAnimate", client_
, 1, 2);
2272 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
2273 EXPECT_TRUE(client_
->needs_begin_frames());
2275 task_runner().RunPendingTasks(); // Run posted deadline.
2276 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_
, 0, 1);