Enable Enhanced Bookmark on Android Tablet
[chromium-blink-merge.git] / cc / scheduler / scheduler_unittest.cc
blob46242e3d6b97bec4b20f3e17a440f26715da0886
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"
7 #include <string>
8 #include <vector>
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) \
25 do { \
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)); \
30 } \
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); \
34 } while (false)
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 namespace cc {
42 namespace {
44 class FakeSchedulerClient;
46 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler,
47 FakeSchedulerClient* client);
49 class FakeSchedulerClient : public SchedulerClient {
50 public:
51 class FakeExternalBeginFrameSource : public BeginFrameSourceMixIn {
52 public:
53 explicit FakeExternalBeginFrameSource(FakeSchedulerClient* client)
54 : client_(client) {}
55 virtual ~FakeExternalBeginFrameSource() {}
57 void OnNeedsBeginFramesChange(bool needs_begin_frames) override {
58 if (needs_begin_frames) {
59 client_->actions_.push_back("SetNeedsBeginFrames(true)");
60 } else {
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);
70 private:
71 FakeSchedulerClient* client_;
74 class FakePowerMonitorSource : public base::PowerMonitorSource {
75 public:
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_; }
85 private:
86 bool on_battery_power_impl_;
89 FakeSchedulerClient()
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_)),
98 scheduler_(nullptr) {
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);
103 Reset();
106 void Reset() {
107 actions_.clear();
108 states_.clear();
109 draw_will_happen_ = true;
110 swap_will_happen_if_draw_happens_ = true;
111 num_draws_ = 0;
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_,
126 this,
127 settings,
129 task_runner_,
130 &power_monitor_,
131 fake_external_begin_frame_source.Pass());
132 DCHECK(scheduler_);
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))
203 return i;
204 return -1;
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());
236 num_draws_++;
237 DrawResult result =
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();
247 return result;
249 DrawResult ScheduledActionDrawAndSwapForced() override {
250 actions_.push_back("ScheduledActionDrawAndSwapForced");
251 states_.push_back(scheduler_->AsValue());
252 return DRAW_SUCCESS;
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),
291 state);
294 bool begin_frame_is_sent_to_children() const {
295 return begin_frame_is_sent_to_children_;
298 protected:
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_;
306 int num_draws_;
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) {
322 TRACE_EVENT0("cc",
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());
343 SCOPED_TRACE(
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);
365 client.Reset();
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);
383 client.Reset();
384 EXPECT_FALSE(client.begin_frame_is_sent_to_children());
385 scheduler->SetNeedsCommit();
386 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
387 client.Reset();
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());
397 client.Reset();
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.
413 client.Reset();
414 scheduler->SetNeedsCommit();
415 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
416 client.Reset();
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());
423 client.Reset();
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());
430 client.Reset();
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());
437 client.Reset();
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());
445 client.Reset();
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());
452 client.Reset();
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());
459 client.Reset();
461 client.task_runner().RunPendingTasks(); // Run posted deadline.
462 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client);
463 client.Reset();
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);
477 client.Reset();
479 // SetNeedsCommit should begin the frame.
480 scheduler->SetNeedsCommit();
481 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
483 client.Reset();
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());
490 client.Reset();
492 // Now SetNeedsCommit again. Calling here means we need a second commit.
493 scheduler->SetNeedsCommit();
494 EXPECT_EQ(client.num_actions_(), 0);
495 client.Reset();
497 // Finish the first commit.
498 scheduler->NotifyBeginMainFrameStarted();
499 scheduler->NotifyReadyToCommit();
500 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
501 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
502 client.Reset();
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());
511 client.Reset();
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());
518 client.Reset();
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());
526 client.Reset();
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());
532 client.Reset();
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());
539 client.Reset();
542 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
543 public:
544 void ScheduledActionSendBeginMainFrame() override {}
545 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
546 // Only SetNeedsRedraw the first time this is called
547 if (!num_draws_)
548 scheduler_->SetNeedsRedraw();
549 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
552 DrawResult ScheduledActionDrawAndSwapForced() override {
553 NOTREACHED();
554 return DRAW_SUCCESS;
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);
575 client.Reset();
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
595 // swap.
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);
613 client.Reset();
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());
622 // Fail the draw.
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
628 // request.
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 {
652 public:
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 {
667 NOTREACHED();
668 return DRAW_SUCCESS;
671 void ScheduledActionCommit() override {}
672 void ScheduledActionBeginOutputSurfaceCreation() override {}
673 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {}
675 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; }
677 private:
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);
692 client.Reset();
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
719 // swap.
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);
738 client.Reset();
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());
747 // Fail the draw.
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
753 // request.
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);
786 client.Reset();
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 {
812 public:
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.
832 client.Reset();
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.
844 client.Reset();
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.
851 client.Reset();
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.
863 client.Reset();
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.
872 client.Reset();
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.
881 client.Reset();
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.
893 client.Reset();
894 client.AdvanceFrame();
895 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
896 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
897 client.Reset();
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.
905 client.Reset();
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.
913 client.Reset();
914 client.AdvanceFrame();
915 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
916 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
917 client.Reset();
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
938 // again.
939 scheduler->SetNeedsPrepareTiles();
940 scheduler->SetNeedsRedraw();
941 client.Reset();
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());
951 client.Reset();
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();
963 client.Reset();
964 client.AdvanceFrame();
965 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
966 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
967 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
969 client.Reset();
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();
986 client.Reset();
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());
994 client.Reset();
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
1004 // twice.
1005 EXPECT_TRUE(scheduler->PrepareTilesPending());
1006 scheduler->DidPrepareTiles(); // An explicit PrepareTiles.
1007 EXPECT_FALSE(scheduler->PrepareTilesPending());
1008 scheduler->SetNeedsPrepareTiles();
1009 scheduler->SetNeedsRedraw();
1010 client.Reset();
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());
1018 client.Reset();
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();
1029 client.Reset();
1030 client.AdvanceFrame();
1031 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1032 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1033 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1035 client.Reset();
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);
1058 client.Reset();
1059 scheduler->SetNeedsRedraw();
1060 client.AdvanceFrame();
1062 // The deadline should be zero since there is no work other than drawing
1063 // pending.
1064 EXPECT_EQ(base::TimeTicks(), client.posted_begin_impl_frame_deadline());
1067 class SchedulerClientWithFixedEstimates : public FakeSchedulerClient {
1068 public:
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_;
1086 private:
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.
1112 client.Reset();
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"));
1124 client.Reset();
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);
1136 TEST(SchedulerTest,
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
1158 // priority mode.
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.
1252 client.Reset();
1253 scheduler->SetNeedsCommit();
1254 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1255 client.Reset();
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());
1267 client.Reset();
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());
1280 client.Reset();
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());
1287 client.Reset();
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());
1295 client.Reset();
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());
1302 client.Reset();
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());
1309 client.Reset();
1311 client.task_runner().RunPendingTasks(); // Run posted deadline.
1312 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client);
1313 client.Reset();
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.
1332 client.Reset();
1333 scheduler->SetNeedsCommit();
1334 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1335 client.Reset();
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());
1342 client.Reset();
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());
1349 client.Reset();
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());
1356 client.Reset();
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());
1365 client.Reset();
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());
1377 client.Reset();
1379 // Let time pass sufficiently beyond the regular deadline but not beyond the
1380 // late deadline.
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());
1391 client.Reset();
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());
1398 client.Reset();
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);
1411 client.Reset();
1412 scheduler->SetNeedsCommit();
1413 EXPECT_TRUE(client.needs_begin_frames());
1414 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1416 client.Reset();
1417 client.AdvanceFrame();
1418 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1419 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1420 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1422 client.Reset();
1423 scheduler->NotifyBeginMainFrameStarted();
1425 client.Reset();
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());
1432 client.Reset();
1433 // This commit should schedule the (previous) deadline to trigger immediately.
1434 scheduler->NotifyReadyToCommit();
1435 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1437 client.Reset();
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);
1444 // Keep animating.
1445 client.Reset();
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.
1463 client.Reset();
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);
1479 client.Reset();
1480 scheduler->SetNeedsCommit();
1481 EXPECT_TRUE(client.needs_begin_frames());
1482 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1484 client.Reset();
1485 client.AdvanceFrame();
1486 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1487 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1488 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1490 client.Reset();
1491 scheduler->NotifyBeginMainFrameStarted();
1493 client.Reset();
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());
1500 client.Reset();
1501 // This commit should schedule the (previous) deadline to trigger immediately.
1502 scheduler->NotifyReadyToCommit();
1503 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1505 client.Reset();
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);
1512 // Keep animating.
1513 client.Reset();
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.
1543 client.Reset();
1544 scheduler->SetNeedsCommit();
1545 EXPECT_NO_ACTION(client);
1546 client.Reset();
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());
1554 client.Reset();
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());
1560 client.Reset();
1562 // NotifyReadyToCommit should trigger the commit.
1563 scheduler->NotifyBeginMainFrameStarted();
1564 scheduler->NotifyReadyToCommit();
1565 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1566 client.Reset();
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());
1573 client.Reset();
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());
1579 client.Reset();
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());
1586 client.Reset();
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);
1592 client.Reset();
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.
1638 client.Reset();
1639 scheduler->SetNeedsCommit();
1640 EXPECT_NO_ACTION(client);
1641 client.Reset();
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());
1648 client.Reset();
1650 // NotifyReadyToCommit should trigger the pending commit and draw.
1651 scheduler->NotifyBeginMainFrameStarted();
1652 scheduler->NotifyReadyToCommit();
1653 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1654 client.Reset();
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());
1662 client.Reset();
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());
1672 client.Reset();
1674 // Let time pass sufficiently beyond the regular deadline but not beyond the
1675 // late deadline.
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());
1685 client.Reset();
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());
1695 client.Reset();
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);
1712 TEST(SchedulerTest,
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);
1730 client.Reset();
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.
1750 client.Reset();
1751 scheduler->SetNeedsCommit();
1752 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1754 client.Reset();
1755 client.AdvanceFrame();
1756 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1757 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1758 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1760 client.Reset();
1761 scheduler->DidLoseOutputSurface();
1762 // Do nothing when impl frame is in deadine pending state.
1763 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client);
1765 client.Reset();
1766 scheduler->NotifyBeginMainFrameStarted();
1767 scheduler->NotifyReadyToCommit();
1768 EXPECT_ACTION("ScheduledActionCommit", client, 0, 1);
1770 client.Reset();
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.
1790 client.Reset();
1791 scheduler->SetNeedsCommit();
1792 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1794 client.Reset();
1795 client.AdvanceFrame();
1796 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1797 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1798 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1800 client.Reset();
1801 scheduler->DidLoseOutputSurface();
1802 // Do nothing when impl frame is in deadine pending state.
1803 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client);
1805 client.Reset();
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());
1820 client.Reset();
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);
1827 } else {
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);
1838 TEST(SchedulerTest,
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.
1858 client.Reset();
1859 scheduler->SetNeedsCommit();
1860 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1862 client.Reset();
1863 client.AdvanceFrame();
1864 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1865 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1866 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1868 client.Reset();
1869 scheduler->NotifyBeginMainFrameStarted();
1870 scheduler->NotifyReadyToCommit();
1871 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1873 client.Reset();
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);
1879 } else {
1880 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client);
1883 client.Reset();
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);
1906 client.Reset();
1907 scheduler->SetNeedsPrepareTiles();
1908 scheduler->SetNeedsRedraw();
1909 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1911 client.Reset();
1912 client.AdvanceFrame();
1913 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1914 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1915 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1917 client.Reset();
1918 scheduler->DidLoseOutputSurface();
1919 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client);
1921 client.Reset();
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.
1938 client.Reset();
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.
1944 client.Reset();
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.
1961 client.Reset();
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.
1968 client.Reset();
1969 scheduler->NotifyBeginMainFrameStarted();
1970 scheduler->NotifyReadyToCommit();
1971 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1972 EXPECT_TRUE(client.needs_begin_frames());
1974 client.Reset();
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.
1982 client.Reset();
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.
1998 client.Reset();
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.
2004 client.Reset();
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.
2021 client.Reset();
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.
2028 client.Reset();
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.
2035 client.Reset();
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());
2042 client.Reset();
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.
2049 client.Reset();
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.
2056 client.Reset();
2057 client.task_runner().RunPendingTasks();
2058 EXPECT_NO_ACTION(client);
2061 TEST(SchedulerTest,
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.
2072 client.Reset();
2073 EXPECT_FALSE(scheduler->frame_source().NeedsBeginFrames());
2074 scheduler->SetNeedsCommit();
2075 EXPECT_TRUE(scheduler->frame_source().NeedsBeginFrames());
2077 client.Reset();
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.
2085 client.Reset();
2086 scheduler->NotifyBeginMainFrameStarted();
2087 scheduler->NotifyReadyToCommit();
2088 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
2089 EXPECT_TRUE(scheduler->frame_source().NeedsBeginFrames());
2091 client.Reset();
2092 scheduler->DidLoseOutputSurface();
2093 EXPECT_NO_ACTION(client);
2094 EXPECT_FALSE(scheduler->frame_source().NeedsBeginFrames());
2096 client.Reset();
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.
2116 client.Reset();
2117 scheduler->SetNeedsCommit();
2118 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
2120 client.Reset();
2121 client.AdvanceFrame();
2122 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
2123 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
2124 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
2126 client.Reset();
2127 scheduler->NotifyBeginMainFrameStarted();
2128 scheduler->NotifyReadyToCommit();
2129 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
2131 client.Reset();
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();
2154 client.Reset();
2156 // On non-battery power
2157 EXPECT_FALSE(client.PowerMonitor()->IsOnBatteryPower());
2159 client.AdvanceFrame();
2160 client.Reset();
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();
2177 client.Reset();
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();
2194 client.Reset();
2196 // Same as before
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();
2203 TEST(SchedulerTest,
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();
2220 client.Reset();
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();
2229 client.Reset();
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());
2248 TEST(SchedulerTest,
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();
2266 client.Reset();
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();
2275 client.Reset();
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());
2287 } // namespace
2288 } // namespace cc