Don't preview autofill/autocomplete until first real mouse move.
[chromium-blink-merge.git] / cc / scheduler / scheduler_unittest.cc
blob50cc846c44114edffbc07dfdc6f0faf117b95299
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 void SendBeginMainFrameNotExpectedSoon() override {
165 PushAction("SendBeginMainFrameNotExpectedSoon");
168 base::Callback<bool(void)> ImplFrameDeadlinePending(bool state) {
169 return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback,
170 base::Unretained(this),
171 state);
174 bool begin_frame_is_sent_to_children() const {
175 return begin_frame_is_sent_to_children_;
178 void PushAction(const char* description) {
179 actions_.push_back(description);
180 states_.push_back(scheduler_->AsValue());
183 protected:
184 bool ImplFrameDeadlinePendingCallback(bool state) {
185 return scheduler_->BeginImplFrameDeadlinePending() == state;
188 bool draw_will_happen_;
189 bool swap_will_happen_if_draw_happens_;
190 bool automatic_swap_ack_;
191 int num_draws_;
192 bool log_anticipated_draw_time_change_;
193 bool begin_frame_is_sent_to_children_;
194 base::TimeTicks posted_begin_impl_frame_deadline_;
195 std::vector<const char*> actions_;
196 std::vector<scoped_refptr<base::trace_event::ConvertableToTraceFormat>>
197 states_;
198 TestScheduler* scheduler_;
201 class FakePowerMonitorSource : public base::PowerMonitorSource {
202 public:
203 FakePowerMonitorSource() {}
204 ~FakePowerMonitorSource() override {}
205 void GeneratePowerStateEvent(bool on_battery_power) {
206 on_battery_power_impl_ = on_battery_power;
207 ProcessPowerEvent(POWER_STATE_EVENT);
208 base::MessageLoop::current()->RunUntilIdle();
210 bool IsOnBatteryPowerImpl() override { return on_battery_power_impl_; }
212 private:
213 bool on_battery_power_impl_;
216 class FakeExternalBeginFrameSource : public BeginFrameSourceMixIn {
217 public:
218 explicit FakeExternalBeginFrameSource(FakeSchedulerClient* client)
219 : client_(client) {}
220 ~FakeExternalBeginFrameSource() override {}
222 void OnNeedsBeginFramesChange(bool needs_begin_frames) override {
223 if (needs_begin_frames) {
224 client_->PushAction("SetNeedsBeginFrames(true)");
225 } else {
226 client_->PushAction("SetNeedsBeginFrames(false)");
230 void TestOnBeginFrame(const BeginFrameArgs& args) {
231 return CallOnBeginFrame(args);
234 private:
235 FakeSchedulerClient* client_;
238 class SchedulerTest : public testing::Test {
239 public:
240 SchedulerTest()
241 : now_src_(TestNowSource::Create()),
242 task_runner_(new OrderedSimpleTaskRunner(now_src_, true)),
243 fake_external_begin_frame_source_(nullptr),
244 fake_power_monitor_source_(new FakePowerMonitorSource),
245 power_monitor_(make_scoped_ptr<base::PowerMonitorSource>(
246 fake_power_monitor_source_)) {
247 // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval()
248 now_src_->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
249 // Fail if we need to run 100 tasks in a row.
250 task_runner_->SetRunTaskLimit(100);
253 ~SchedulerTest() override {}
255 protected:
256 TestScheduler* CreateScheduler() {
257 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source;
258 if (scheduler_settings_.use_external_begin_frame_source) {
259 fake_external_begin_frame_source.reset(
260 new FakeExternalBeginFrameSource(client_.get()));
261 fake_external_begin_frame_source_ =
262 fake_external_begin_frame_source.get();
264 scheduler_ = TestScheduler::Create(
265 now_src_, client_.get(), scheduler_settings_, 0, task_runner_,
266 &power_monitor_, fake_external_begin_frame_source.Pass());
267 DCHECK(scheduler_);
268 client_->set_scheduler(scheduler_.get());
269 return scheduler_.get();
272 void CreateSchedulerAndInitSurface() {
273 CreateScheduler();
274 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit());
277 void SetUpScheduler(bool initSurface) {
278 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient), initSurface);
281 void SetUpScheduler(scoped_ptr<FakeSchedulerClient> client,
282 bool initSurface) {
283 client_ = client.Pass();
284 if (initSurface)
285 CreateSchedulerAndInitSurface();
286 else
287 CreateScheduler();
290 OrderedSimpleTaskRunner& task_runner() { return *task_runner_; }
291 TestNowSource* now_src() { return now_src_.get(); }
293 // As this function contains EXPECT macros, to allow debugging it should be
294 // called inside EXPECT_SCOPED like so;
295 // EXPECT_SCOPED(client.InitializeOutputSurfaceAndFirstCommit(scheduler));
296 void InitializeOutputSurfaceAndFirstCommit() {
297 TRACE_EVENT0("cc",
298 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit");
299 DCHECK(scheduler_);
301 // Check the client doesn't have any actions queued when calling this
302 // function.
303 EXPECT_NO_ACTION(client_);
304 EXPECT_FALSE(client_->needs_begin_frames());
306 // Start the initial output surface creation.
307 EXPECT_FALSE(scheduler_->CanStart());
308 scheduler_->SetCanStart();
309 scheduler_->SetVisible(true);
310 scheduler_->SetCanDraw(true);
311 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
313 client_->Reset();
315 // We don't see anything happening until the first impl frame.
316 scheduler_->DidCreateAndInitializeOutputSurface();
317 scheduler_->SetNeedsCommit();
318 EXPECT_TRUE(client_->needs_begin_frames());
319 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
320 client_->Reset();
323 SCOPED_TRACE("Do first frame to commit after initialize.");
324 AdvanceFrame();
326 scheduler_->NotifyBeginMainFrameStarted();
327 scheduler_->NotifyReadyToCommitThenActivateIfNeeded();
329 // Run the posted deadline task.
330 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
331 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
332 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
334 EXPECT_FALSE(scheduler_->CommitPending());
337 client_->Reset();
340 SCOPED_TRACE(
341 "Run second frame so Scheduler calls SetNeedsBeginFrame(false).");
342 AdvanceFrame();
344 // Run the posted deadline task.
345 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
346 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
347 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
350 EXPECT_FALSE(client_->needs_begin_frames());
351 client_->Reset();
354 // As this function contains EXPECT macros, to allow debugging it should be
355 // called inside EXPECT_SCOPED like so;
356 // EXPECT_SCOPED(client.AdvanceFrame());
357 void AdvanceFrame() {
358 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
359 "FakeSchedulerClient::AdvanceFrame");
360 // Consume any previous deadline first, if no deadline is currently
361 // pending, ImplFrameDeadlinePending will return false straight away and we
362 // will run no tasks.
363 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
364 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
366 // Send the next BeginFrame message if using an external source, otherwise
367 // it will be already in the task queue.
368 if (scheduler_->settings().use_external_begin_frame_source &&
369 scheduler_->FrameProductionThrottled()) {
370 SendNextBeginFrame();
371 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
374 // Then run tasks until new deadline is scheduled.
375 EXPECT_TRUE(
376 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(false)));
377 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
380 void SendNextBeginFrame() {
381 DCHECK(scheduler_->settings().use_external_begin_frame_source);
382 // Creep the time forward so that any BeginFrameArgs is not equal to the
383 // last one otherwise we violate the BeginFrameSource contract.
384 now_src_->AdvanceNow(BeginFrameArgs::DefaultInterval());
385 fake_external_begin_frame_source_->TestOnBeginFrame(
386 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()));
389 base::PowerMonitor* PowerMonitor() { return &power_monitor_; }
390 FakePowerMonitorSource* PowerMonitorSource() {
391 return fake_power_monitor_source_;
394 FakeExternalBeginFrameSource* fake_external_begin_frame_source() const {
395 return fake_external_begin_frame_source_;
398 void MainFrameInHighLatencyMode(
399 int64 begin_main_frame_to_commit_estimate_in_ms,
400 int64 commit_to_activate_estimate_in_ms,
401 bool impl_latency_takes_priority,
402 bool should_send_begin_main_frame);
403 void BeginFramesNotFromClient(bool use_external_begin_frame_source,
404 bool throttle_frame_production);
405 void BeginFramesNotFromClient_SwapThrottled(
406 bool use_external_begin_frame_source,
407 bool throttle_frame_production);
408 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
409 bool impl_side_painting);
410 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting);
412 scoped_refptr<TestNowSource> now_src_;
413 scoped_refptr<OrderedSimpleTaskRunner> task_runner_;
414 FakeExternalBeginFrameSource* fake_external_begin_frame_source_;
415 FakePowerMonitorSource* fake_power_monitor_source_;
416 base::PowerMonitor power_monitor_;
417 SchedulerSettings scheduler_settings_;
418 scoped_ptr<FakeSchedulerClient> client_;
419 scoped_ptr<TestScheduler> scheduler_;
422 TEST_F(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) {
423 scheduler_settings_.use_external_begin_frame_source = true;
424 SetUpScheduler(false);
425 scheduler_->SetCanStart();
426 scheduler_->SetVisible(true);
427 scheduler_->SetCanDraw(true);
429 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
430 client_->Reset();
431 scheduler_->DidCreateAndInitializeOutputSurface();
432 EXPECT_NO_ACTION(client_);
435 TEST_F(SchedulerTest, SendBeginFramesToChildren) {
436 scheduler_settings_.use_external_begin_frame_source = true;
437 scheduler_settings_.forward_begin_frames_to_children = true;
438 SetUpScheduler(true);
440 EXPECT_FALSE(client_->begin_frame_is_sent_to_children());
441 scheduler_->SetNeedsCommit();
442 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
443 EXPECT_TRUE(client_->needs_begin_frames());
445 scheduler_->SetChildrenNeedBeginFrames(true);
447 client_->Reset();
448 EXPECT_SCOPED(AdvanceFrame());
449 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
450 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
451 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
452 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
453 EXPECT_TRUE(client_->needs_begin_frames());
456 TEST_F(SchedulerTest, SendBeginFramesToChildrenWithoutCommit) {
457 scheduler_settings_.use_external_begin_frame_source = true;
458 scheduler_settings_.forward_begin_frames_to_children = true;
459 SetUpScheduler(true);
461 EXPECT_FALSE(client_->needs_begin_frames());
462 scheduler_->SetChildrenNeedBeginFrames(true);
463 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
464 EXPECT_TRUE(client_->needs_begin_frames());
466 client_->Reset();
467 EXPECT_SCOPED(AdvanceFrame());
468 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
471 TEST_F(SchedulerTest, RequestCommit) {
472 scheduler_settings_.use_external_begin_frame_source = true;
473 SetUpScheduler(true);
475 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
476 scheduler_->SetNeedsCommit();
477 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
478 client_->Reset();
480 EXPECT_SCOPED(AdvanceFrame());
481 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
482 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
483 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
484 EXPECT_TRUE(client_->needs_begin_frames());
485 client_->Reset();
487 // If we don't swap on the deadline, we wait for the next BeginFrame.
488 task_runner().RunPendingTasks(); // Run posted deadline.
489 EXPECT_NO_ACTION(client_);
490 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
491 EXPECT_TRUE(client_->needs_begin_frames());
492 client_->Reset();
494 // NotifyReadyToCommit should trigger the commit.
495 scheduler_->NotifyBeginMainFrameStarted();
496 scheduler_->NotifyReadyToCommit();
497 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
498 EXPECT_TRUE(client_->needs_begin_frames());
499 client_->Reset();
501 // BeginImplFrame should prepare the draw.
502 EXPECT_SCOPED(AdvanceFrame());
503 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
504 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
505 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
506 EXPECT_TRUE(client_->needs_begin_frames());
507 client_->Reset();
509 // BeginImplFrame deadline should draw.
510 task_runner().RunPendingTasks(); // Run posted deadline.
511 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
512 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
513 EXPECT_TRUE(client_->needs_begin_frames());
514 client_->Reset();
516 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
517 // to avoid excessive toggles.
518 EXPECT_SCOPED(AdvanceFrame());
519 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
520 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
521 client_->Reset();
523 task_runner().RunPendingTasks(); // Run posted deadline.
524 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
525 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
526 client_->Reset();
529 TEST_F(SchedulerTest, RequestCommitAfterSetDeferCommit) {
530 scheduler_settings_.use_external_begin_frame_source = true;
531 SetUpScheduler(true);
533 scheduler_->SetCanStart();
534 scheduler_->SetVisible(true);
535 scheduler_->SetCanDraw(true);
537 scheduler_->SetDeferCommits(true);
539 scheduler_->SetNeedsCommit();
540 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
542 client_->Reset();
543 AdvanceFrame();
544 // BeginMainFrame is not sent during the defer commit is on.
545 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
547 client_->Reset();
548 task_runner().RunPendingTasks(); // Run posted deadline.
549 // There is no posted deadline.
550 EXPECT_NO_ACTION(client_);
551 EXPECT_TRUE(client_->needs_begin_frames());
553 client_->Reset();
554 scheduler_->SetDeferCommits(false);
555 EXPECT_NO_ACTION(client_);
557 // Start new BeginMainFrame after defer commit is off.
558 client_->Reset();
559 AdvanceFrame();
560 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
561 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
562 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
565 TEST_F(SchedulerTest, DeferCommitWithRedraw) {
566 scheduler_settings_.use_external_begin_frame_source = true;
567 SetUpScheduler(true);
569 scheduler_->SetCanStart();
570 scheduler_->SetVisible(true);
571 scheduler_->SetCanDraw(true);
573 scheduler_->SetDeferCommits(true);
575 scheduler_->SetNeedsCommit();
576 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
578 client_->Reset();
579 scheduler_->SetNeedsRedraw();
580 EXPECT_NO_ACTION(client_);
582 client_->Reset();
583 AdvanceFrame();
584 // BeginMainFrame is not sent during the defer commit is on.
585 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
586 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
588 client_->Reset();
589 task_runner().RunPendingTasks(); // Run posted deadline.
590 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
591 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
592 EXPECT_TRUE(client_->needs_begin_frames());
594 client_->Reset();
595 AdvanceFrame();
596 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
599 TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
600 scheduler_settings_.use_external_begin_frame_source = true;
601 SetUpScheduler(true);
603 // SetNeedsCommit should begin the frame.
604 scheduler_->SetNeedsCommit();
605 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
607 client_->Reset();
608 EXPECT_SCOPED(AdvanceFrame());
609 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
610 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
611 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
613 EXPECT_TRUE(client_->needs_begin_frames());
614 client_->Reset();
616 // Now SetNeedsCommit again. Calling here means we need a second commit.
617 scheduler_->SetNeedsCommit();
618 EXPECT_EQ(client_->num_actions_(), 0);
619 client_->Reset();
621 // Finish the first commit.
622 scheduler_->NotifyBeginMainFrameStarted();
623 scheduler_->NotifyReadyToCommit();
624 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
625 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
626 client_->Reset();
627 task_runner().RunPendingTasks(); // Run posted deadline.
628 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
629 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
630 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
632 // Because we just swapped, the Scheduler should also request the next
633 // BeginImplFrame from the OutputSurface.
634 EXPECT_TRUE(client_->needs_begin_frames());
635 client_->Reset();
636 // Since another commit is needed, the next BeginImplFrame should initiate
637 // the second commit.
638 EXPECT_SCOPED(AdvanceFrame());
639 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
640 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
641 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
642 client_->Reset();
644 // Finishing the commit before the deadline should post a new deadline task
645 // to trigger the deadline early.
646 scheduler_->NotifyBeginMainFrameStarted();
647 scheduler_->NotifyReadyToCommit();
648 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
649 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
650 client_->Reset();
651 task_runner().RunPendingTasks(); // Run posted deadline.
652 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
653 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
654 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
655 EXPECT_TRUE(client_->needs_begin_frames());
656 client_->Reset();
658 // On the next BeginImplFrame, verify we go back to a quiescent state and
659 // no longer request BeginImplFrames.
660 EXPECT_SCOPED(AdvanceFrame());
661 task_runner().RunPendingTasks(); // Run posted deadline.
662 EXPECT_FALSE(client_->needs_begin_frames());
663 client_->Reset();
666 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
667 public:
668 SchedulerClientThatsetNeedsDrawInsideDraw()
669 : FakeSchedulerClient(), request_redraws_(false) {}
671 void ScheduledActionSendBeginMainFrame() override {}
673 void SetRequestRedrawsInsideDraw(bool enable) { request_redraws_ = enable; }
675 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
676 // Only SetNeedsRedraw the first time this is called
677 if (request_redraws_) {
678 scheduler_->SetNeedsRedraw();
680 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
683 DrawResult ScheduledActionDrawAndSwapForced() override {
684 NOTREACHED();
685 return DRAW_SUCCESS;
688 void ScheduledActionCommit() override {}
689 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {}
691 private:
692 bool request_redraws_;
695 // Tests for two different situations:
696 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
697 // a ScheduledActionDrawAndSwap
698 // 2. the scheduler drawing twice inside a single tick
699 TEST_F(SchedulerTest, RequestRedrawInsideDraw) {
700 SchedulerClientThatsetNeedsDrawInsideDraw* client =
701 new SchedulerClientThatsetNeedsDrawInsideDraw;
702 scheduler_settings_.use_external_begin_frame_source = true;
703 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
704 client->SetRequestRedrawsInsideDraw(true);
706 scheduler_->SetNeedsRedraw();
707 EXPECT_TRUE(scheduler_->RedrawPending());
708 EXPECT_TRUE(client->needs_begin_frames());
709 EXPECT_EQ(0, client->num_draws());
711 EXPECT_SCOPED(AdvanceFrame());
712 task_runner().RunPendingTasks(); // Run posted deadline.
713 EXPECT_EQ(1, client->num_draws());
714 EXPECT_TRUE(scheduler_->RedrawPending());
715 EXPECT_TRUE(client->needs_begin_frames());
717 client->SetRequestRedrawsInsideDraw(false);
719 EXPECT_SCOPED(AdvanceFrame());
720 task_runner().RunPendingTasks(); // Run posted deadline.
721 EXPECT_EQ(2, client_->num_draws());
722 EXPECT_FALSE(scheduler_->RedrawPending());
723 EXPECT_TRUE(client->needs_begin_frames());
725 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
726 // swap.
727 EXPECT_SCOPED(AdvanceFrame());
728 task_runner().RunPendingTasks(); // Run posted deadline.
729 EXPECT_EQ(2, client->num_draws());
730 EXPECT_FALSE(scheduler_->RedrawPending());
731 EXPECT_FALSE(client->needs_begin_frames());
734 // Test that requesting redraw inside a failed draw doesn't lose the request.
735 TEST_F(SchedulerTest, RequestRedrawInsideFailedDraw) {
736 SchedulerClientThatsetNeedsDrawInsideDraw* client =
737 new SchedulerClientThatsetNeedsDrawInsideDraw;
738 scheduler_settings_.use_external_begin_frame_source = true;
739 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
741 client->SetRequestRedrawsInsideDraw(true);
742 client->SetDrawWillHappen(false);
744 scheduler_->SetNeedsRedraw();
745 EXPECT_TRUE(scheduler_->RedrawPending());
746 EXPECT_TRUE(client->needs_begin_frames());
747 EXPECT_EQ(0, client->num_draws());
749 // Fail the draw.
750 EXPECT_SCOPED(AdvanceFrame());
751 task_runner().RunPendingTasks(); // Run posted deadline.
752 EXPECT_EQ(1, client->num_draws());
754 // We have a commit pending and the draw failed, and we didn't lose the redraw
755 // request.
756 EXPECT_TRUE(scheduler_->CommitPending());
757 EXPECT_TRUE(scheduler_->RedrawPending());
758 EXPECT_TRUE(client->needs_begin_frames());
760 client->SetRequestRedrawsInsideDraw(false);
762 // Fail the draw again.
763 EXPECT_SCOPED(AdvanceFrame());
764 task_runner().RunPendingTasks(); // Run posted deadline.
765 EXPECT_EQ(2, client->num_draws());
766 EXPECT_TRUE(scheduler_->CommitPending());
767 EXPECT_TRUE(scheduler_->RedrawPending());
768 EXPECT_TRUE(client->needs_begin_frames());
770 // Draw successfully.
771 client->SetDrawWillHappen(true);
772 EXPECT_SCOPED(AdvanceFrame());
773 task_runner().RunPendingTasks(); // Run posted deadline.
774 EXPECT_EQ(3, client->num_draws());
775 EXPECT_TRUE(scheduler_->CommitPending());
776 EXPECT_FALSE(scheduler_->RedrawPending());
777 EXPECT_TRUE(client->needs_begin_frames());
780 class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
781 public:
782 SchedulerClientThatSetNeedsCommitInsideDraw()
783 : set_needs_commit_on_next_draw_(false) {}
785 void ScheduledActionSendBeginMainFrame() override {}
786 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
787 // Only SetNeedsCommit the first time this is called
788 if (set_needs_commit_on_next_draw_) {
789 scheduler_->SetNeedsCommit();
790 set_needs_commit_on_next_draw_ = false;
792 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
795 DrawResult ScheduledActionDrawAndSwapForced() override {
796 NOTREACHED();
797 return DRAW_SUCCESS;
800 void ScheduledActionCommit() override {}
801 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {}
803 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; }
805 private:
806 bool set_needs_commit_on_next_draw_;
809 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
810 // happen inside a ScheduledActionDrawAndSwap
811 TEST_F(SchedulerTest, RequestCommitInsideDraw) {
812 SchedulerClientThatSetNeedsCommitInsideDraw* client =
813 new SchedulerClientThatSetNeedsCommitInsideDraw;
815 scheduler_settings_.use_external_begin_frame_source = true;
816 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
818 EXPECT_FALSE(client->needs_begin_frames());
819 scheduler_->SetNeedsRedraw();
820 EXPECT_TRUE(scheduler_->RedrawPending());
821 EXPECT_EQ(0, client->num_draws());
822 EXPECT_TRUE(client->needs_begin_frames());
824 client->SetNeedsCommitOnNextDraw();
825 EXPECT_SCOPED(AdvanceFrame());
826 client->SetNeedsCommitOnNextDraw();
827 task_runner().RunPendingTasks(); // Run posted deadline.
828 EXPECT_EQ(1, client->num_draws());
829 EXPECT_TRUE(scheduler_->CommitPending());
830 EXPECT_TRUE(client->needs_begin_frames());
831 scheduler_->NotifyBeginMainFrameStarted();
832 scheduler_->NotifyReadyToCommit();
834 EXPECT_SCOPED(AdvanceFrame());
835 task_runner().RunPendingTasks(); // Run posted deadline.
836 EXPECT_EQ(2, client->num_draws());
838 EXPECT_FALSE(scheduler_->RedrawPending());
839 EXPECT_FALSE(scheduler_->CommitPending());
840 EXPECT_TRUE(client->needs_begin_frames());
842 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
843 // swap.
844 EXPECT_SCOPED(AdvanceFrame());
845 task_runner().RunPendingTasks(); // Run posted deadline.
846 EXPECT_EQ(2, client->num_draws());
847 EXPECT_FALSE(scheduler_->RedrawPending());
848 EXPECT_FALSE(scheduler_->CommitPending());
849 EXPECT_FALSE(client->needs_begin_frames());
852 // Tests that when a draw fails then the pending commit should not be dropped.
853 TEST_F(SchedulerTest, RequestCommitInsideFailedDraw) {
854 SchedulerClientThatsetNeedsDrawInsideDraw* client =
855 new SchedulerClientThatsetNeedsDrawInsideDraw;
856 scheduler_settings_.use_external_begin_frame_source = true;
857 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
859 client->SetDrawWillHappen(false);
861 scheduler_->SetNeedsRedraw();
862 EXPECT_TRUE(scheduler_->RedrawPending());
863 EXPECT_TRUE(client->needs_begin_frames());
864 EXPECT_EQ(0, client->num_draws());
866 // Fail the draw.
867 EXPECT_SCOPED(AdvanceFrame());
868 task_runner().RunPendingTasks(); // Run posted deadline.
869 EXPECT_EQ(1, client->num_draws());
871 // We have a commit pending and the draw failed, and we didn't lose the commit
872 // request.
873 EXPECT_TRUE(scheduler_->CommitPending());
874 EXPECT_TRUE(scheduler_->RedrawPending());
875 EXPECT_TRUE(client->needs_begin_frames());
877 // Fail the draw again.
878 EXPECT_SCOPED(AdvanceFrame());
880 task_runner().RunPendingTasks(); // Run posted deadline.
881 EXPECT_EQ(2, client->num_draws());
882 EXPECT_TRUE(scheduler_->CommitPending());
883 EXPECT_TRUE(scheduler_->RedrawPending());
884 EXPECT_TRUE(client->needs_begin_frames());
886 // Draw successfully.
887 client->SetDrawWillHappen(true);
888 EXPECT_SCOPED(AdvanceFrame());
889 task_runner().RunPendingTasks(); // Run posted deadline.
890 EXPECT_EQ(3, client->num_draws());
891 EXPECT_TRUE(scheduler_->CommitPending());
892 EXPECT_FALSE(scheduler_->RedrawPending());
893 EXPECT_TRUE(client->needs_begin_frames());
896 TEST_F(SchedulerTest, NoSwapWhenDrawFails) {
897 SchedulerClientThatSetNeedsCommitInsideDraw* client =
898 new SchedulerClientThatSetNeedsCommitInsideDraw;
899 scheduler_settings_.use_external_begin_frame_source = true;
900 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
902 scheduler_->SetNeedsRedraw();
903 EXPECT_TRUE(scheduler_->RedrawPending());
904 EXPECT_TRUE(client->needs_begin_frames());
905 EXPECT_EQ(0, client->num_draws());
907 // Draw successfully, this starts a new frame.
908 client->SetNeedsCommitOnNextDraw();
909 EXPECT_SCOPED(AdvanceFrame());
910 task_runner().RunPendingTasks(); // Run posted deadline.
911 EXPECT_EQ(1, client->num_draws());
913 scheduler_->SetNeedsRedraw();
914 EXPECT_TRUE(scheduler_->RedrawPending());
915 EXPECT_TRUE(client->needs_begin_frames());
917 // Fail to draw, this should not start a frame.
918 client->SetDrawWillHappen(false);
919 client->SetNeedsCommitOnNextDraw();
920 EXPECT_SCOPED(AdvanceFrame());
921 task_runner().RunPendingTasks(); // Run posted deadline.
922 EXPECT_EQ(2, client->num_draws());
925 class SchedulerClientNeedsPrepareTilesInDraw : public FakeSchedulerClient {
926 public:
927 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
928 scheduler_->SetNeedsPrepareTiles();
929 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
933 // Test prepare tiles is independant of draws.
934 TEST_F(SchedulerTest, PrepareTiles) {
935 SchedulerClientNeedsPrepareTilesInDraw* client =
936 new SchedulerClientNeedsPrepareTilesInDraw;
937 scheduler_settings_.use_external_begin_frame_source = true;
938 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
940 // Request both draw and prepare tiles. PrepareTiles shouldn't
941 // be trigged until BeginImplFrame.
942 client->Reset();
943 scheduler_->SetNeedsPrepareTiles();
944 scheduler_->SetNeedsRedraw();
945 EXPECT_TRUE(scheduler_->RedrawPending());
946 EXPECT_TRUE(scheduler_->PrepareTilesPending());
947 EXPECT_TRUE(client->needs_begin_frames());
948 EXPECT_EQ(0, client->num_draws());
949 EXPECT_FALSE(client->HasAction("ScheduledActionPrepareTiles"));
950 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
952 // We have no immediate actions to perform, so the BeginImplFrame should post
953 // the deadline task.
954 client->Reset();
955 EXPECT_SCOPED(AdvanceFrame());
956 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
957 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
958 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
960 // On the deadline, he actions should have occured in the right order.
961 client->Reset();
962 task_runner().RunPendingTasks(); // Run posted deadline.
963 EXPECT_EQ(1, client->num_draws());
964 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
965 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
966 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
967 client->ActionIndex("ScheduledActionPrepareTiles"));
968 EXPECT_FALSE(scheduler_->RedrawPending());
969 EXPECT_FALSE(scheduler_->PrepareTilesPending());
970 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
972 // Request a draw. We don't need a PrepareTiles yet.
973 client->Reset();
974 scheduler_->SetNeedsRedraw();
975 EXPECT_TRUE(scheduler_->RedrawPending());
976 EXPECT_FALSE(scheduler_->PrepareTilesPending());
977 EXPECT_TRUE(client->needs_begin_frames());
978 EXPECT_EQ(0, client->num_draws());
980 // We have no immediate actions to perform, so the BeginImplFrame should post
981 // the deadline task.
982 client->Reset();
983 EXPECT_SCOPED(AdvanceFrame());
984 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
985 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
986 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
988 // Draw. The draw will trigger SetNeedsPrepareTiles, and
989 // then the PrepareTiles action will be triggered after the Draw.
990 // Afterwards, neither a draw nor PrepareTiles are pending.
991 client->Reset();
992 task_runner().RunPendingTasks(); // Run posted deadline.
993 EXPECT_EQ(1, client->num_draws());
994 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
995 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
996 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
997 client->ActionIndex("ScheduledActionPrepareTiles"));
998 EXPECT_FALSE(scheduler_->RedrawPending());
999 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1000 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1002 // We need a BeginImplFrame where we don't swap to go idle.
1003 client->Reset();
1004 EXPECT_SCOPED(AdvanceFrame());
1005 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1006 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1007 client->Reset();
1008 task_runner().RunPendingTasks(); // Run posted deadline.
1009 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1010 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1011 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1012 EXPECT_EQ(0, client->num_draws());
1014 // Now trigger a PrepareTiles outside of a draw. We will then need
1015 // a begin-frame for the PrepareTiles, but we don't need a draw.
1016 client->Reset();
1017 EXPECT_FALSE(client->needs_begin_frames());
1018 scheduler_->SetNeedsPrepareTiles();
1019 EXPECT_TRUE(client->needs_begin_frames());
1020 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1021 EXPECT_FALSE(scheduler_->RedrawPending());
1023 // BeginImplFrame. There will be no draw, only PrepareTiles.
1024 client->Reset();
1025 EXPECT_SCOPED(AdvanceFrame());
1026 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1027 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1028 client->Reset();
1029 task_runner().RunPendingTasks(); // Run posted deadline.
1030 EXPECT_EQ(0, client->num_draws());
1031 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1032 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1033 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1036 // Test that PrepareTiles only happens once per frame. If an external caller
1037 // initiates it, then the state machine should not PrepareTiles on that frame.
1038 TEST_F(SchedulerTest, PrepareTilesOncePerFrame) {
1039 scheduler_settings_.use_external_begin_frame_source = true;
1040 SetUpScheduler(true);
1042 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
1043 // again.
1044 scheduler_->SetNeedsPrepareTiles();
1045 scheduler_->SetNeedsRedraw();
1046 client_->Reset();
1047 EXPECT_SCOPED(AdvanceFrame());
1048 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1049 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1050 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1052 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1053 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1054 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1056 client_->Reset();
1057 task_runner().RunPendingTasks(); // Run posted deadline.
1058 EXPECT_EQ(1, client_->num_draws());
1059 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1060 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1061 EXPECT_FALSE(scheduler_->RedrawPending());
1062 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1063 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1065 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1066 scheduler_->SetNeedsPrepareTiles();
1067 scheduler_->SetNeedsRedraw();
1068 client_->Reset();
1069 EXPECT_SCOPED(AdvanceFrame());
1070 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1071 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1072 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1074 client_->Reset();
1075 task_runner().RunPendingTasks(); // Run posted deadline.
1076 EXPECT_EQ(1, client_->num_draws());
1077 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1078 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1079 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1080 client_->ActionIndex("ScheduledActionPrepareTiles"));
1081 EXPECT_FALSE(scheduler_->RedrawPending());
1082 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1083 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1084 scheduler_->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1086 // If we get another DidPrepareTiles within the same frame, we should
1087 // not PrepareTiles on the next frame.
1088 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1089 scheduler_->SetNeedsPrepareTiles();
1090 scheduler_->SetNeedsRedraw();
1091 client_->Reset();
1092 EXPECT_SCOPED(AdvanceFrame());
1093 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1094 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1095 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1097 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1099 client_->Reset();
1100 task_runner().RunPendingTasks(); // Run posted deadline.
1101 EXPECT_EQ(1, client_->num_draws());
1102 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1103 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1104 EXPECT_FALSE(scheduler_->RedrawPending());
1105 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1107 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1108 // frame. This verifies we don't alternate calling PrepareTiles once and
1109 // twice.
1110 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1111 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1112 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1113 scheduler_->SetNeedsPrepareTiles();
1114 scheduler_->SetNeedsRedraw();
1115 client_->Reset();
1116 EXPECT_SCOPED(AdvanceFrame());
1117 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1118 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1119 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1121 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1123 client_->Reset();
1124 task_runner().RunPendingTasks(); // Run posted deadline.
1125 EXPECT_EQ(1, client_->num_draws());
1126 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1127 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1128 EXPECT_FALSE(scheduler_->RedrawPending());
1129 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1131 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1132 scheduler_->SetNeedsPrepareTiles();
1133 scheduler_->SetNeedsRedraw();
1134 client_->Reset();
1135 EXPECT_SCOPED(AdvanceFrame());
1136 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1137 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1138 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1140 client_->Reset();
1141 task_runner().RunPendingTasks(); // Run posted deadline.
1142 EXPECT_EQ(1, client_->num_draws());
1143 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1144 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1145 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1146 client_->ActionIndex("ScheduledActionPrepareTiles"));
1147 EXPECT_FALSE(scheduler_->RedrawPending());
1148 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1149 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1150 scheduler_->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1153 TEST_F(SchedulerTest, TriggerBeginFrameDeadlineEarly) {
1154 SchedulerClientNeedsPrepareTilesInDraw* client =
1155 new SchedulerClientNeedsPrepareTilesInDraw;
1156 scheduler_settings_.use_external_begin_frame_source = true;
1157 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1159 scheduler_->SetNeedsRedraw();
1160 EXPECT_SCOPED(AdvanceFrame());
1162 // The deadline should be zero since there is no work other than drawing
1163 // pending.
1164 EXPECT_EQ(base::TimeTicks(), client->posted_begin_impl_frame_deadline());
1167 class SchedulerClientWithFixedEstimates : public FakeSchedulerClient {
1168 public:
1169 SchedulerClientWithFixedEstimates(
1170 base::TimeDelta draw_duration,
1171 base::TimeDelta begin_main_frame_to_commit_duration,
1172 base::TimeDelta commit_to_activate_duration)
1173 : draw_duration_(draw_duration),
1174 begin_main_frame_to_commit_duration_(
1175 begin_main_frame_to_commit_duration),
1176 commit_to_activate_duration_(commit_to_activate_duration) {}
1178 base::TimeDelta DrawDurationEstimate() override { return draw_duration_; }
1179 base::TimeDelta BeginMainFrameToCommitDurationEstimate() override {
1180 return begin_main_frame_to_commit_duration_;
1182 base::TimeDelta CommitToActivateDurationEstimate() override {
1183 return commit_to_activate_duration_;
1186 private:
1187 base::TimeDelta draw_duration_;
1188 base::TimeDelta begin_main_frame_to_commit_duration_;
1189 base::TimeDelta commit_to_activate_duration_;
1192 void SchedulerTest::MainFrameInHighLatencyMode(
1193 int64 begin_main_frame_to_commit_estimate_in_ms,
1194 int64 commit_to_activate_estimate_in_ms,
1195 bool impl_latency_takes_priority,
1196 bool should_send_begin_main_frame) {
1197 // Set up client with specified estimates (draw duration is set to 1).
1198 SchedulerClientWithFixedEstimates* client =
1199 new SchedulerClientWithFixedEstimates(
1200 base::TimeDelta::FromMilliseconds(1),
1201 base::TimeDelta::FromMilliseconds(
1202 begin_main_frame_to_commit_estimate_in_ms),
1203 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms));
1205 scheduler_settings_.use_external_begin_frame_source = true;
1206 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1208 scheduler_->SetImplLatencyTakesPriority(impl_latency_takes_priority);
1210 // Impl thread hits deadline before commit finishes.
1211 scheduler_->SetNeedsCommit();
1212 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1213 EXPECT_SCOPED(AdvanceFrame());
1214 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1215 task_runner().RunPendingTasks(); // Run posted deadline.
1216 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1217 scheduler_->NotifyBeginMainFrameStarted();
1218 scheduler_->NotifyReadyToCommit();
1219 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1220 EXPECT_TRUE(client->HasAction("ScheduledActionSendBeginMainFrame"));
1222 client->Reset();
1223 scheduler_->SetNeedsCommit();
1224 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1225 EXPECT_SCOPED(AdvanceFrame());
1226 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1227 task_runner().RunPendingTasks(); // Run posted deadline.
1228 EXPECT_EQ(scheduler_->MainThreadIsInHighLatencyMode(),
1229 should_send_begin_main_frame);
1230 EXPECT_EQ(client->HasAction("ScheduledActionSendBeginMainFrame"),
1231 should_send_begin_main_frame);
1234 TEST_F(SchedulerTest,
1235 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) {
1236 // Set up client so that estimates indicate that we can commit and activate
1237 // before the deadline (~8ms by default).
1238 MainFrameInHighLatencyMode(1, 1, false, false);
1241 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) {
1242 // Set up client so that estimates indicate that the commit cannot finish
1243 // before the deadline (~8ms by default).
1244 MainFrameInHighLatencyMode(10, 1, false, true);
1247 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) {
1248 // Set up client so that estimates indicate that the activate cannot finish
1249 // before the deadline (~8ms by default).
1250 MainFrameInHighLatencyMode(1, 10, false, true);
1253 TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) {
1254 // Set up client so that estimates indicate that we can commit and activate
1255 // before the deadline (~8ms by default), but also enable impl latency takes
1256 // priority mode.
1257 MainFrameInHighLatencyMode(1, 1, true, true);
1260 TEST_F(SchedulerTest, PollForCommitCompletion) {
1261 // Since we are simulating a long commit, set up a client with draw duration
1262 // estimates that prevent skipping main frames to get to low latency mode.
1263 SchedulerClientWithFixedEstimates* client =
1264 new SchedulerClientWithFixedEstimates(
1265 base::TimeDelta::FromMilliseconds(1),
1266 base::TimeDelta::FromMilliseconds(32),
1267 base::TimeDelta::FromMilliseconds(32));
1268 scheduler_settings_.use_external_begin_frame_source = true;
1269 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1271 client->set_log_anticipated_draw_time_change(true);
1273 BeginFrameArgs frame_args =
1274 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
1275 frame_args.interval = base::TimeDelta::FromMilliseconds(1000);
1277 // At this point, we've drawn a frame. Start another commit, but hold off on
1278 // the NotifyReadyToCommit for now.
1279 EXPECT_FALSE(scheduler_->CommitPending());
1280 scheduler_->SetNeedsCommit();
1281 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args);
1282 EXPECT_TRUE(scheduler_->CommitPending());
1284 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1285 // blocking on the renderer.
1286 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1287 task_runner().RunPendingTasks(); // Run posted deadline.
1288 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1289 scheduler_->DidSwapBuffers();
1291 // Spin the event loop a few times and make sure we get more
1292 // DidAnticipateDrawTimeChange calls every time.
1293 int actions_so_far = client->num_actions_();
1295 // Does three iterations to make sure that the timer is properly repeating.
1296 for (int i = 0; i < 3; ++i) {
1297 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1298 task_runner().DelayToNextTaskTime().InMicroseconds())
1299 << scheduler_->AsValue()->ToString();
1300 task_runner().RunPendingTasks();
1301 EXPECT_GT(client->num_actions_(), actions_so_far);
1302 EXPECT_STREQ(client->Action(client->num_actions_() - 1),
1303 "DidAnticipatedDrawTimeChange");
1304 actions_so_far = client->num_actions_();
1307 // Do the same thing after BeginMainFrame starts but still before activation.
1308 scheduler_->NotifyBeginMainFrameStarted();
1309 for (int i = 0; i < 3; ++i) {
1310 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1311 task_runner().DelayToNextTaskTime().InMicroseconds())
1312 << scheduler_->AsValue()->ToString();
1313 task_runner().RunPendingTasks();
1314 EXPECT_GT(client->num_actions_(), actions_so_far);
1315 EXPECT_STREQ(client->Action(client->num_actions_() - 1),
1316 "DidAnticipatedDrawTimeChange");
1317 actions_so_far = client->num_actions_();
1321 TEST_F(SchedulerTest, BeginRetroFrame) {
1322 scheduler_settings_.use_external_begin_frame_source = true;
1323 SetUpScheduler(true);
1325 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1326 scheduler_->SetNeedsCommit();
1327 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1328 client_->Reset();
1330 // Create a BeginFrame with a long deadline to avoid race conditions.
1331 // This is the first BeginFrame, which will be handled immediately.
1332 BeginFrameArgs args =
1333 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
1334 args.deadline += base::TimeDelta::FromHours(1);
1335 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1336 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1337 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1338 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1339 EXPECT_TRUE(client_->needs_begin_frames());
1340 client_->Reset();
1342 // Queue BeginFrames while we are still handling the previous BeginFrame.
1343 args.frame_time += base::TimeDelta::FromSeconds(1);
1344 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1345 args.frame_time += base::TimeDelta::FromSeconds(1);
1346 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1348 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1349 task_runner().RunPendingTasks(); // Run posted deadline.
1350 EXPECT_NO_ACTION(client_);
1351 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1352 EXPECT_TRUE(client_->needs_begin_frames());
1353 client_->Reset();
1355 // NotifyReadyToCommit should trigger the commit.
1356 scheduler_->NotifyBeginMainFrameStarted();
1357 scheduler_->NotifyReadyToCommit();
1358 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1359 EXPECT_TRUE(client_->needs_begin_frames());
1360 client_->Reset();
1362 // BeginImplFrame should prepare the draw.
1363 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
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 // BeginImplFrame deadline should draw.
1371 task_runner().RunPendingTasks(); // Run posted deadline.
1372 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
1373 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1374 EXPECT_TRUE(client_->needs_begin_frames());
1375 client_->Reset();
1377 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1378 // to avoid excessive toggles.
1379 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1380 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
1381 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1382 client_->Reset();
1384 task_runner().RunPendingTasks(); // Run posted deadline.
1385 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1386 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1387 client_->Reset();
1390 TEST_F(SchedulerTest, BeginRetroFrame_SwapThrottled) {
1391 scheduler_settings_.use_external_begin_frame_source = true;
1392 SetUpScheduler(true);
1394 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1396 // To test swap ack throttling, this test disables automatic swap acks.
1397 scheduler_->SetMaxSwapsPending(1);
1398 client_->SetAutomaticSwapAck(false);
1400 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1401 client_->Reset();
1402 scheduler_->SetNeedsCommit();
1403 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1404 client_->Reset();
1406 EXPECT_SCOPED(AdvanceFrame());
1407 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1408 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1409 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1410 EXPECT_TRUE(client_->needs_begin_frames());
1411 client_->Reset();
1413 // Queue BeginFrame while we are still handling the previous BeginFrame.
1414 SendNextBeginFrame();
1415 EXPECT_NO_ACTION(client_);
1416 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1417 EXPECT_TRUE(client_->needs_begin_frames());
1418 client_->Reset();
1420 // NotifyReadyToCommit should trigger the pending commit and draw.
1421 scheduler_->NotifyBeginMainFrameStarted();
1422 scheduler_->NotifyReadyToCommit();
1423 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1424 EXPECT_TRUE(client_->needs_begin_frames());
1425 client_->Reset();
1427 // Swapping will put us into a swap throttled state.
1428 // Run posted deadline.
1429 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1430 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1431 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1432 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1433 EXPECT_TRUE(client_->needs_begin_frames());
1434 client_->Reset();
1436 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1437 // but not a BeginMainFrame or draw.
1438 scheduler_->SetNeedsCommit();
1439 scheduler_->SetNeedsRedraw();
1440 // Run posted BeginRetroFrame.
1441 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
1442 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1443 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1444 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1445 EXPECT_TRUE(client_->needs_begin_frames());
1446 client_->Reset();
1448 // Let time pass sufficiently beyond the regular deadline but not beyond the
1449 // late deadline.
1450 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1451 base::TimeDelta::FromMicroseconds(1));
1452 task_runner().RunUntilTime(now_src()->Now());
1453 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1455 // Take us out of a swap throttled state.
1456 scheduler_->DidSwapBuffersComplete();
1457 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
1458 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1459 EXPECT_TRUE(client_->needs_begin_frames());
1460 client_->Reset();
1462 // Verify that the deadline was rescheduled.
1463 task_runner().RunUntilTime(now_src()->Now());
1464 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
1465 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1466 EXPECT_TRUE(client_->needs_begin_frames());
1467 client_->Reset();
1470 TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooEarly) {
1471 scheduler_settings_.use_external_begin_frame_source = true;
1472 SetUpScheduler(true);
1474 scheduler_->SetNeedsCommit();
1475 EXPECT_TRUE(client_->needs_begin_frames());
1476 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1478 client_->Reset();
1479 EXPECT_SCOPED(AdvanceFrame());
1480 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1481 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1482 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1484 client_->Reset();
1485 scheduler_->NotifyBeginMainFrameStarted();
1487 client_->Reset();
1488 SendNextBeginFrame();
1489 // This BeginFrame is queued up as a retro frame.
1490 EXPECT_NO_ACTION(client_);
1491 // The previous deadline is still pending.
1492 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1494 client_->Reset();
1495 // This commit should schedule the (previous) deadline to trigger immediately.
1496 scheduler_->NotifyReadyToCommit();
1497 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1499 client_->Reset();
1500 // The deadline task should trigger causing a draw.
1501 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1502 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1503 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1504 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1506 // Keep animating.
1507 client_->Reset();
1508 scheduler_->SetNeedsAnimate();
1509 scheduler_->SetNeedsRedraw();
1510 EXPECT_NO_ACTION(client_);
1512 // Let's advance sufficiently past the next frame's deadline.
1513 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1514 BeginFrameArgs::DefaultEstimatedParentDrawTime() +
1515 base::TimeDelta::FromMicroseconds(1));
1517 // The retro frame hasn't expired yet.
1518 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
1519 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1520 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1521 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1523 // This is an immediate deadline case.
1524 client_->Reset();
1525 task_runner().RunPendingTasks();
1526 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1527 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
1530 TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooLate) {
1531 scheduler_settings_.use_external_begin_frame_source = true;
1532 SetUpScheduler(true);
1534 scheduler_->SetNeedsCommit();
1535 EXPECT_TRUE(client_->needs_begin_frames());
1536 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1538 client_->Reset();
1539 EXPECT_SCOPED(AdvanceFrame());
1540 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1541 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1542 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1544 client_->Reset();
1545 scheduler_->NotifyBeginMainFrameStarted();
1547 client_->Reset();
1548 SendNextBeginFrame();
1549 // This BeginFrame is queued up as a retro frame.
1550 EXPECT_NO_ACTION(client_);
1551 // The previous deadline is still pending.
1552 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1554 client_->Reset();
1555 // This commit should schedule the (previous) deadline to trigger immediately.
1556 scheduler_->NotifyReadyToCommit();
1557 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1559 client_->Reset();
1560 // The deadline task should trigger causing a draw.
1561 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1562 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1563 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1564 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1566 // Keep animating.
1567 client_->Reset();
1568 scheduler_->SetNeedsAnimate();
1569 scheduler_->SetNeedsRedraw();
1570 EXPECT_NO_ACTION(client_);
1572 // Let's advance sufficiently past the next frame's deadline.
1573 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() +
1574 base::TimeDelta::FromMicroseconds(1));
1576 // The retro frame should've expired.
1577 EXPECT_NO_ACTION(client_);
1580 void SchedulerTest::BeginFramesNotFromClient(
1581 bool use_external_begin_frame_source,
1582 bool throttle_frame_production) {
1583 scheduler_settings_.use_external_begin_frame_source =
1584 use_external_begin_frame_source;
1585 scheduler_settings_.throttle_frame_production = throttle_frame_production;
1586 SetUpScheduler(true);
1588 // SetNeedsCommit should begin the frame on the next BeginImplFrame
1589 // without calling SetNeedsBeginFrame.
1590 scheduler_->SetNeedsCommit();
1591 EXPECT_NO_ACTION(client_);
1592 client_->Reset();
1594 // When the client-driven BeginFrame are disabled, the scheduler posts it's
1595 // own BeginFrame tasks.
1596 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1597 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1598 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1599 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1600 client_->Reset();
1602 // If we don't swap on the deadline, we wait for the next BeginFrame.
1603 task_runner().RunPendingTasks(); // Run posted deadline.
1604 EXPECT_NO_ACTION(client_);
1605 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1606 client_->Reset();
1608 // NotifyReadyToCommit should trigger the commit.
1609 scheduler_->NotifyBeginMainFrameStarted();
1610 scheduler_->NotifyReadyToCommit();
1611 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1612 client_->Reset();
1614 // BeginImplFrame should prepare the draw.
1615 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1616 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1617 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1618 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1619 client_->Reset();
1621 // BeginImplFrame deadline should draw.
1622 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1623 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
1624 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1625 client_->Reset();
1627 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1628 // to avoid excessive toggles.
1629 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1630 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
1631 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1632 client_->Reset();
1634 // Make sure SetNeedsBeginFrame isn't called on the client
1635 // when the BeginFrame is no longer needed.
1636 task_runner().RunPendingTasks(); // Run posted deadline.
1637 EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_);
1638 client_->Reset();
1641 TEST_F(SchedulerTest, SyntheticBeginFrames) {
1642 bool use_external_begin_frame_source = false;
1643 bool throttle_frame_production = true;
1644 BeginFramesNotFromClient(use_external_begin_frame_source,
1645 throttle_frame_production);
1648 TEST_F(SchedulerTest, VSyncThrottlingDisabled) {
1649 bool use_external_begin_frame_source = true;
1650 bool throttle_frame_production = false;
1651 BeginFramesNotFromClient(use_external_begin_frame_source,
1652 throttle_frame_production);
1655 TEST_F(SchedulerTest, SyntheticBeginFrames_And_VSyncThrottlingDisabled) {
1656 bool use_external_begin_frame_source = false;
1657 bool throttle_frame_production = false;
1658 BeginFramesNotFromClient(use_external_begin_frame_source,
1659 throttle_frame_production);
1662 void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
1663 bool use_external_begin_frame_source,
1664 bool throttle_frame_production) {
1665 scheduler_settings_.use_external_begin_frame_source =
1666 use_external_begin_frame_source;
1667 scheduler_settings_.throttle_frame_production = throttle_frame_production;
1668 SetUpScheduler(true);
1670 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1672 // To test swap ack throttling, this test disables automatic swap acks.
1673 scheduler_->SetMaxSwapsPending(1);
1674 client_->SetAutomaticSwapAck(false);
1676 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1677 client_->Reset();
1678 scheduler_->SetNeedsCommit();
1679 EXPECT_NO_ACTION(client_);
1680 client_->Reset();
1682 // Trigger the first BeginImplFrame and BeginMainFrame
1683 EXPECT_SCOPED(AdvanceFrame());
1684 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1685 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1686 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1687 client_->Reset();
1689 // NotifyReadyToCommit should trigger the pending commit and draw.
1690 scheduler_->NotifyBeginMainFrameStarted();
1691 scheduler_->NotifyReadyToCommit();
1692 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1693 client_->Reset();
1695 // Swapping will put us into a swap throttled state.
1696 // Run posted deadline.
1697 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1698 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1699 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1700 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1701 client_->Reset();
1703 // While swap throttled, BeginFrames should trigger BeginImplFrames,
1704 // but not a BeginMainFrame or draw.
1705 scheduler_->SetNeedsCommit();
1706 scheduler_->SetNeedsRedraw();
1707 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
1708 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1709 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1710 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1711 client_->Reset();
1713 // Let time pass sufficiently beyond the regular deadline but not beyond the
1714 // late deadline.
1715 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1716 base::TimeDelta::FromMicroseconds(1));
1717 task_runner().RunUntilTime(now_src()->Now());
1718 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1720 // Take us out of a swap throttled state.
1721 scheduler_->DidSwapBuffersComplete();
1722 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
1723 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1724 client_->Reset();
1726 // Verify that the deadline was rescheduled.
1727 // We can't use RunUntilTime(now) here because the next frame is also
1728 // scheduled if throttle_frame_production = false.
1729 base::TimeTicks before_deadline = now_src()->Now();
1730 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1731 base::TimeTicks after_deadline = now_src()->Now();
1732 EXPECT_EQ(after_deadline, before_deadline);
1733 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1734 client_->Reset();
1737 TEST_F(SchedulerTest, SyntheticBeginFrames_SwapThrottled) {
1738 bool use_external_begin_frame_source = false;
1739 bool throttle_frame_production = true;
1740 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
1741 throttle_frame_production);
1744 TEST_F(SchedulerTest, VSyncThrottlingDisabled_SwapThrottled) {
1745 bool use_external_begin_frame_source = true;
1746 bool throttle_frame_production = false;
1747 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
1748 throttle_frame_production);
1751 TEST_F(SchedulerTest,
1752 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled) {
1753 bool use_external_begin_frame_source = false;
1754 bool throttle_frame_production = false;
1755 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
1756 throttle_frame_production);
1759 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized) {
1760 scheduler_settings_.use_external_begin_frame_source = true;
1761 SetUpScheduler(false);
1763 scheduler_->SetCanStart();
1764 scheduler_->SetVisible(true);
1765 scheduler_->SetCanDraw(true);
1767 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
1768 client_->Reset();
1769 scheduler_->DidCreateAndInitializeOutputSurface();
1770 EXPECT_NO_ACTION(client_);
1772 scheduler_->DidLoseOutputSurface();
1773 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
1776 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) {
1777 scheduler_settings_.use_external_begin_frame_source = true;
1778 SetUpScheduler(true);
1780 // SetNeedsCommit should begin the frame.
1781 scheduler_->SetNeedsCommit();
1782 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1784 client_->Reset();
1785 EXPECT_SCOPED(AdvanceFrame());
1786 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1787 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1788 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1790 client_->Reset();
1791 scheduler_->DidLoseOutputSurface();
1792 // Do nothing when impl frame is in deadine pending state.
1793 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1794 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1796 client_->Reset();
1797 scheduler_->NotifyBeginMainFrameStarted();
1798 scheduler_->NotifyReadyToCommit();
1799 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 1);
1801 client_->Reset();
1802 task_runner().RunPendingTasks(); // Run posted deadline.
1803 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
1806 void SchedulerTest::DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
1807 bool impl_side_painting) {
1808 scheduler_settings_.impl_side_painting = impl_side_painting;
1809 scheduler_settings_.use_external_begin_frame_source = true;
1810 SetUpScheduler(true);
1812 // SetNeedsCommit should begin the frame.
1813 scheduler_->SetNeedsCommit();
1814 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1816 client_->Reset();
1817 EXPECT_SCOPED(AdvanceFrame());
1818 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1819 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1820 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1822 client_->Reset();
1823 scheduler_->DidLoseOutputSurface();
1824 // Do nothing when impl frame is in deadine pending state.
1825 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1826 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1828 client_->Reset();
1829 // Run posted deadline.
1830 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1831 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1832 // OnBeginImplFrameDeadline didn't schedule any actions because main frame is
1833 // not yet completed.
1834 EXPECT_NO_ACTION(client_);
1835 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1837 // BeginImplFrame is not started.
1838 task_runner().RunUntilTime(now_src()->Now() +
1839 base::TimeDelta::FromMilliseconds(10));
1840 EXPECT_NO_ACTION(client_);
1841 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1843 client_->Reset();
1844 scheduler_->NotifyBeginMainFrameStarted();
1845 scheduler_->NotifyReadyToCommit();
1846 if (impl_side_painting) {
1847 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 3);
1848 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 3);
1849 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 2, 3);
1850 } else {
1851 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2);
1852 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 2);
1856 TEST_F(SchedulerTest,
1857 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) {
1858 bool impl_side_painting = false;
1859 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
1862 TEST_F(SchedulerTest,
1863 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint) {
1864 bool impl_side_painting = true;
1865 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
1868 void SchedulerTest::DidLoseOutputSurfaceAfterReadyToCommit(
1869 bool impl_side_painting) {
1870 scheduler_settings_.impl_side_painting = impl_side_painting;
1871 scheduler_settings_.use_external_begin_frame_source = true;
1872 SetUpScheduler(true);
1874 // SetNeedsCommit should begin the frame.
1875 scheduler_->SetNeedsCommit();
1876 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1878 client_->Reset();
1879 EXPECT_SCOPED(AdvanceFrame());
1880 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1881 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1882 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1884 client_->Reset();
1885 scheduler_->NotifyBeginMainFrameStarted();
1886 scheduler_->NotifyReadyToCommit();
1887 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1889 client_->Reset();
1890 scheduler_->DidLoseOutputSurface();
1891 if (impl_side_painting) {
1892 // Sync tree should be forced to activate.
1893 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 3);
1894 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
1895 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
1896 } else {
1897 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1898 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1901 client_->Reset();
1902 task_runner().RunPendingTasks(); // Run posted deadline.
1903 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
1906 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) {
1907 DidLoseOutputSurfaceAfterReadyToCommit(false);
1910 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting) {
1911 DidLoseOutputSurfaceAfterReadyToCommit(true);
1914 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles) {
1915 scheduler_settings_.use_external_begin_frame_source = true;
1916 SetUpScheduler(true);
1918 scheduler_->SetNeedsPrepareTiles();
1919 scheduler_->SetNeedsRedraw();
1920 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1922 client_->Reset();
1923 EXPECT_SCOPED(AdvanceFrame());
1924 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1925 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1926 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1928 client_->Reset();
1929 scheduler_->DidLoseOutputSurface();
1930 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1931 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1933 client_->Reset();
1934 task_runner().RunPendingTasks(); // Run posted deadline.
1935 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 0, 2);
1936 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 2);
1939 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) {
1940 scheduler_settings_.use_external_begin_frame_source = true;
1941 SetUpScheduler(true);
1943 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1944 scheduler_->SetNeedsCommit();
1945 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1947 // Create a BeginFrame with a long deadline to avoid race conditions.
1948 // This is the first BeginFrame, which will be handled immediately.
1949 client_->Reset();
1950 BeginFrameArgs args =
1951 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
1952 args.deadline += base::TimeDelta::FromHours(1);
1953 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1954 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1955 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1956 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1957 EXPECT_TRUE(client_->needs_begin_frames());
1959 // Queue BeginFrames while we are still handling the previous BeginFrame.
1960 args.frame_time += base::TimeDelta::FromSeconds(1);
1961 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1962 args.frame_time += base::TimeDelta::FromSeconds(1);
1963 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1965 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1966 client_->Reset();
1967 task_runner().RunPendingTasks(); // Run posted deadline.
1968 EXPECT_NO_ACTION(client_);
1969 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1970 EXPECT_TRUE(client_->needs_begin_frames());
1972 // NotifyReadyToCommit should trigger the commit.
1973 client_->Reset();
1974 scheduler_->NotifyBeginMainFrameStarted();
1975 scheduler_->NotifyReadyToCommit();
1976 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1977 EXPECT_TRUE(client_->needs_begin_frames());
1979 client_->Reset();
1980 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty());
1981 scheduler_->DidLoseOutputSurface();
1982 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
1983 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
1984 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
1985 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty());
1987 // Posted BeginRetroFrame is aborted.
1988 client_->Reset();
1989 task_runner().RunPendingTasks();
1990 EXPECT_NO_ACTION(client_);
1993 TEST_F(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) {
1994 scheduler_settings_.use_external_begin_frame_source = true;
1995 SetUpScheduler(true);
1997 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1998 scheduler_->SetNeedsCommit();
1999 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2001 // Create a BeginFrame with a long deadline to avoid race conditions.
2002 // This is the first BeginFrame, which will be handled immediately.
2003 client_->Reset();
2004 BeginFrameArgs args =
2005 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2006 args.deadline += base::TimeDelta::FromHours(1);
2007 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2008 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2009 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2010 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2011 EXPECT_TRUE(client_->needs_begin_frames());
2013 // Queue BeginFrames while we are still handling the previous BeginFrame.
2014 args.frame_time += base::TimeDelta::FromSeconds(1);
2015 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2016 args.frame_time += base::TimeDelta::FromSeconds(1);
2017 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2019 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2020 client_->Reset();
2021 task_runner().RunPendingTasks(); // Run posted deadline.
2022 EXPECT_NO_ACTION(client_);
2023 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2024 EXPECT_TRUE(client_->needs_begin_frames());
2026 // NotifyReadyToCommit should trigger the commit.
2027 client_->Reset();
2028 scheduler_->NotifyBeginMainFrameStarted();
2029 scheduler_->NotifyReadyToCommit();
2030 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2031 EXPECT_TRUE(client_->needs_begin_frames());
2033 // BeginImplFrame should prepare the draw.
2034 client_->Reset();
2035 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2036 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2037 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2038 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2039 EXPECT_TRUE(client_->needs_begin_frames());
2041 client_->Reset();
2042 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty());
2043 scheduler_->DidLoseOutputSurface();
2044 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
2045 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2046 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty());
2048 // BeginImplFrame deadline should abort drawing.
2049 client_->Reset();
2050 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 task_runner().RunPendingTasks();
2058 EXPECT_NO_ACTION(client_);
2061 TEST_F(SchedulerTest,
2062 StopBeginFrameAfterDidLoseOutputSurfaceWithSyntheticBeginFrameSource) {
2063 SetUpScheduler(true);
2065 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2066 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2067 scheduler_->SetNeedsCommit();
2068 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2070 client_->Reset();
2071 task_runner().RunPendingTasks(); // Run posted Tick.
2072 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2073 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2074 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2075 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2077 // NotifyReadyToCommit should trigger the commit.
2078 client_->Reset();
2079 scheduler_->NotifyBeginMainFrameStarted();
2080 scheduler_->NotifyReadyToCommit();
2081 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2082 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2084 client_->Reset();
2085 scheduler_->DidLoseOutputSurface();
2086 EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_);
2087 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2089 client_->Reset();
2090 task_runner().RunPendingTasks(); // Run posted deadline.
2091 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
2092 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2095 TEST_F(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) {
2096 scheduler_settings_.impl_side_painting = true;
2097 scheduler_settings_.use_external_begin_frame_source = true;
2098 SetUpScheduler(true);
2100 // SetNeedsCommit should begin the frame.
2101 scheduler_->SetNeedsCommit();
2102 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2104 client_->Reset();
2105 EXPECT_SCOPED(AdvanceFrame());
2106 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2107 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2108 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2110 client_->Reset();
2111 scheduler_->NotifyBeginMainFrameStarted();
2112 scheduler_->NotifyReadyToCommit();
2113 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2115 client_->Reset();
2116 scheduler_->SetVisible(false);
2117 // Sync tree should be forced to activate.
2118 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
2119 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2);
2122 TEST_F(SchedulerTest, SchedulerPowerMonitoring) {
2123 scheduler_settings_.disable_hi_res_timer_tasks_on_battery = true;
2124 SetUpScheduler(true);
2126 base::TimeTicks before_deadline, after_deadline;
2128 scheduler_->SetNeedsCommit();
2129 scheduler_->SetNeedsRedraw();
2130 client_->Reset();
2132 // On non-battery power
2133 EXPECT_FALSE(PowerMonitor()->IsOnBatteryPower());
2135 EXPECT_SCOPED(AdvanceFrame());
2136 client_->Reset();
2138 before_deadline = now_src()->Now();
2139 EXPECT_TRUE(
2140 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)));
2141 after_deadline = now_src()->Now();
2143 // We post a non-zero deadline task when not on battery
2144 EXPECT_LT(before_deadline, after_deadline);
2146 // Switch to battery power
2147 PowerMonitorSource()->GeneratePowerStateEvent(true);
2148 EXPECT_TRUE(PowerMonitor()->IsOnBatteryPower());
2150 EXPECT_SCOPED(AdvanceFrame());
2151 scheduler_->SetNeedsCommit();
2152 scheduler_->SetNeedsRedraw();
2153 client_->Reset();
2155 before_deadline = now_src()->Now();
2156 EXPECT_TRUE(
2157 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)));
2158 after_deadline = now_src()->Now();
2160 // We post a zero deadline task when on battery
2161 EXPECT_EQ(before_deadline, after_deadline);
2163 // Switch to non-battery power
2164 PowerMonitorSource()->GeneratePowerStateEvent(false);
2165 EXPECT_FALSE(PowerMonitor()->IsOnBatteryPower());
2167 EXPECT_SCOPED(AdvanceFrame());
2168 scheduler_->SetNeedsCommit();
2169 scheduler_->SetNeedsRedraw();
2170 client_->Reset();
2172 // Same as before
2173 before_deadline = now_src()->Now();
2174 EXPECT_TRUE(
2175 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)));
2176 after_deadline = now_src()->Now();
2179 TEST_F(SchedulerTest,
2180 SimulateWindowsLowResolutionTimerOnBattery_PrioritizeImplLatencyOff) {
2181 scheduler_settings_.use_external_begin_frame_source = true;
2182 SetUpScheduler(true);
2184 // Set needs commit so that the scheduler tries to wait for the main thread
2185 scheduler_->SetNeedsCommit();
2186 // Set needs redraw so that the scheduler doesn't wait too long
2187 scheduler_->SetNeedsRedraw();
2188 client_->Reset();
2190 // Switch to battery power
2191 PowerMonitorSource()->GeneratePowerStateEvent(true);
2192 EXPECT_TRUE(PowerMonitor()->IsOnBatteryPower());
2194 EXPECT_SCOPED(AdvanceFrame());
2195 scheduler_->SetNeedsCommit();
2196 scheduler_->SetNeedsRedraw();
2197 client_->Reset();
2199 // Disable auto-advancing of now_src
2200 task_runner().SetAutoAdvanceNowToPendingTasks(false);
2202 // Deadline task is pending
2203 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2204 task_runner().RunPendingTasks();
2205 // Deadline task is still pending
2206 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2208 // Advance now by 15 ms - same as windows low res timer
2209 now_src()->AdvanceNowMicroseconds(15000);
2210 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2211 task_runner().RunPendingTasks();
2212 // Deadline task finally completes
2213 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2216 TEST_F(SchedulerTest,
2217 SimulateWindowsLowResolutionTimerOnBattery_PrioritizeImplLatencyOn) {
2218 scheduler_settings_.disable_hi_res_timer_tasks_on_battery = true;
2219 scheduler_settings_.use_external_begin_frame_source = true;
2220 SetUpScheduler(true);
2222 // Set needs commit so that the scheduler tries to wait for the main thread
2223 scheduler_->SetNeedsCommit();
2224 // Set needs redraw so that the scheduler doesn't wait too long
2225 scheduler_->SetNeedsRedraw();
2226 client_->Reset();
2228 // Switch to battery power
2229 PowerMonitorSource()->GeneratePowerStateEvent(true);
2230 EXPECT_TRUE(PowerMonitor()->IsOnBatteryPower());
2232 EXPECT_SCOPED(AdvanceFrame());
2233 scheduler_->SetNeedsCommit();
2234 scheduler_->SetNeedsRedraw();
2235 client_->Reset();
2237 // Disable auto-advancing of now_src
2238 task_runner().SetAutoAdvanceNowToPendingTasks(false);
2240 // Deadline task is pending
2241 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2242 task_runner().RunPendingTasks();
2243 // Deadline task runs immediately
2244 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2247 // Tests to ensure frame sources can be successfully changed while drawing.
2248 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottled) {
2249 scheduler_settings_.use_external_begin_frame_source = true;
2250 SetUpScheduler(true);
2252 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2253 scheduler_->SetNeedsRedraw();
2254 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2255 client_->Reset();
2257 EXPECT_SCOPED(AdvanceFrame());
2258 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2259 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2260 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2261 EXPECT_TRUE(client_->needs_begin_frames());
2262 client_->Reset();
2263 task_runner().RunPendingTasks(); // Run posted deadline.
2264 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2265 scheduler_->SetNeedsRedraw();
2267 // Switch to an unthrottled frame source.
2268 scheduler_->SetThrottleFrameProduction(false);
2269 client_->Reset();
2271 // Unthrottled frame source will immediately begin a new frame.
2272 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2273 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2274 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2275 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2276 client_->Reset();
2278 // If we don't swap on the deadline, we wait for the next BeginFrame.
2279 task_runner().RunPendingTasks(); // Run posted deadline.
2280 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2281 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2282 client_->Reset();
2285 // Tests to ensure frame sources can be successfully changed while a frame
2286 // deadline is pending.
2287 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottledBeforeDeadline) {
2288 scheduler_settings_.use_external_begin_frame_source = true;
2289 SetUpScheduler(true);
2291 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2292 scheduler_->SetNeedsRedraw();
2293 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2294 client_->Reset();
2296 EXPECT_SCOPED(AdvanceFrame());
2297 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2298 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2300 // Switch to an unthrottled frame source before the frame deadline is hit.
2301 scheduler_->SetThrottleFrameProduction(false);
2302 client_->Reset();
2304 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2305 EXPECT_TRUE(client_->needs_begin_frames());
2306 client_->Reset();
2308 task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame.
2309 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
2310 // Unthrottled frame source will immediately begin a new frame.
2311 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 2);
2312 scheduler_->SetNeedsRedraw();
2313 client_->Reset();
2315 task_runner().RunPendingTasks(); // Run posted deadline.
2316 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2317 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2318 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2319 client_->Reset();
2322 // Tests to ensure that the active frame source can successfully be changed from
2323 // unthrottled to throttled.
2324 TEST_F(SchedulerTest, SwitchFrameSourceToThrottled) {
2325 scheduler_settings_.throttle_frame_production = false;
2326 scheduler_settings_.use_external_begin_frame_source = true;
2327 SetUpScheduler(true);
2329 scheduler_->SetNeedsRedraw();
2330 EXPECT_NO_ACTION(client_);
2331 client_->Reset();
2333 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2334 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2335 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2336 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2337 client_->Reset();
2339 task_runner().RunPendingTasks(); // Run posted deadline.
2340 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2341 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2342 client_->Reset();
2344 // Switch to a throttled frame source.
2345 scheduler_->SetThrottleFrameProduction(true);
2346 client_->Reset();
2348 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2349 scheduler_->SetNeedsRedraw();
2350 task_runner().RunPendingTasks();
2351 EXPECT_NO_ACTION(client_);
2352 client_->Reset();
2354 EXPECT_SCOPED(AdvanceFrame());
2355 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2356 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2357 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2358 EXPECT_TRUE(client_->needs_begin_frames());
2359 client_->Reset();
2360 task_runner().RunPendingTasks(); // Run posted deadline.
2361 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2364 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
2365 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon) {
2366 scheduler_settings_.use_external_begin_frame_source = true;
2367 SetUpScheduler(true);
2369 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2370 scheduler_->SetNeedsCommit();
2371 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2372 client_->Reset();
2374 // Trigger a frame draw.
2375 EXPECT_SCOPED(AdvanceFrame());
2376 scheduler_->NotifyBeginMainFrameStarted();
2377 scheduler_->NotifyReadyToCommit();
2378 task_runner().RunPendingTasks();
2379 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 5);
2380 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 5);
2381 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 5);
2382 EXPECT_ACTION("ScheduledActionAnimate", client_, 3, 5);
2383 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 5);
2384 client_->Reset();
2386 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2387 // and send a SendBeginMainFrameNotExpectedSoon.
2388 EXPECT_SCOPED(AdvanceFrame());
2389 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
2390 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2391 client_->Reset();
2393 task_runner().RunPendingTasks(); // Run posted deadline.
2394 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
2395 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2396 client_->Reset();
2399 } // namespace
2400 } // namespace cc