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