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/debug/trace_event.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/power_monitor/power_monitor.h"
15 #include "base/power_monitor/power_monitor_source.h"
16 #include "base/run_loop.h"
17 #include "base/time/time.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; \
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)
44 class FakeSchedulerClient
;
46 void InitializeOutputSurfaceAndFirstCommit(Scheduler
* scheduler
,
47 FakeSchedulerClient
* client
);
49 class FakeSchedulerClient
: public SchedulerClient
{
51 class FakeExternalBeginFrameSource
: public BeginFrameSourceMixIn
{
53 explicit FakeExternalBeginFrameSource(FakeSchedulerClient
* client
)
55 virtual ~FakeExternalBeginFrameSource() {}
57 void OnNeedsBeginFramesChange(bool needs_begin_frames
) override
{
58 if (needs_begin_frames
) {
59 client_
->actions_
.push_back("SetNeedsBeginFrames(true)");
61 client_
->actions_
.push_back("SetNeedsBeginFrames(false)");
63 client_
->states_
.push_back(client_
->scheduler_
->AsValue());
66 void TestOnBeginFrame(const BeginFrameArgs
& args
) {
67 return CallOnBeginFrame(args
);
71 FakeSchedulerClient
* client_
;
74 class FakePowerMonitorSource
: public base::PowerMonitorSource
{
76 FakePowerMonitorSource() {}
77 ~FakePowerMonitorSource() override
{}
78 void GeneratePowerStateEvent(bool on_battery_power
) {
79 on_battery_power_impl_
= on_battery_power
;
80 ProcessPowerEvent(POWER_STATE_EVENT
);
81 base::MessageLoop::current()->RunUntilIdle();
83 bool IsOnBatteryPowerImpl() override
{ return on_battery_power_impl_
; }
86 bool on_battery_power_impl_
;
90 : automatic_swap_ack_(true),
91 begin_frame_is_sent_to_children_(false),
92 now_src_(TestNowSource::Create()),
93 task_runner_(new OrderedSimpleTaskRunner(now_src_
, true)),
94 fake_external_begin_frame_source_(nullptr),
95 fake_power_monitor_source_(new FakePowerMonitorSource
),
96 power_monitor_(make_scoped_ptr
<base::PowerMonitorSource
>(
97 fake_power_monitor_source_
)),
99 // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval()
100 now_src_
->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
101 // Fail if we need to run 100 tasks in a row.
102 task_runner_
->SetRunTaskLimit(100);
109 draw_will_happen_
= true;
110 swap_will_happen_if_draw_happens_
= true;
112 log_anticipated_draw_time_change_
= false;
113 begin_frame_is_sent_to_children_
= false;
116 TestScheduler
* CreateScheduler(const SchedulerSettings
& settings
) {
117 scoped_ptr
<FakeExternalBeginFrameSource
> fake_external_begin_frame_source
;
118 if (settings
.use_external_begin_frame_source
&&
119 settings
.throttle_frame_production
) {
120 fake_external_begin_frame_source
.reset(
121 new FakeExternalBeginFrameSource(this));
122 fake_external_begin_frame_source_
=
123 fake_external_begin_frame_source
.get();
125 scheduler_
= TestScheduler::Create(now_src_
,
131 fake_external_begin_frame_source
.Pass());
133 return scheduler_
.get();
136 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
137 // for tests that do.
138 void set_log_anticipated_draw_time_change(bool log
) {
139 log_anticipated_draw_time_change_
= log
;
141 bool needs_begin_frames() {
142 DCHECK(ExternalBeginFrame());
143 return fake_external_begin_frame_source_
->NeedsBeginFrames();
145 int num_draws() const { return num_draws_
; }
146 int num_actions_() const { return static_cast<int>(actions_
.size()); }
147 const char* Action(int i
) const { return actions_
[i
]; }
148 std::string
StateForAction(int i
) const { return states_
[i
]->ToString(); }
149 base::TimeTicks
posted_begin_impl_frame_deadline() const {
150 return posted_begin_impl_frame_deadline_
;
153 bool ExternalBeginFrame() {
154 return scheduler_
->settings().use_external_begin_frame_source
&&
155 scheduler_
->settings().throttle_frame_production
;
158 FakeExternalBeginFrameSource
* fake_external_begin_frame_source() const {
159 return fake_external_begin_frame_source_
;
162 base::PowerMonitor
* PowerMonitor() { return &power_monitor_
; }
164 FakePowerMonitorSource
* PowerMonitorSource() {
165 return fake_power_monitor_source_
;
168 void AdvanceFrame() {
169 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
170 "FakeSchedulerClient::AdvanceFrame");
171 bool previous_deadline_pending
=
172 scheduler_
->BeginImplFrameDeadlinePending();
173 if (ExternalBeginFrame()) {
174 SendNextBeginFrame();
175 // This could be the previous deadline or a new one.
176 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
178 // Consume previous deadline first. It is important that we check for the
179 // existence of a previous deadline so that we do not consume the new one.
180 if (previous_deadline_pending
) {
181 EXPECT_TRUE(task_runner().RunTasksWhile(ImplFrameDeadlinePending(true)));
183 // Then run tasks until new deadline is scheduled.
184 EXPECT_TRUE(task_runner().RunTasksWhile(ImplFrameDeadlinePending(false)));
185 EXPECT_TRUE(scheduler_
->BeginImplFrameDeadlinePending());
188 void SendNextBeginFrame() {
189 DCHECK(ExternalBeginFrame());
190 // Creep the time forward so that any BeginFrameArgs is not equal to the
191 // last one otherwise we violate the BeginFrameSource contract.
192 now_src_
->AdvanceNow(BeginFrameArgs::DefaultInterval());
193 fake_external_begin_frame_source_
->TestOnBeginFrame(
194 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now_src_
));
197 OrderedSimpleTaskRunner
& task_runner() { return *task_runner_
; }
198 TestNowSource
* now_src() { return now_src_
.get(); }
200 int ActionIndex(const char* action
) const {
201 for (size_t i
= 0; i
< actions_
.size(); i
++)
202 if (!strcmp(actions_
[i
], action
))
207 bool HasAction(const char* action
) const {
208 return ActionIndex(action
) >= 0;
211 void SetDrawWillHappen(bool draw_will_happen
) {
212 draw_will_happen_
= draw_will_happen
;
214 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens
) {
215 swap_will_happen_if_draw_happens_
= swap_will_happen_if_draw_happens
;
217 void SetAutomaticSwapAck(bool automatic_swap_ack
) {
218 automatic_swap_ack_
= automatic_swap_ack
;
220 // SchedulerClient implementation.
221 void WillBeginImplFrame(const BeginFrameArgs
& args
) override
{
222 actions_
.push_back("WillBeginImplFrame");
223 states_
.push_back(scheduler_
->AsValue());
225 void ScheduledActionSendBeginMainFrame() override
{
226 actions_
.push_back("ScheduledActionSendBeginMainFrame");
227 states_
.push_back(scheduler_
->AsValue());
229 void ScheduledActionAnimate() override
{
230 actions_
.push_back("ScheduledActionAnimate");
231 states_
.push_back(scheduler_
->AsValue());
233 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
234 actions_
.push_back("ScheduledActionDrawAndSwapIfPossible");
235 states_
.push_back(scheduler_
->AsValue());
238 draw_will_happen_
? DRAW_SUCCESS
: DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
;
239 bool swap_will_happen
=
240 draw_will_happen_
&& swap_will_happen_if_draw_happens_
;
241 if (swap_will_happen
) {
242 scheduler_
->DidSwapBuffers();
244 if (automatic_swap_ack_
)
245 scheduler_
->DidSwapBuffersComplete();
249 DrawResult
ScheduledActionDrawAndSwapForced() override
{
250 actions_
.push_back("ScheduledActionDrawAndSwapForced");
251 states_
.push_back(scheduler_
->AsValue());
254 void ScheduledActionCommit() override
{
255 actions_
.push_back("ScheduledActionCommit");
256 states_
.push_back(scheduler_
->AsValue());
258 void ScheduledActionActivateSyncTree() override
{
259 actions_
.push_back("ScheduledActionActivateSyncTree");
260 states_
.push_back(scheduler_
->AsValue());
262 void ScheduledActionBeginOutputSurfaceCreation() override
{
263 actions_
.push_back("ScheduledActionBeginOutputSurfaceCreation");
264 states_
.push_back(scheduler_
->AsValue());
266 void ScheduledActionPrepareTiles() override
{
267 actions_
.push_back("ScheduledActionPrepareTiles");
268 states_
.push_back(scheduler_
->AsValue());
270 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{
271 if (log_anticipated_draw_time_change_
)
272 actions_
.push_back("DidAnticipatedDrawTimeChange");
274 base::TimeDelta
DrawDurationEstimate() override
{ return base::TimeDelta(); }
275 base::TimeDelta
BeginMainFrameToCommitDurationEstimate() override
{
276 return base::TimeDelta();
278 base::TimeDelta
CommitToActivateDurationEstimate() override
{
279 return base::TimeDelta();
282 void DidBeginImplFrameDeadline() override
{}
284 void SendBeginFramesToChildren(const BeginFrameArgs
& args
) override
{
285 begin_frame_is_sent_to_children_
= true;
288 base::Callback
<bool(void)> ImplFrameDeadlinePending(bool state
) {
289 return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback
,
290 base::Unretained(this),
294 bool begin_frame_is_sent_to_children() const {
295 return begin_frame_is_sent_to_children_
;
299 bool ImplFrameDeadlinePendingCallback(bool state
) {
300 return scheduler_
->BeginImplFrameDeadlinePending() == state
;
303 bool draw_will_happen_
;
304 bool swap_will_happen_if_draw_happens_
;
305 bool automatic_swap_ack_
;
307 bool log_anticipated_draw_time_change_
;
308 bool begin_frame_is_sent_to_children_
;
309 base::TimeTicks posted_begin_impl_frame_deadline_
;
310 std::vector
<const char*> actions_
;
311 std::vector
<scoped_refptr
<base::debug::ConvertableToTraceFormat
>> states_
;
312 scoped_refptr
<TestNowSource
> now_src_
;
313 scoped_refptr
<OrderedSimpleTaskRunner
> task_runner_
;
314 FakeExternalBeginFrameSource
* fake_external_begin_frame_source_
;
315 FakePowerMonitorSource
* fake_power_monitor_source_
;
316 base::PowerMonitor power_monitor_
;
317 scoped_ptr
<TestScheduler
> scheduler_
;
320 void InitializeOutputSurfaceAndFirstCommit(Scheduler
* scheduler
,
321 FakeSchedulerClient
* client
) {
323 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit");
325 scheduler
->DidCreateAndInitializeOutputSurface();
326 scheduler
->SetNeedsCommit();
327 scheduler
->NotifyBeginMainFrameStarted();
328 scheduler
->NotifyReadyToCommit();
329 if (scheduler
->settings().impl_side_painting
)
330 scheduler
->NotifyReadyToActivate();
333 SCOPED_TRACE("Go through the motions to draw the commit");
334 client
->AdvanceFrame();
337 // Run the posted deadline task.
338 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
339 client
->task_runner().RunTasksWhile(client
->ImplFrameDeadlinePending(true));
340 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
344 "We need another BeginImplFrame so Scheduler calls "
345 "SetNeedsBeginFrame(false).");
346 client
->AdvanceFrame();
349 // Run the posted deadline task.
350 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
351 client
->task_runner().RunTasksWhile(client
->ImplFrameDeadlinePending(true));
352 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
355 TEST(SchedulerTest
, InitializeOutputSurfaceDoesNotBeginImplFrame
) {
356 FakeSchedulerClient client
;
357 SchedulerSettings scheduler_settings
;
358 scheduler_settings
.use_external_begin_frame_source
= true;
359 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
360 scheduler
->SetCanStart();
361 scheduler
->SetVisible(true);
362 scheduler
->SetCanDraw(true);
364 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
366 scheduler
->DidCreateAndInitializeOutputSurface();
367 EXPECT_NO_ACTION(client
);
370 TEST(SchedulerTest
, SendBeginFramesToChildren
) {
371 FakeSchedulerClient client
;
372 SchedulerSettings scheduler_settings
;
373 scheduler_settings
.use_external_begin_frame_source
= true;
374 scheduler_settings
.forward_begin_frames_to_children
= true;
375 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
376 scheduler
->SetCanStart();
377 scheduler
->SetVisible(true);
378 scheduler
->SetCanDraw(true);
380 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
381 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
384 EXPECT_FALSE(client
.begin_frame_is_sent_to_children());
385 scheduler
->SetNeedsCommit();
386 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client
);
389 scheduler
->SetChildrenNeedBeginFrames(true);
391 client
.AdvanceFrame();
392 EXPECT_TRUE(client
.begin_frame_is_sent_to_children());
393 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
394 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
395 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
396 EXPECT_TRUE(client
.needs_begin_frames());
400 TEST(SchedulerTest
, RequestCommit
) {
401 FakeSchedulerClient client
;
402 SchedulerSettings scheduler_settings
;
403 scheduler_settings
.use_external_begin_frame_source
= true;
404 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
405 scheduler
->SetCanStart();
406 scheduler
->SetVisible(true);
407 scheduler
->SetCanDraw(true);
409 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
410 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
412 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
414 scheduler
->SetNeedsCommit();
415 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client
);
418 client
.AdvanceFrame();
419 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
420 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
421 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
422 EXPECT_TRUE(client
.needs_begin_frames());
425 // If we don't swap on the deadline, we wait for the next BeginFrame.
426 client
.task_runner().RunPendingTasks(); // Run posted deadline.
427 EXPECT_NO_ACTION(client
);
428 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
429 EXPECT_TRUE(client
.needs_begin_frames());
432 // NotifyReadyToCommit should trigger the commit.
433 scheduler
->NotifyBeginMainFrameStarted();
434 scheduler
->NotifyReadyToCommit();
435 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
436 EXPECT_TRUE(client
.needs_begin_frames());
439 // BeginImplFrame should prepare the draw.
440 client
.AdvanceFrame();
441 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
442 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
443 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
444 EXPECT_TRUE(client
.needs_begin_frames());
447 // BeginImplFrame deadline should draw.
448 client
.task_runner().RunPendingTasks(); // Run posted deadline.
449 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 1);
450 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
451 EXPECT_TRUE(client
.needs_begin_frames());
454 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
455 // to avoid excessive toggles.
456 client
.AdvanceFrame();
457 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
458 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
461 client
.task_runner().RunPendingTasks(); // Run posted deadline.
462 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client
);
466 TEST(SchedulerTest
, RequestCommitAfterBeginMainFrameSent
) {
467 FakeSchedulerClient client
;
468 SchedulerSettings scheduler_settings
;
469 scheduler_settings
.use_external_begin_frame_source
= true;
470 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
471 scheduler
->SetCanStart();
472 scheduler
->SetVisible(true);
473 scheduler
->SetCanDraw(true);
475 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
476 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
479 // SetNeedsCommit should begin the frame.
480 scheduler
->SetNeedsCommit();
481 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client
);
484 client
.AdvanceFrame();
485 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
486 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
487 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
489 EXPECT_TRUE(client
.needs_begin_frames());
492 // Now SetNeedsCommit again. Calling here means we need a second commit.
493 scheduler
->SetNeedsCommit();
494 EXPECT_EQ(client
.num_actions_(), 0);
497 // Finish the first commit.
498 scheduler
->NotifyBeginMainFrameStarted();
499 scheduler
->NotifyReadyToCommit();
500 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
501 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
503 client
.task_runner().RunPendingTasks(); // Run posted deadline.
504 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
505 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
506 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
508 // Because we just swapped, the Scheduler should also request the next
509 // BeginImplFrame from the OutputSurface.
510 EXPECT_TRUE(client
.needs_begin_frames());
512 // Since another commit is needed, the next BeginImplFrame should initiate
513 // the second commit.
514 client
.AdvanceFrame();
515 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
516 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
517 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
520 // Finishing the commit before the deadline should post a new deadline task
521 // to trigger the deadline early.
522 scheduler
->NotifyBeginMainFrameStarted();
523 scheduler
->NotifyReadyToCommit();
524 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
525 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
527 client
.task_runner().RunPendingTasks(); // Run posted deadline.
528 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
529 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
530 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
531 EXPECT_TRUE(client
.needs_begin_frames());
534 // On the next BeginImplFrame, verify we go back to a quiescent state and
535 // no longer request BeginImplFrames.
536 client
.AdvanceFrame();
537 client
.task_runner().RunPendingTasks(); // Run posted deadline.
538 EXPECT_FALSE(client
.needs_begin_frames());
542 class SchedulerClientThatsetNeedsDrawInsideDraw
: public FakeSchedulerClient
{
544 void ScheduledActionSendBeginMainFrame() override
{}
545 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
546 // Only SetNeedsRedraw the first time this is called
548 scheduler_
->SetNeedsRedraw();
549 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
552 DrawResult
ScheduledActionDrawAndSwapForced() override
{
557 void ScheduledActionCommit() override
{}
558 void ScheduledActionBeginOutputSurfaceCreation() override
{}
559 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{}
562 // Tests for two different situations:
563 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
564 // a ScheduledActionDrawAndSwap
565 // 2. the scheduler drawing twice inside a single tick
566 TEST(SchedulerTest
, RequestRedrawInsideDraw
) {
567 SchedulerClientThatsetNeedsDrawInsideDraw client
;
568 SchedulerSettings scheduler_settings
;
569 scheduler_settings
.use_external_begin_frame_source
= true;
570 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
571 scheduler
->SetCanStart();
572 scheduler
->SetVisible(true);
573 scheduler
->SetCanDraw(true);
574 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
577 scheduler
->SetNeedsRedraw();
578 EXPECT_TRUE(scheduler
->RedrawPending());
579 EXPECT_TRUE(client
.needs_begin_frames());
580 EXPECT_EQ(0, client
.num_draws());
582 client
.AdvanceFrame();
583 client
.task_runner().RunPendingTasks(); // Run posted deadline.
584 EXPECT_EQ(1, client
.num_draws());
585 EXPECT_TRUE(scheduler
->RedrawPending());
586 EXPECT_TRUE(client
.needs_begin_frames());
588 client
.AdvanceFrame();
589 client
.task_runner().RunPendingTasks(); // Run posted deadline.
590 EXPECT_EQ(2, client
.num_draws());
591 EXPECT_FALSE(scheduler
->RedrawPending());
592 EXPECT_TRUE(client
.needs_begin_frames());
594 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
596 client
.AdvanceFrame();
597 client
.task_runner().RunPendingTasks(); // Run posted deadline.
598 EXPECT_EQ(2, client
.num_draws());
599 EXPECT_FALSE(scheduler
->RedrawPending());
600 EXPECT_FALSE(client
.needs_begin_frames());
603 // Test that requesting redraw inside a failed draw doesn't lose the request.
604 TEST(SchedulerTest
, RequestRedrawInsideFailedDraw
) {
605 SchedulerClientThatsetNeedsDrawInsideDraw client
;
606 SchedulerSettings scheduler_settings
;
607 scheduler_settings
.use_external_begin_frame_source
= true;
608 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
609 scheduler
->SetCanStart();
610 scheduler
->SetVisible(true);
611 scheduler
->SetCanDraw(true);
612 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
615 client
.SetDrawWillHappen(false);
617 scheduler
->SetNeedsRedraw();
618 EXPECT_TRUE(scheduler
->RedrawPending());
619 EXPECT_TRUE(client
.needs_begin_frames());
620 EXPECT_EQ(0, client
.num_draws());
623 client
.AdvanceFrame();
624 client
.task_runner().RunPendingTasks(); // Run posted deadline.
625 EXPECT_EQ(1, client
.num_draws());
627 // We have a commit pending and the draw failed, and we didn't lose the redraw
629 EXPECT_TRUE(scheduler
->CommitPending());
630 EXPECT_TRUE(scheduler
->RedrawPending());
631 EXPECT_TRUE(client
.needs_begin_frames());
633 // Fail the draw again.
634 client
.AdvanceFrame();
635 client
.task_runner().RunPendingTasks(); // Run posted deadline.
636 EXPECT_EQ(2, client
.num_draws());
637 EXPECT_TRUE(scheduler
->CommitPending());
638 EXPECT_TRUE(scheduler
->RedrawPending());
639 EXPECT_TRUE(client
.needs_begin_frames());
641 // Draw successfully.
642 client
.SetDrawWillHappen(true);
643 client
.AdvanceFrame();
644 client
.task_runner().RunPendingTasks(); // Run posted deadline.
645 EXPECT_EQ(3, client
.num_draws());
646 EXPECT_TRUE(scheduler
->CommitPending());
647 EXPECT_FALSE(scheduler
->RedrawPending());
648 EXPECT_TRUE(client
.needs_begin_frames());
651 class SchedulerClientThatSetNeedsCommitInsideDraw
: public FakeSchedulerClient
{
653 SchedulerClientThatSetNeedsCommitInsideDraw()
654 : set_needs_commit_on_next_draw_(false) {}
656 void ScheduledActionSendBeginMainFrame() override
{}
657 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
658 // Only SetNeedsCommit the first time this is called
659 if (set_needs_commit_on_next_draw_
) {
660 scheduler_
->SetNeedsCommit();
661 set_needs_commit_on_next_draw_
= false;
663 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
666 DrawResult
ScheduledActionDrawAndSwapForced() override
{
671 void ScheduledActionCommit() override
{}
672 void ScheduledActionBeginOutputSurfaceCreation() override
{}
673 void DidAnticipatedDrawTimeChange(base::TimeTicks
) override
{}
675 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_
= true; }
678 bool set_needs_commit_on_next_draw_
;
681 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
682 // happen inside a ScheduledActionDrawAndSwap
683 TEST(SchedulerTest
, RequestCommitInsideDraw
) {
684 SchedulerClientThatSetNeedsCommitInsideDraw client
;
685 SchedulerSettings scheduler_settings
;
686 scheduler_settings
.use_external_begin_frame_source
= true;
687 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
688 scheduler
->SetCanStart();
689 scheduler
->SetVisible(true);
690 scheduler
->SetCanDraw(true);
691 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
694 EXPECT_FALSE(client
.needs_begin_frames());
695 scheduler
->SetNeedsRedraw();
696 EXPECT_TRUE(scheduler
->RedrawPending());
697 EXPECT_EQ(0, client
.num_draws());
698 EXPECT_TRUE(client
.needs_begin_frames());
700 client
.SetNeedsCommitOnNextDraw();
701 client
.AdvanceFrame();
702 client
.SetNeedsCommitOnNextDraw();
703 client
.task_runner().RunPendingTasks(); // Run posted deadline.
704 EXPECT_EQ(1, client
.num_draws());
705 EXPECT_TRUE(scheduler
->CommitPending());
706 EXPECT_TRUE(client
.needs_begin_frames());
707 scheduler
->NotifyBeginMainFrameStarted();
708 scheduler
->NotifyReadyToCommit();
710 client
.AdvanceFrame();
711 client
.task_runner().RunPendingTasks(); // Run posted deadline.
712 EXPECT_EQ(2, client
.num_draws());
714 EXPECT_FALSE(scheduler
->RedrawPending());
715 EXPECT_FALSE(scheduler
->CommitPending());
716 EXPECT_TRUE(client
.needs_begin_frames());
718 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
720 client
.AdvanceFrame();
721 client
.task_runner().RunPendingTasks(); // Run posted deadline.
722 EXPECT_EQ(2, client
.num_draws());
723 EXPECT_FALSE(scheduler
->RedrawPending());
724 EXPECT_FALSE(scheduler
->CommitPending());
725 EXPECT_FALSE(client
.needs_begin_frames());
728 // Tests that when a draw fails then the pending commit should not be dropped.
729 TEST(SchedulerTest
, RequestCommitInsideFailedDraw
) {
730 SchedulerClientThatsetNeedsDrawInsideDraw client
;
731 SchedulerSettings scheduler_settings
;
732 scheduler_settings
.use_external_begin_frame_source
= true;
733 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
734 scheduler
->SetCanStart();
735 scheduler
->SetVisible(true);
736 scheduler
->SetCanDraw(true);
737 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
740 client
.SetDrawWillHappen(false);
742 scheduler
->SetNeedsRedraw();
743 EXPECT_TRUE(scheduler
->RedrawPending());
744 EXPECT_TRUE(client
.needs_begin_frames());
745 EXPECT_EQ(0, client
.num_draws());
748 client
.AdvanceFrame();
749 client
.task_runner().RunPendingTasks(); // Run posted deadline.
750 EXPECT_EQ(1, client
.num_draws());
752 // We have a commit pending and the draw failed, and we didn't lose the commit
754 EXPECT_TRUE(scheduler
->CommitPending());
755 EXPECT_TRUE(scheduler
->RedrawPending());
756 EXPECT_TRUE(client
.needs_begin_frames());
758 // Fail the draw again.
759 client
.AdvanceFrame();
761 client
.task_runner().RunPendingTasks(); // Run posted deadline.
762 EXPECT_EQ(2, client
.num_draws());
763 EXPECT_TRUE(scheduler
->CommitPending());
764 EXPECT_TRUE(scheduler
->RedrawPending());
765 EXPECT_TRUE(client
.needs_begin_frames());
767 // Draw successfully.
768 client
.SetDrawWillHappen(true);
769 client
.AdvanceFrame();
770 client
.task_runner().RunPendingTasks(); // Run posted deadline.
771 EXPECT_EQ(3, client
.num_draws());
772 EXPECT_TRUE(scheduler
->CommitPending());
773 EXPECT_FALSE(scheduler
->RedrawPending());
774 EXPECT_TRUE(client
.needs_begin_frames());
777 TEST(SchedulerTest
, NoSwapWhenDrawFails
) {
778 SchedulerClientThatSetNeedsCommitInsideDraw client
;
779 SchedulerSettings scheduler_settings
;
780 scheduler_settings
.use_external_begin_frame_source
= true;
781 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
782 scheduler
->SetCanStart();
783 scheduler
->SetVisible(true);
784 scheduler
->SetCanDraw(true);
785 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
788 scheduler
->SetNeedsRedraw();
789 EXPECT_TRUE(scheduler
->RedrawPending());
790 EXPECT_TRUE(client
.needs_begin_frames());
791 EXPECT_EQ(0, client
.num_draws());
793 // Draw successfully, this starts a new frame.
794 client
.SetNeedsCommitOnNextDraw();
795 client
.AdvanceFrame();
796 client
.task_runner().RunPendingTasks(); // Run posted deadline.
797 EXPECT_EQ(1, client
.num_draws());
799 scheduler
->SetNeedsRedraw();
800 EXPECT_TRUE(scheduler
->RedrawPending());
801 EXPECT_TRUE(client
.needs_begin_frames());
803 // Fail to draw, this should not start a frame.
804 client
.SetDrawWillHappen(false);
805 client
.SetNeedsCommitOnNextDraw();
806 client
.AdvanceFrame();
807 client
.task_runner().RunPendingTasks(); // Run posted deadline.
808 EXPECT_EQ(2, client
.num_draws());
811 class SchedulerClientNeedsPrepareTilesInDraw
: public FakeSchedulerClient
{
813 DrawResult
ScheduledActionDrawAndSwapIfPossible() override
{
814 scheduler_
->SetNeedsPrepareTiles();
815 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
819 // Test prepare tiles is independant of draws.
820 TEST(SchedulerTest
, PrepareTiles
) {
821 SchedulerClientNeedsPrepareTilesInDraw client
;
822 SchedulerSettings scheduler_settings
;
823 scheduler_settings
.use_external_begin_frame_source
= true;
824 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
825 scheduler
->SetCanStart();
826 scheduler
->SetVisible(true);
827 scheduler
->SetCanDraw(true);
828 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
830 // Request both draw and prepare tiles. PrepareTiles shouldn't
831 // be trigged until BeginImplFrame.
833 scheduler
->SetNeedsPrepareTiles();
834 scheduler
->SetNeedsRedraw();
835 EXPECT_TRUE(scheduler
->RedrawPending());
836 EXPECT_TRUE(scheduler
->PrepareTilesPending());
837 EXPECT_TRUE(client
.needs_begin_frames());
838 EXPECT_EQ(0, client
.num_draws());
839 EXPECT_FALSE(client
.HasAction("ScheduledActionPrepareTiles"));
840 EXPECT_FALSE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
842 // We have no immediate actions to perform, so the BeginImplFrame should post
843 // the deadline task.
845 client
.AdvanceFrame();
846 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
847 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
848 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
850 // On the deadline, he actions should have occured in the right order.
852 client
.task_runner().RunPendingTasks(); // Run posted deadline.
853 EXPECT_EQ(1, client
.num_draws());
854 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
855 EXPECT_TRUE(client
.HasAction("ScheduledActionPrepareTiles"));
856 EXPECT_LT(client
.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
857 client
.ActionIndex("ScheduledActionPrepareTiles"));
858 EXPECT_FALSE(scheduler
->RedrawPending());
859 EXPECT_FALSE(scheduler
->PrepareTilesPending());
860 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
862 // Request a draw. We don't need a PrepareTiles yet.
864 scheduler
->SetNeedsRedraw();
865 EXPECT_TRUE(scheduler
->RedrawPending());
866 EXPECT_FALSE(scheduler
->PrepareTilesPending());
867 EXPECT_TRUE(client
.needs_begin_frames());
868 EXPECT_EQ(0, client
.num_draws());
870 // We have no immediate actions to perform, so the BeginImplFrame should post
871 // the deadline task.
873 client
.AdvanceFrame();
874 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
875 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
876 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
878 // Draw. The draw will trigger SetNeedsPrepareTiles, and
879 // then the PrepareTiles action will be triggered after the Draw.
880 // Afterwards, neither a draw nor PrepareTiles are pending.
882 client
.task_runner().RunPendingTasks(); // Run posted deadline.
883 EXPECT_EQ(1, client
.num_draws());
884 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
885 EXPECT_TRUE(client
.HasAction("ScheduledActionPrepareTiles"));
886 EXPECT_LT(client
.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
887 client
.ActionIndex("ScheduledActionPrepareTiles"));
888 EXPECT_FALSE(scheduler
->RedrawPending());
889 EXPECT_FALSE(scheduler
->PrepareTilesPending());
890 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
892 // We need a BeginImplFrame where we don't swap to go idle.
894 client
.AdvanceFrame();
895 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
896 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
898 client
.task_runner().RunPendingTasks(); // Run posted deadline.
899 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client
);
900 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
901 EXPECT_EQ(0, client
.num_draws());
903 // Now trigger a PrepareTiles outside of a draw. We will then need
904 // a begin-frame for the PrepareTiles, but we don't need a draw.
906 EXPECT_FALSE(client
.needs_begin_frames());
907 scheduler
->SetNeedsPrepareTiles();
908 EXPECT_TRUE(client
.needs_begin_frames());
909 EXPECT_TRUE(scheduler
->PrepareTilesPending());
910 EXPECT_FALSE(scheduler
->RedrawPending());
912 // BeginImplFrame. There will be no draw, only PrepareTiles.
914 client
.AdvanceFrame();
915 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
916 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
918 client
.task_runner().RunPendingTasks(); // Run posted deadline.
919 EXPECT_EQ(0, client
.num_draws());
920 EXPECT_FALSE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
921 EXPECT_TRUE(client
.HasAction("ScheduledActionPrepareTiles"));
922 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
925 // Test that PrepareTiles only happens once per frame. If an external caller
926 // initiates it, then the state machine should not PrepareTiles on that frame.
927 TEST(SchedulerTest
, PrepareTilesOncePerFrame
) {
928 FakeSchedulerClient client
;
929 SchedulerSettings scheduler_settings
;
930 scheduler_settings
.use_external_begin_frame_source
= true;
931 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
932 scheduler
->SetCanStart();
933 scheduler
->SetVisible(true);
934 scheduler
->SetCanDraw(true);
935 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
937 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
939 scheduler
->SetNeedsPrepareTiles();
940 scheduler
->SetNeedsRedraw();
942 client
.AdvanceFrame();
943 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
944 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
945 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
947 EXPECT_TRUE(scheduler
->PrepareTilesPending());
948 scheduler
->DidPrepareTiles(); // An explicit PrepareTiles.
949 EXPECT_FALSE(scheduler
->PrepareTilesPending());
952 client
.task_runner().RunPendingTasks(); // Run posted deadline.
953 EXPECT_EQ(1, client
.num_draws());
954 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
955 EXPECT_FALSE(client
.HasAction("ScheduledActionPrepareTiles"));
956 EXPECT_FALSE(scheduler
->RedrawPending());
957 EXPECT_FALSE(scheduler
->PrepareTilesPending());
958 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
960 // Next frame without DidPrepareTiles should PrepareTiles with draw.
961 scheduler
->SetNeedsPrepareTiles();
962 scheduler
->SetNeedsRedraw();
964 client
.AdvanceFrame();
965 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
966 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
967 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
970 client
.task_runner().RunPendingTasks(); // Run posted deadline.
971 EXPECT_EQ(1, client
.num_draws());
972 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
973 EXPECT_TRUE(client
.HasAction("ScheduledActionPrepareTiles"));
974 EXPECT_LT(client
.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
975 client
.ActionIndex("ScheduledActionPrepareTiles"));
976 EXPECT_FALSE(scheduler
->RedrawPending());
977 EXPECT_FALSE(scheduler
->PrepareTilesPending());
978 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
979 scheduler
->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
981 // If we get another DidPrepareTiles within the same frame, we should
982 // not PrepareTiles on the next frame.
983 scheduler
->DidPrepareTiles(); // An explicit PrepareTiles.
984 scheduler
->SetNeedsPrepareTiles();
985 scheduler
->SetNeedsRedraw();
987 client
.AdvanceFrame();
988 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
989 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
990 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
992 EXPECT_TRUE(scheduler
->PrepareTilesPending());
995 client
.task_runner().RunPendingTasks(); // Run posted deadline.
996 EXPECT_EQ(1, client
.num_draws());
997 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
998 EXPECT_FALSE(client
.HasAction("ScheduledActionPrepareTiles"));
999 EXPECT_FALSE(scheduler
->RedrawPending());
1000 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1002 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1003 // frame. This verifies we don't alternate calling PrepareTiles once and
1005 EXPECT_TRUE(scheduler
->PrepareTilesPending());
1006 scheduler
->DidPrepareTiles(); // An explicit PrepareTiles.
1007 EXPECT_FALSE(scheduler
->PrepareTilesPending());
1008 scheduler
->SetNeedsPrepareTiles();
1009 scheduler
->SetNeedsRedraw();
1011 client
.AdvanceFrame();
1012 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1013 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1014 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1016 EXPECT_TRUE(scheduler
->PrepareTilesPending());
1019 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1020 EXPECT_EQ(1, client
.num_draws());
1021 EXPECT_TRUE(client
.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1022 EXPECT_FALSE(client
.HasAction("ScheduledActionPrepareTiles"));
1023 EXPECT_FALSE(scheduler
->RedrawPending());
1024 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1026 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1027 scheduler
->SetNeedsPrepareTiles();
1028 scheduler
->SetNeedsRedraw();
1030 client
.AdvanceFrame();
1031 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1032 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1033 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1036 client
.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());
1045 scheduler
->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1048 TEST(SchedulerTest
, TriggerBeginFrameDeadlineEarly
) {
1049 SchedulerClientNeedsPrepareTilesInDraw client
;
1050 SchedulerSettings scheduler_settings
;
1051 scheduler_settings
.use_external_begin_frame_source
= true;
1052 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1053 scheduler
->SetCanStart();
1054 scheduler
->SetVisible(true);
1055 scheduler
->SetCanDraw(true);
1056 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1059 scheduler
->SetNeedsRedraw();
1060 client
.AdvanceFrame();
1062 // The deadline should be zero since there is no work other than drawing
1064 EXPECT_EQ(base::TimeTicks(), client
.posted_begin_impl_frame_deadline());
1067 class SchedulerClientWithFixedEstimates
: public FakeSchedulerClient
{
1069 SchedulerClientWithFixedEstimates(
1070 base::TimeDelta draw_duration
,
1071 base::TimeDelta begin_main_frame_to_commit_duration
,
1072 base::TimeDelta commit_to_activate_duration
)
1073 : draw_duration_(draw_duration
),
1074 begin_main_frame_to_commit_duration_(
1075 begin_main_frame_to_commit_duration
),
1076 commit_to_activate_duration_(commit_to_activate_duration
) {}
1078 base::TimeDelta
DrawDurationEstimate() override
{ return draw_duration_
; }
1079 base::TimeDelta
BeginMainFrameToCommitDurationEstimate() override
{
1080 return begin_main_frame_to_commit_duration_
;
1082 base::TimeDelta
CommitToActivateDurationEstimate() override
{
1083 return commit_to_activate_duration_
;
1087 base::TimeDelta draw_duration_
;
1088 base::TimeDelta begin_main_frame_to_commit_duration_
;
1089 base::TimeDelta commit_to_activate_duration_
;
1092 void MainFrameInHighLatencyMode(int64 begin_main_frame_to_commit_estimate_in_ms
,
1093 int64 commit_to_activate_estimate_in_ms
,
1094 bool impl_latency_takes_priority
,
1095 bool should_send_begin_main_frame
) {
1096 // Set up client with specified estimates (draw duration is set to 1).
1097 SchedulerClientWithFixedEstimates
client(
1098 base::TimeDelta::FromMilliseconds(1),
1099 base::TimeDelta::FromMilliseconds(
1100 begin_main_frame_to_commit_estimate_in_ms
),
1101 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms
));
1102 SchedulerSettings scheduler_settings
;
1103 scheduler_settings
.use_external_begin_frame_source
= true;
1104 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1105 scheduler
->SetCanStart();
1106 scheduler
->SetVisible(true);
1107 scheduler
->SetCanDraw(true);
1108 scheduler
->SetImplLatencyTakesPriority(impl_latency_takes_priority
);
1109 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1111 // Impl thread hits deadline before commit finishes.
1113 scheduler
->SetNeedsCommit();
1114 EXPECT_FALSE(scheduler
->MainThreadIsInHighLatencyMode());
1115 client
.AdvanceFrame();
1116 EXPECT_FALSE(scheduler
->MainThreadIsInHighLatencyMode());
1117 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1118 EXPECT_TRUE(scheduler
->MainThreadIsInHighLatencyMode());
1119 scheduler
->NotifyBeginMainFrameStarted();
1120 scheduler
->NotifyReadyToCommit();
1121 EXPECT_TRUE(scheduler
->MainThreadIsInHighLatencyMode());
1122 EXPECT_TRUE(client
.HasAction("ScheduledActionSendBeginMainFrame"));
1125 scheduler
->SetNeedsCommit();
1126 EXPECT_TRUE(scheduler
->MainThreadIsInHighLatencyMode());
1127 client
.AdvanceFrame();
1128 EXPECT_TRUE(scheduler
->MainThreadIsInHighLatencyMode());
1129 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1130 EXPECT_EQ(scheduler
->MainThreadIsInHighLatencyMode(),
1131 should_send_begin_main_frame
);
1132 EXPECT_EQ(client
.HasAction("ScheduledActionSendBeginMainFrame"),
1133 should_send_begin_main_frame
);
1137 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline
) {
1138 // Set up client so that estimates indicate that we can commit and activate
1139 // before the deadline (~8ms by default).
1140 MainFrameInHighLatencyMode(1, 1, false, false);
1143 TEST(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong
) {
1144 // Set up client so that estimates indicate that the commit cannot finish
1145 // before the deadline (~8ms by default).
1146 MainFrameInHighLatencyMode(10, 1, false, true);
1149 TEST(SchedulerTest
, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong
) {
1150 // Set up client so that estimates indicate that the activate cannot finish
1151 // before the deadline (~8ms by default).
1152 MainFrameInHighLatencyMode(1, 10, false, true);
1155 TEST(SchedulerTest
, NotSkipMainFrameInPreferImplLatencyMode
) {
1156 // Set up client so that estimates indicate that we can commit and activate
1157 // before the deadline (~8ms by default), but also enable impl latency takes
1159 MainFrameInHighLatencyMode(1, 1, true, true);
1162 TEST(SchedulerTest
, PollForCommitCompletion
) {
1163 // Since we are simulating a long commit, set up a client with draw duration
1164 // estimates that prevent skipping main frames to get to low latency mode.
1165 SchedulerClientWithFixedEstimates
client(
1166 base::TimeDelta::FromMilliseconds(1),
1167 base::TimeDelta::FromMilliseconds(32),
1168 base::TimeDelta::FromMilliseconds(32));
1169 client
.set_log_anticipated_draw_time_change(true);
1170 SchedulerSettings scheduler_settings
;
1171 scheduler_settings
.use_external_begin_frame_source
= true;
1172 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1174 scheduler
->SetCanDraw(true);
1175 scheduler
->SetCanStart();
1176 scheduler
->SetVisible(true);
1177 scheduler
->DidCreateAndInitializeOutputSurface();
1179 scheduler
->SetNeedsCommit();
1180 EXPECT_TRUE(scheduler
->CommitPending());
1181 scheduler
->NotifyBeginMainFrameStarted();
1182 scheduler
->NotifyReadyToCommit();
1183 scheduler
->SetNeedsRedraw();
1185 BeginFrameArgs frame_args
=
1186 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, client
.now_src());
1187 frame_args
.interval
= base::TimeDelta::FromMilliseconds(1000);
1188 client
.fake_external_begin_frame_source()->TestOnBeginFrame(frame_args
);
1190 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1191 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1192 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1194 scheduler
->DidSwapBuffers();
1195 scheduler
->DidSwapBuffersComplete();
1197 // At this point, we've drawn a frame. Start another commit, but hold off on
1198 // the NotifyReadyToCommit for now.
1199 EXPECT_FALSE(scheduler
->CommitPending());
1200 scheduler
->SetNeedsCommit();
1201 client
.fake_external_begin_frame_source()->TestOnBeginFrame(frame_args
);
1202 EXPECT_TRUE(scheduler
->CommitPending());
1204 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1205 // blocking on the renderer.
1206 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1207 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1208 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1209 scheduler
->DidSwapBuffers();
1211 // Spin the event loop a few times and make sure we get more
1212 // DidAnticipateDrawTimeChange calls every time.
1213 int actions_so_far
= client
.num_actions_();
1215 // Does three iterations to make sure that the timer is properly repeating.
1216 for (int i
= 0; i
< 3; ++i
) {
1217 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1218 client
.task_runner().DelayToNextTaskTime().InMicroseconds())
1219 << scheduler
->AsValue()->ToString();
1220 client
.task_runner().RunPendingTasks();
1221 EXPECT_GT(client
.num_actions_(), actions_so_far
);
1222 EXPECT_STREQ(client
.Action(client
.num_actions_() - 1),
1223 "DidAnticipatedDrawTimeChange");
1224 actions_so_far
= client
.num_actions_();
1227 // Do the same thing after BeginMainFrame starts but still before activation.
1228 scheduler
->NotifyBeginMainFrameStarted();
1229 for (int i
= 0; i
< 3; ++i
) {
1230 EXPECT_EQ((frame_args
.interval
* 2).InMicroseconds(),
1231 client
.task_runner().DelayToNextTaskTime().InMicroseconds())
1232 << scheduler
->AsValue()->ToString();
1233 client
.task_runner().RunPendingTasks();
1234 EXPECT_GT(client
.num_actions_(), actions_so_far
);
1235 EXPECT_STREQ(client
.Action(client
.num_actions_() - 1),
1236 "DidAnticipatedDrawTimeChange");
1237 actions_so_far
= client
.num_actions_();
1241 TEST(SchedulerTest
, BeginRetroFrame
) {
1242 FakeSchedulerClient client
;
1243 SchedulerSettings scheduler_settings
;
1244 scheduler_settings
.use_external_begin_frame_source
= true;
1245 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1246 scheduler
->SetCanStart();
1247 scheduler
->SetVisible(true);
1248 scheduler
->SetCanDraw(true);
1249 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1251 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1253 scheduler
->SetNeedsCommit();
1254 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client
);
1257 // Create a BeginFrame with a long deadline to avoid race conditions.
1258 // This is the first BeginFrame, which will be handled immediately.
1259 BeginFrameArgs args
=
1260 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, client
.now_src());
1261 args
.deadline
+= base::TimeDelta::FromHours(1);
1262 client
.fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1263 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1264 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1265 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1266 EXPECT_TRUE(client
.needs_begin_frames());
1269 // Queue BeginFrames while we are still handling the previous BeginFrame.
1270 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1271 client
.fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1272 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1273 client
.fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1275 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1276 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1277 EXPECT_NO_ACTION(client
);
1278 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1279 EXPECT_TRUE(client
.needs_begin_frames());
1282 // NotifyReadyToCommit should trigger the commit.
1283 scheduler
->NotifyBeginMainFrameStarted();
1284 scheduler
->NotifyReadyToCommit();
1285 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1286 EXPECT_TRUE(client
.needs_begin_frames());
1289 // BeginImplFrame should prepare the draw.
1290 client
.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1291 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1292 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1293 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1294 EXPECT_TRUE(client
.needs_begin_frames());
1297 // BeginImplFrame deadline should draw.
1298 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1299 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 1);
1300 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1301 EXPECT_TRUE(client
.needs_begin_frames());
1304 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1305 // to avoid excessive toggles.
1306 client
.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1307 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
1308 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1311 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1312 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client
);
1316 TEST(SchedulerTest
, BeginRetroFrame_SwapThrottled
) {
1317 FakeSchedulerClient client
;
1318 SchedulerSettings scheduler_settings
;
1319 scheduler_settings
.use_external_begin_frame_source
= true;
1320 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1321 scheduler
->SetCanStart();
1322 scheduler
->SetVisible(true);
1323 scheduler
->SetCanDraw(true);
1324 scheduler
->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1325 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1327 // To test swap ack throttling, this test disables automatic swap acks.
1328 scheduler
->SetMaxSwapsPending(1);
1329 client
.SetAutomaticSwapAck(false);
1331 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1333 scheduler
->SetNeedsCommit();
1334 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client
);
1337 client
.AdvanceFrame();
1338 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1339 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1340 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1341 EXPECT_TRUE(client
.needs_begin_frames());
1344 // Queue BeginFrame while we are still handling the previous BeginFrame.
1345 client
.SendNextBeginFrame();
1346 EXPECT_NO_ACTION(client
);
1347 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1348 EXPECT_TRUE(client
.needs_begin_frames());
1351 // NotifyReadyToCommit should trigger the pending commit and draw.
1352 scheduler
->NotifyBeginMainFrameStarted();
1353 scheduler
->NotifyReadyToCommit();
1354 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1355 EXPECT_TRUE(client
.needs_begin_frames());
1358 // Swapping will put us into a swap throttled state.
1359 // Run posted deadline.
1360 client
.task_runner().RunTasksWhile(client
.ImplFrameDeadlinePending(true));
1361 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
1362 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
1363 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1364 EXPECT_TRUE(client
.needs_begin_frames());
1367 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1368 // but not a BeginMainFrame or draw.
1369 scheduler
->SetNeedsCommit();
1370 scheduler
->SetNeedsRedraw();
1371 // Run posted BeginRetroFrame.
1372 client
.task_runner().RunTasksWhile(client
.ImplFrameDeadlinePending(false));
1373 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1374 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1375 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1376 EXPECT_TRUE(client
.needs_begin_frames());
1379 // Let time pass sufficiently beyond the regular deadline but not beyond the
1381 client
.now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1382 base::TimeDelta::FromMicroseconds(1));
1383 client
.task_runner().RunUntilTime(client
.now_src()->Now());
1384 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1386 // Take us out of a swap throttled state.
1387 scheduler
->DidSwapBuffersComplete();
1388 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client
);
1389 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1390 EXPECT_TRUE(client
.needs_begin_frames());
1393 // Verify that the deadline was rescheduled.
1394 client
.task_runner().RunUntilTime(client
.now_src()->Now());
1395 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client
);
1396 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1397 EXPECT_TRUE(client
.needs_begin_frames());
1401 TEST(SchedulerTest
, RetroFrameDoesNotExpireTooEarly
) {
1402 FakeSchedulerClient client
;
1403 SchedulerSettings scheduler_settings
;
1404 scheduler_settings
.use_external_begin_frame_source
= true;
1405 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1406 scheduler
->SetCanStart();
1407 scheduler
->SetVisible(true);
1408 scheduler
->SetCanDraw(true);
1409 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1412 scheduler
->SetNeedsCommit();
1413 EXPECT_TRUE(client
.needs_begin_frames());
1414 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client
);
1417 client
.AdvanceFrame();
1418 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1419 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1420 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1423 scheduler
->NotifyBeginMainFrameStarted();
1426 client
.SendNextBeginFrame();
1427 // This BeginFrame is queued up as a retro frame.
1428 EXPECT_NO_ACTION(client
);
1429 // The previous deadline is still pending.
1430 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1433 // This commit should schedule the (previous) deadline to trigger immediately.
1434 scheduler
->NotifyReadyToCommit();
1435 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1438 // The deadline task should trigger causing a draw.
1439 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1440 client
.task_runner().RunTasksWhile(client
.ImplFrameDeadlinePending(true));
1441 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
1442 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
1446 scheduler
->SetNeedsAnimate();
1447 scheduler
->SetNeedsRedraw();
1448 EXPECT_NO_ACTION(client
);
1450 // Let's advance sufficiently past the next frame's deadline.
1451 client
.now_src()->AdvanceNow(
1452 BeginFrameArgs::DefaultInterval() -
1453 BeginFrameArgs::DefaultEstimatedParentDrawTime() +
1454 base::TimeDelta::FromMicroseconds(1));
1456 // The retro frame hasn't expired yet.
1457 client
.task_runner().RunTasksWhile(client
.ImplFrameDeadlinePending(false));
1458 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1459 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1460 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1462 // This is an immediate deadline case.
1464 client
.task_runner().RunPendingTasks();
1465 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1466 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client
);
1469 TEST(SchedulerTest
, RetroFrameDoesNotExpireTooLate
) {
1470 FakeSchedulerClient client
;
1471 SchedulerSettings scheduler_settings
;
1472 scheduler_settings
.use_external_begin_frame_source
= true;
1473 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1474 scheduler
->SetCanStart();
1475 scheduler
->SetVisible(true);
1476 scheduler
->SetCanDraw(true);
1477 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1480 scheduler
->SetNeedsCommit();
1481 EXPECT_TRUE(client
.needs_begin_frames());
1482 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client
);
1485 client
.AdvanceFrame();
1486 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1487 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1488 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1491 scheduler
->NotifyBeginMainFrameStarted();
1494 client
.SendNextBeginFrame();
1495 // This BeginFrame is queued up as a retro frame.
1496 EXPECT_NO_ACTION(client
);
1497 // The previous deadline is still pending.
1498 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1501 // This commit should schedule the (previous) deadline to trigger immediately.
1502 scheduler
->NotifyReadyToCommit();
1503 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1506 // The deadline task should trigger causing a draw.
1507 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1508 client
.task_runner().RunTasksWhile(client
.ImplFrameDeadlinePending(true));
1509 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
1510 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
1514 scheduler
->SetNeedsAnimate();
1515 scheduler
->SetNeedsRedraw();
1516 EXPECT_NO_ACTION(client
);
1518 // Let's advance sufficiently past the next frame's deadline.
1519 client
.now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() +
1520 base::TimeDelta::FromMicroseconds(1));
1522 // The retro frame should've expired.
1523 EXPECT_NO_ACTION(client
);
1526 void BeginFramesNotFromClient(bool use_external_begin_frame_source
,
1527 bool throttle_frame_production
) {
1528 FakeSchedulerClient client
;
1529 SchedulerSettings scheduler_settings
;
1530 scheduler_settings
.use_external_begin_frame_source
=
1531 use_external_begin_frame_source
;
1532 scheduler_settings
.throttle_frame_production
= throttle_frame_production
;
1533 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1534 scheduler
->SetCanStart();
1535 scheduler
->SetVisible(true);
1536 scheduler
->SetCanDraw(true);
1537 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1539 DCHECK(!client
.fake_external_begin_frame_source());
1541 // SetNeedsCommit should begin the frame on the next BeginImplFrame
1542 // without calling SetNeedsBeginFrame.
1544 scheduler
->SetNeedsCommit();
1545 EXPECT_NO_ACTION(client
);
1548 // When the client-driven BeginFrame are disabled, the scheduler posts it's
1549 // own BeginFrame tasks.
1550 client
.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1551 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1552 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1553 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1556 // If we don't swap on the deadline, we wait for the next BeginFrame.
1557 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1558 EXPECT_NO_ACTION(client
);
1559 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1562 // NotifyReadyToCommit should trigger the commit.
1563 scheduler
->NotifyBeginMainFrameStarted();
1564 scheduler
->NotifyReadyToCommit();
1565 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1568 // BeginImplFrame should prepare the draw.
1569 client
.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1570 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1571 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1572 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1575 // BeginImplFrame deadline should draw.
1576 client
.task_runner().RunTasksWhile(client
.ImplFrameDeadlinePending(true));
1577 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 0, 1);
1578 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1581 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1582 // to avoid excessive toggles.
1583 client
.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1584 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client
);
1585 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1588 // Make sure SetNeedsBeginFrame isn't called on the client
1589 // when the BeginFrame is no longer needed.
1590 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1591 EXPECT_NO_ACTION(client
);
1595 TEST(SchedulerTest
, SyntheticBeginFrames
) {
1596 bool use_external_begin_frame_source
= false;
1597 bool throttle_frame_production
= true;
1598 BeginFramesNotFromClient(use_external_begin_frame_source
,
1599 throttle_frame_production
);
1602 TEST(SchedulerTest
, VSyncThrottlingDisabled
) {
1603 bool use_external_begin_frame_source
= true;
1604 bool throttle_frame_production
= false;
1605 BeginFramesNotFromClient(use_external_begin_frame_source
,
1606 throttle_frame_production
);
1609 TEST(SchedulerTest
, SyntheticBeginFrames_And_VSyncThrottlingDisabled
) {
1610 bool use_external_begin_frame_source
= false;
1611 bool throttle_frame_production
= false;
1612 BeginFramesNotFromClient(use_external_begin_frame_source
,
1613 throttle_frame_production
);
1616 void BeginFramesNotFromClient_SwapThrottled(
1617 bool use_external_begin_frame_source
,
1618 bool throttle_frame_production
) {
1619 FakeSchedulerClient client
;
1620 SchedulerSettings scheduler_settings
;
1621 scheduler_settings
.use_external_begin_frame_source
=
1622 use_external_begin_frame_source
;
1623 scheduler_settings
.throttle_frame_production
= throttle_frame_production
;
1624 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1625 scheduler
->SetCanStart();
1626 scheduler
->SetVisible(true);
1627 scheduler
->SetCanDraw(true);
1628 scheduler
->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1629 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1631 DCHECK(!client
.fake_external_begin_frame_source());
1633 // To test swap ack throttling, this test disables automatic swap acks.
1634 scheduler
->SetMaxSwapsPending(1);
1635 client
.SetAutomaticSwapAck(false);
1637 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1639 scheduler
->SetNeedsCommit();
1640 EXPECT_NO_ACTION(client
);
1643 // Trigger the first BeginImplFrame and BeginMainFrame
1644 client
.AdvanceFrame();
1645 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1646 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1647 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1650 // NotifyReadyToCommit should trigger the pending commit and draw.
1651 scheduler
->NotifyBeginMainFrameStarted();
1652 scheduler
->NotifyReadyToCommit();
1653 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1656 // Swapping will put us into a swap throttled state.
1657 // Run posted deadline.
1658 client
.task_runner().RunTasksWhile(client
.ImplFrameDeadlinePending(true));
1659 EXPECT_ACTION("ScheduledActionAnimate", client
, 0, 2);
1660 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client
, 1, 2);
1661 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1664 // While swap throttled, BeginFrames should trigger BeginImplFrames,
1665 // but not a BeginMainFrame or draw.
1666 scheduler
->SetNeedsCommit();
1667 scheduler
->SetNeedsRedraw();
1668 client
.AdvanceFrame(); // Run posted BeginFrame.
1669 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1670 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1671 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1674 // Let time pass sufficiently beyond the regular deadline but not beyond the
1676 client
.now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1677 base::TimeDelta::FromMicroseconds(1));
1678 client
.task_runner().RunUntilTime(client
.now_src()->Now());
1679 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1681 // Take us out of a swap throttled state.
1682 scheduler
->DidSwapBuffersComplete();
1683 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client
);
1684 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1687 // Verify that the deadline was rescheduled.
1688 // We can't use RunUntilTime(now) here because the next frame is also
1689 // scheduled if throttle_frame_production = false.
1690 base::TimeTicks before_deadline
= client
.now_src()->Now();
1691 client
.task_runner().RunTasksWhile(client
.ImplFrameDeadlinePending(true));
1692 base::TimeTicks after_deadline
= client
.now_src()->Now();
1693 EXPECT_EQ(after_deadline
, before_deadline
);
1694 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1698 TEST(SchedulerTest
, SyntheticBeginFrames_SwapThrottled
) {
1699 bool use_external_begin_frame_source
= false;
1700 bool throttle_frame_production
= true;
1701 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1702 throttle_frame_production
);
1705 TEST(SchedulerTest
, VSyncThrottlingDisabled_SwapThrottled
) {
1706 bool use_external_begin_frame_source
= true;
1707 bool throttle_frame_production
= false;
1708 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1709 throttle_frame_production
);
1713 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled
) {
1714 bool use_external_begin_frame_source
= false;
1715 bool throttle_frame_production
= false;
1716 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source
,
1717 throttle_frame_production
);
1720 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized
) {
1721 FakeSchedulerClient client
;
1722 SchedulerSettings scheduler_settings
;
1723 scheduler_settings
.use_external_begin_frame_source
= true;
1724 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1725 scheduler
->SetCanStart();
1726 scheduler
->SetVisible(true);
1727 scheduler
->SetCanDraw(true);
1729 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1731 scheduler
->DidCreateAndInitializeOutputSurface();
1732 EXPECT_NO_ACTION(client
);
1734 scheduler
->DidLoseOutputSurface();
1735 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1738 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterBeginFrameStarted
) {
1739 FakeSchedulerClient client
;
1740 SchedulerSettings scheduler_settings
;
1741 scheduler_settings
.use_external_begin_frame_source
= true;
1742 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1743 scheduler
->SetCanStart();
1744 scheduler
->SetVisible(true);
1745 scheduler
->SetCanDraw(true);
1747 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1748 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1749 // SetNeedsCommit should begin the frame.
1751 scheduler
->SetNeedsCommit();
1752 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client
);
1755 client
.AdvanceFrame();
1756 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1757 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1758 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1761 scheduler
->DidLoseOutputSurface();
1762 // Do nothing when impl frame is in deadine pending state.
1763 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client
);
1766 scheduler
->NotifyBeginMainFrameStarted();
1767 scheduler
->NotifyReadyToCommit();
1768 EXPECT_ACTION("ScheduledActionCommit", client
, 0, 1);
1771 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1772 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1775 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
1776 bool impl_side_painting
) {
1777 FakeSchedulerClient client
;
1778 SchedulerSettings scheduler_settings
;
1779 scheduler_settings
.impl_side_painting
= impl_side_painting
;
1780 scheduler_settings
.use_external_begin_frame_source
= true;
1781 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1782 scheduler
->SetCanStart();
1783 scheduler
->SetVisible(true);
1784 scheduler
->SetCanDraw(true);
1786 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1787 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1789 // SetNeedsCommit should begin the frame.
1791 scheduler
->SetNeedsCommit();
1792 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client
);
1795 client
.AdvanceFrame();
1796 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1797 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1798 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1801 scheduler
->DidLoseOutputSurface();
1802 // Do nothing when impl frame is in deadine pending state.
1803 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client
);
1806 // Run posted deadline.
1807 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1808 client
.task_runner().RunTasksWhile(client
.ImplFrameDeadlinePending(true));
1809 // OnBeginImplFrameDeadline didn't schedule any actions because main frame is
1810 // not yet completed.
1811 EXPECT_NO_ACTION(client
);
1812 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1814 // BeginImplFrame is not started.
1815 client
.task_runner().RunUntilTime(client
.now_src()->Now() +
1816 base::TimeDelta::FromMilliseconds(10));
1817 EXPECT_NO_ACTION(client
);
1818 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1821 scheduler
->NotifyBeginMainFrameStarted();
1822 scheduler
->NotifyReadyToCommit();
1823 if (impl_side_painting
) {
1824 EXPECT_ACTION("ScheduledActionCommit", client
, 0, 3);
1825 EXPECT_ACTION("ScheduledActionActivateSyncTree", client
, 1, 3);
1826 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
, 2, 3);
1828 EXPECT_ACTION("ScheduledActionCommit", client
, 0, 2);
1829 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
, 1, 2);
1833 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency
) {
1834 bool impl_side_painting
= false;
1835 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
1839 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint
) {
1840 bool impl_side_painting
= true;
1841 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting
);
1844 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting
) {
1845 FakeSchedulerClient client
;
1846 SchedulerSettings scheduler_settings
;
1847 scheduler_settings
.impl_side_painting
= impl_side_painting
;
1848 scheduler_settings
.use_external_begin_frame_source
= true;
1849 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1850 scheduler
->SetCanStart();
1851 scheduler
->SetVisible(true);
1852 scheduler
->SetCanDraw(true);
1854 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1855 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1857 // SetNeedsCommit should begin the frame.
1859 scheduler
->SetNeedsCommit();
1860 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client
);
1863 client
.AdvanceFrame();
1864 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1865 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1866 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1869 scheduler
->NotifyBeginMainFrameStarted();
1870 scheduler
->NotifyReadyToCommit();
1871 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1874 scheduler
->DidLoseOutputSurface();
1875 if (impl_side_painting
) {
1876 // Sync tree should be forced to activate.
1877 EXPECT_ACTION("SetNeedsBeginFrames(false)", client
, 0, 2);
1878 EXPECT_ACTION("ScheduledActionActivateSyncTree", client
, 1, 2);
1880 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client
);
1884 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1885 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
1888 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommit
) {
1889 DidLoseOutputSurfaceAfterReadyToCommit(false);
1892 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting
) {
1893 DidLoseOutputSurfaceAfterReadyToCommit(true);
1896 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles
) {
1897 FakeSchedulerClient client
;
1898 SchedulerSettings scheduler_settings
;
1899 scheduler_settings
.use_external_begin_frame_source
= true;
1900 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1901 scheduler
->SetCanStart();
1902 scheduler
->SetVisible(true);
1903 scheduler
->SetCanDraw(true);
1904 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1907 scheduler
->SetNeedsPrepareTiles();
1908 scheduler
->SetNeedsRedraw();
1909 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client
);
1912 client
.AdvanceFrame();
1913 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1914 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
1915 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1918 scheduler
->DidLoseOutputSurface();
1919 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client
);
1922 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1923 EXPECT_ACTION("ScheduledActionPrepareTiles", client
, 0, 2);
1924 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
, 1, 2);
1927 TEST(SchedulerTest
, DidLoseOutputSurfaceAfterBeginRetroFramePosted
) {
1928 FakeSchedulerClient client
;
1929 SchedulerSettings scheduler_settings
;
1930 scheduler_settings
.use_external_begin_frame_source
= true;
1931 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1932 scheduler
->SetCanStart();
1933 scheduler
->SetVisible(true);
1934 scheduler
->SetCanDraw(true);
1935 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1937 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1939 scheduler
->SetNeedsCommit();
1940 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client
);
1942 // Create a BeginFrame with a long deadline to avoid race conditions.
1943 // This is the first BeginFrame, which will be handled immediately.
1945 BeginFrameArgs args
=
1946 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, client
.now_src());
1947 args
.deadline
+= base::TimeDelta::FromHours(1);
1948 client
.fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1949 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
1950 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
1951 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
1952 EXPECT_TRUE(client
.needs_begin_frames());
1954 // Queue BeginFrames while we are still handling the previous BeginFrame.
1955 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1956 client
.fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1957 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
1958 client
.fake_external_begin_frame_source()->TestOnBeginFrame(args
);
1960 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1962 client
.task_runner().RunPendingTasks(); // Run posted deadline.
1963 EXPECT_NO_ACTION(client
);
1964 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
1965 EXPECT_TRUE(client
.needs_begin_frames());
1967 // NotifyReadyToCommit should trigger the commit.
1969 scheduler
->NotifyBeginMainFrameStarted();
1970 scheduler
->NotifyReadyToCommit();
1971 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
1972 EXPECT_TRUE(client
.needs_begin_frames());
1975 EXPECT_FALSE(scheduler
->IsBeginRetroFrameArgsEmpty());
1976 scheduler
->DidLoseOutputSurface();
1977 EXPECT_ACTION("SetNeedsBeginFrames(false)", client
, 0, 2);
1978 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
, 1, 2);
1979 EXPECT_TRUE(scheduler
->IsBeginRetroFrameArgsEmpty());
1981 // Posted BeginRetroFrame is aborted.
1983 client
.task_runner().RunPendingTasks();
1984 EXPECT_NO_ACTION(client
);
1987 TEST(SchedulerTest
, DidLoseOutputSurfaceDuringBeginRetroFrameRunning
) {
1988 FakeSchedulerClient client
;
1989 SchedulerSettings scheduler_settings
;
1990 scheduler_settings
.use_external_begin_frame_source
= true;
1991 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
1992 scheduler
->SetCanStart();
1993 scheduler
->SetVisible(true);
1994 scheduler
->SetCanDraw(true);
1995 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
1997 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1999 scheduler
->SetNeedsCommit();
2000 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client
);
2002 // Create a BeginFrame with a long deadline to avoid race conditions.
2003 // This is the first BeginFrame, which will be handled immediately.
2005 BeginFrameArgs args
=
2006 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, client
.now_src());
2007 args
.deadline
+= base::TimeDelta::FromHours(1);
2008 client
.fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2009 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
2010 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
2011 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
2012 EXPECT_TRUE(client
.needs_begin_frames());
2014 // Queue BeginFrames while we are still handling the previous BeginFrame.
2015 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2016 client
.fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2017 args
.frame_time
+= base::TimeDelta::FromSeconds(1);
2018 client
.fake_external_begin_frame_source()->TestOnBeginFrame(args
);
2020 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2022 client
.task_runner().RunPendingTasks(); // Run posted deadline.
2023 EXPECT_NO_ACTION(client
);
2024 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
2025 EXPECT_TRUE(client
.needs_begin_frames());
2027 // NotifyReadyToCommit should trigger the commit.
2029 scheduler
->NotifyBeginMainFrameStarted();
2030 scheduler
->NotifyReadyToCommit();
2031 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
2032 EXPECT_TRUE(client
.needs_begin_frames());
2034 // BeginImplFrame should prepare the draw.
2036 client
.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2037 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
2038 EXPECT_ACTION("ScheduledActionAnimate", client
, 1, 2);
2039 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
2040 EXPECT_TRUE(client
.needs_begin_frames());
2043 EXPECT_FALSE(scheduler
->IsBeginRetroFrameArgsEmpty());
2044 scheduler
->DidLoseOutputSurface();
2045 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client
);
2046 EXPECT_TRUE(scheduler
->IsBeginRetroFrameArgsEmpty());
2048 // BeginImplFrame deadline should abort drawing.
2050 client
.task_runner().RunPendingTasks(); // Run posted deadline.
2051 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
2052 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
2053 EXPECT_FALSE(client
.needs_begin_frames());
2055 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
2057 client
.task_runner().RunPendingTasks();
2058 EXPECT_NO_ACTION(client
);
2062 StopBeginFrameAfterDidLoseOutputSurfaceWithSyntheticBeginFrameSource
) {
2063 FakeSchedulerClient client
;
2064 SchedulerSettings scheduler_settings
;
2065 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
2066 scheduler
->SetCanStart();
2067 scheduler
->SetVisible(true);
2068 scheduler
->SetCanDraw(true);
2069 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
2071 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2073 EXPECT_FALSE(scheduler
->frame_source().NeedsBeginFrames());
2074 scheduler
->SetNeedsCommit();
2075 EXPECT_TRUE(scheduler
->frame_source().NeedsBeginFrames());
2078 client
.task_runner().RunPendingTasks(); // Run posted Tick.
2079 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
2080 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
2081 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
2082 EXPECT_TRUE(scheduler
->frame_source().NeedsBeginFrames());
2084 // NotifyReadyToCommit should trigger the commit.
2086 scheduler
->NotifyBeginMainFrameStarted();
2087 scheduler
->NotifyReadyToCommit();
2088 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
2089 EXPECT_TRUE(scheduler
->frame_source().NeedsBeginFrames());
2092 scheduler
->DidLoseOutputSurface();
2093 EXPECT_NO_ACTION(client
);
2094 EXPECT_FALSE(scheduler
->frame_source().NeedsBeginFrames());
2097 client
.task_runner().RunPendingTasks(); // Run posted deadline.
2098 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
2099 EXPECT_FALSE(scheduler
->frame_source().NeedsBeginFrames());
2102 TEST(SchedulerTest
, ScheduledActionActivateAfterBecomingInvisible
) {
2103 FakeSchedulerClient client
;
2104 SchedulerSettings scheduler_settings
;
2105 scheduler_settings
.impl_side_painting
= true;
2106 scheduler_settings
.use_external_begin_frame_source
= true;
2107 TestScheduler
* scheduler
= client
.CreateScheduler(scheduler_settings
);
2108 scheduler
->SetCanStart();
2109 scheduler
->SetVisible(true);
2110 scheduler
->SetCanDraw(true);
2112 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client
);
2113 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
2115 // SetNeedsCommit should begin the frame.
2117 scheduler
->SetNeedsCommit();
2118 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client
);
2121 client
.AdvanceFrame();
2122 EXPECT_ACTION("WillBeginImplFrame", client
, 0, 2);
2123 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client
, 1, 2);
2124 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
2127 scheduler
->NotifyBeginMainFrameStarted();
2128 scheduler
->NotifyReadyToCommit();
2129 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client
);
2132 scheduler
->SetVisible(false);
2133 // Sync tree should be forced to activate.
2134 EXPECT_ACTION("SetNeedsBeginFrames(false)", client
, 0, 2);
2135 EXPECT_ACTION("ScheduledActionActivateSyncTree", client
, 1, 2);
2138 TEST(SchedulerTest
, SchedulerPowerMonitoring
) {
2139 FakeSchedulerClient client
;
2140 SchedulerSettings settings
;
2141 settings
.disable_hi_res_timer_tasks_on_battery
= true;
2142 TestScheduler
* scheduler
= client
.CreateScheduler(settings
);
2144 base::TimeTicks before_deadline
, after_deadline
;
2146 scheduler
->SetCanStart();
2147 scheduler
->SetVisible(true);
2148 scheduler
->SetCanDraw(true);
2150 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
2152 scheduler
->SetNeedsCommit();
2153 scheduler
->SetNeedsRedraw();
2156 // On non-battery power
2157 EXPECT_FALSE(client
.PowerMonitor()->IsOnBatteryPower());
2159 client
.AdvanceFrame();
2162 before_deadline
= client
.now_src()->Now();
2163 EXPECT_TRUE(client
.task_runner().RunTasksWhile(
2164 client
.ImplFrameDeadlinePending(true)));
2165 after_deadline
= client
.now_src()->Now();
2167 // We post a non-zero deadline task when not on battery
2168 EXPECT_LT(before_deadline
, after_deadline
);
2170 // Switch to battery power
2171 client
.PowerMonitorSource()->GeneratePowerStateEvent(true);
2172 EXPECT_TRUE(client
.PowerMonitor()->IsOnBatteryPower());
2174 client
.AdvanceFrame();
2175 scheduler
->SetNeedsCommit();
2176 scheduler
->SetNeedsRedraw();
2179 before_deadline
= client
.now_src()->Now();
2180 EXPECT_TRUE(client
.task_runner().RunTasksWhile(
2181 client
.ImplFrameDeadlinePending(true)));
2182 after_deadline
= client
.now_src()->Now();
2184 // We post a zero deadline task when on battery
2185 EXPECT_EQ(before_deadline
, after_deadline
);
2187 // Switch to non-battery power
2188 client
.PowerMonitorSource()->GeneratePowerStateEvent(false);
2189 EXPECT_FALSE(client
.PowerMonitor()->IsOnBatteryPower());
2191 client
.AdvanceFrame();
2192 scheduler
->SetNeedsCommit();
2193 scheduler
->SetNeedsRedraw();
2197 before_deadline
= client
.now_src()->Now();
2198 EXPECT_TRUE(client
.task_runner().RunTasksWhile(
2199 client
.ImplFrameDeadlinePending(true)));
2200 after_deadline
= client
.now_src()->Now();
2204 SimulateWindowsLowResolutionTimerOnBattery_PrioritizeImplLatencyOff
) {
2205 FakeSchedulerClient client
;
2206 SchedulerSettings settings
;
2207 settings
.use_external_begin_frame_source
= true;
2208 TestScheduler
* scheduler
= client
.CreateScheduler(settings
);
2210 scheduler
->SetCanStart();
2211 scheduler
->SetVisible(true);
2212 scheduler
->SetCanDraw(true);
2214 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
2216 // Set needs commit so that the scheduler tries to wait for the main thread
2217 scheduler
->SetNeedsCommit();
2218 // Set needs redraw so that the scheduler doesn't wait too long
2219 scheduler
->SetNeedsRedraw();
2222 // Switch to battery power
2223 client
.PowerMonitorSource()->GeneratePowerStateEvent(true);
2224 EXPECT_TRUE(client
.PowerMonitor()->IsOnBatteryPower());
2226 client
.AdvanceFrame();
2227 scheduler
->SetNeedsCommit();
2228 scheduler
->SetNeedsRedraw();
2231 // Disable auto-advancing of now_src
2232 client
.task_runner().SetAutoAdvanceNowToPendingTasks(false);
2234 // Deadline task is pending
2235 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
2236 client
.task_runner().RunPendingTasks();
2237 // Deadline task is still pending
2238 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
2240 // Advance now by 15 ms - same as windows low res timer
2241 client
.now_src()->AdvanceNowMicroseconds(15000);
2242 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
2243 client
.task_runner().RunPendingTasks();
2244 // Deadline task finally completes
2245 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());
2249 SimulateWindowsLowResolutionTimerOnBattery_PrioritizeImplLatencyOn
) {
2250 FakeSchedulerClient client
;
2251 SchedulerSettings settings
;
2252 settings
.disable_hi_res_timer_tasks_on_battery
= true;
2253 settings
.use_external_begin_frame_source
= true;
2254 TestScheduler
* scheduler
= client
.CreateScheduler(settings
);
2256 scheduler
->SetCanStart();
2257 scheduler
->SetVisible(true);
2258 scheduler
->SetCanDraw(true);
2260 InitializeOutputSurfaceAndFirstCommit(scheduler
, &client
);
2262 // Set needs commit so that the scheduler tries to wait for the main thread
2263 scheduler
->SetNeedsCommit();
2264 // Set needs redraw so that the scheduler doesn't wait too long
2265 scheduler
->SetNeedsRedraw();
2268 // Switch to battery power
2269 client
.PowerMonitorSource()->GeneratePowerStateEvent(true);
2270 EXPECT_TRUE(client
.PowerMonitor()->IsOnBatteryPower());
2272 client
.AdvanceFrame();
2273 scheduler
->SetNeedsCommit();
2274 scheduler
->SetNeedsRedraw();
2277 // Disable auto-advancing of now_src
2278 client
.task_runner().SetAutoAdvanceNowToPendingTasks(false);
2280 // Deadline task is pending
2281 EXPECT_TRUE(scheduler
->BeginImplFrameDeadlinePending());
2282 client
.task_runner().RunPendingTasks();
2283 // Deadline task runs immediately
2284 EXPECT_FALSE(scheduler
->BeginImplFrameDeadlinePending());