Fix search results being clipped in app list.
[chromium-blink-merge.git] / cc / scheduler / scheduler_unittest.cc
blob193893bb6ce1f7dfe45f3610581186425923273d
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/run_loop.h"
14 #include "base/time/time.h"
15 #include "base/trace_event/trace_event.h"
16 #include "cc/test/begin_frame_args_test.h"
17 #include "cc/test/ordered_simple_task_runner.h"
18 #include "cc/test/scheduler_test_common.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
23 do { \
24 EXPECT_EQ(expected_num_actions, client->num_actions_()); \
25 if (action_index >= 0) { \
26 ASSERT_LT(action_index, client->num_actions_()) << scheduler_.get(); \
27 EXPECT_STREQ(action, client->Action(action_index)); \
28 } \
29 for (int i = expected_num_actions; i < client->num_actions_(); ++i) \
30 ADD_FAILURE() << "Unexpected action: " << client->Action(i) \
31 << " with state:\n" << client->StateForAction(i); \
32 } while (false)
34 #define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0)
36 #define EXPECT_SINGLE_ACTION(action, client) \
37 EXPECT_ACTION(action, client, 0, 1)
39 #define EXPECT_SCOPED(statements) \
40 { \
41 SCOPED_TRACE(""); \
42 statements; \
45 namespace cc {
46 namespace {
48 class FakeSchedulerClient : public SchedulerClient {
49 public:
50 FakeSchedulerClient()
51 : automatic_swap_ack_(true),
52 begin_frame_is_sent_to_children_(false),
53 scheduler_(nullptr) {
54 Reset();
57 void Reset() {
58 actions_.clear();
59 states_.clear();
60 draw_will_happen_ = true;
61 swap_will_happen_if_draw_happens_ = true;
62 num_draws_ = 0;
63 log_anticipated_draw_time_change_ = false;
64 begin_frame_is_sent_to_children_ = false;
67 void set_scheduler(TestScheduler* scheduler) { scheduler_ = scheduler; }
69 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
70 // for tests that do.
71 void set_log_anticipated_draw_time_change(bool log) {
72 log_anticipated_draw_time_change_ = log;
74 bool needs_begin_frames() {
75 return scheduler_->frame_source().NeedsBeginFrames();
77 int num_draws() const { return num_draws_; }
78 int num_actions_() const { return static_cast<int>(actions_.size()); }
79 const char* Action(int i) const { return actions_[i]; }
80 std::string StateForAction(int i) const { return states_[i]->ToString(); }
81 base::TimeTicks posted_begin_impl_frame_deadline() const {
82 return posted_begin_impl_frame_deadline_;
85 int ActionIndex(const char* action) const {
86 for (size_t i = 0; i < actions_.size(); i++)
87 if (!strcmp(actions_[i], action))
88 return i;
89 return -1;
92 bool HasAction(const char* action) const {
93 return ActionIndex(action) >= 0;
96 void SetDrawWillHappen(bool draw_will_happen) {
97 draw_will_happen_ = draw_will_happen;
99 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
100 swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
102 void SetAutomaticSwapAck(bool automatic_swap_ack) {
103 automatic_swap_ack_ = automatic_swap_ack;
105 // SchedulerClient implementation.
106 void WillBeginImplFrame(const BeginFrameArgs& args) override {
107 PushAction("WillBeginImplFrame");
109 void ScheduledActionSendBeginMainFrame() override {
110 PushAction("ScheduledActionSendBeginMainFrame");
112 void ScheduledActionAnimate() override {
113 PushAction("ScheduledActionAnimate");
115 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
116 PushAction("ScheduledActionDrawAndSwapIfPossible");
117 num_draws_++;
118 DrawResult result =
119 draw_will_happen_ ? DRAW_SUCCESS : DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
120 bool swap_will_happen =
121 draw_will_happen_ && swap_will_happen_if_draw_happens_;
122 if (swap_will_happen) {
123 scheduler_->DidSwapBuffers();
125 if (automatic_swap_ack_)
126 scheduler_->DidSwapBuffersComplete();
128 return result;
130 DrawResult ScheduledActionDrawAndSwapForced() override {
131 PushAction("ScheduledActionDrawAndSwapForced");
132 return DRAW_SUCCESS;
134 void ScheduledActionCommit() override { PushAction("ScheduledActionCommit"); }
135 void ScheduledActionActivateSyncTree() override {
136 PushAction("ScheduledActionActivateSyncTree");
138 void ScheduledActionBeginOutputSurfaceCreation() override {
139 PushAction("ScheduledActionBeginOutputSurfaceCreation");
141 void ScheduledActionPrepareTiles() override {
142 PushAction("ScheduledActionPrepareTiles");
144 void ScheduledActionInvalidateOutputSurface() override {
145 actions_.push_back("ScheduledActionInvalidateOutputSurface");
146 states_.push_back(scheduler_->AsValue());
148 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {
149 if (log_anticipated_draw_time_change_)
150 PushAction("DidAnticipatedDrawTimeChange");
152 base::TimeDelta DrawDurationEstimate() override { return base::TimeDelta(); }
153 base::TimeDelta BeginMainFrameToCommitDurationEstimate() override {
154 return base::TimeDelta();
156 base::TimeDelta CommitToActivateDurationEstimate() override {
157 return base::TimeDelta();
160 void DidBeginImplFrameDeadline() override {}
162 void SendBeginFramesToChildren(const BeginFrameArgs& args) override {
163 begin_frame_is_sent_to_children_ = true;
166 void SendBeginMainFrameNotExpectedSoon() override {
167 PushAction("SendBeginMainFrameNotExpectedSoon");
170 base::Callback<bool(void)> ImplFrameDeadlinePending(bool state) {
171 return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback,
172 base::Unretained(this),
173 state);
176 bool begin_frame_is_sent_to_children() const {
177 return begin_frame_is_sent_to_children_;
180 void PushAction(const char* description) {
181 actions_.push_back(description);
182 states_.push_back(scheduler_->AsValue());
185 protected:
186 bool ImplFrameDeadlinePendingCallback(bool state) {
187 return scheduler_->BeginImplFrameDeadlinePending() == state;
190 bool draw_will_happen_;
191 bool swap_will_happen_if_draw_happens_;
192 bool automatic_swap_ack_;
193 int num_draws_;
194 bool log_anticipated_draw_time_change_;
195 bool begin_frame_is_sent_to_children_;
196 base::TimeTicks posted_begin_impl_frame_deadline_;
197 std::vector<const char*> actions_;
198 std::vector<scoped_refptr<base::trace_event::ConvertableToTraceFormat>>
199 states_;
200 TestScheduler* scheduler_;
203 class FakeExternalBeginFrameSource : public BeginFrameSourceMixIn {
204 public:
205 explicit FakeExternalBeginFrameSource(FakeSchedulerClient* client)
206 : client_(client) {}
207 ~FakeExternalBeginFrameSource() override {}
209 void OnNeedsBeginFramesChange(bool needs_begin_frames) override {
210 if (needs_begin_frames) {
211 client_->PushAction("SetNeedsBeginFrames(true)");
212 } else {
213 client_->PushAction("SetNeedsBeginFrames(false)");
217 void TestOnBeginFrame(const BeginFrameArgs& args) {
218 return CallOnBeginFrame(args);
221 private:
222 FakeSchedulerClient* client_;
225 class SchedulerTest : public testing::Test {
226 public:
227 SchedulerTest()
228 : now_src_(TestNowSource::Create()),
229 task_runner_(new OrderedSimpleTaskRunner(now_src_, true)),
230 fake_external_begin_frame_source_(nullptr) {
231 // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval()
232 now_src_->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
233 // Fail if we need to run 100 tasks in a row.
234 task_runner_->SetRunTaskLimit(100);
237 ~SchedulerTest() override {}
239 protected:
240 TestScheduler* CreateScheduler() {
241 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source;
242 if (scheduler_settings_.use_external_begin_frame_source) {
243 fake_external_begin_frame_source.reset(
244 new FakeExternalBeginFrameSource(client_.get()));
245 fake_external_begin_frame_source_ =
246 fake_external_begin_frame_source.get();
248 scheduler_ = TestScheduler::Create(now_src_, client_.get(),
249 scheduler_settings_, 0, task_runner_,
250 fake_external_begin_frame_source.Pass());
251 DCHECK(scheduler_);
252 client_->set_scheduler(scheduler_.get());
253 return scheduler_.get();
256 void CreateSchedulerAndInitSurface() {
257 CreateScheduler();
258 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit());
261 void SetUpScheduler(bool initSurface) {
262 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient), initSurface);
265 void SetUpScheduler(scoped_ptr<FakeSchedulerClient> client,
266 bool initSurface) {
267 client_ = client.Pass();
268 if (initSurface)
269 CreateSchedulerAndInitSurface();
270 else
271 CreateScheduler();
274 OrderedSimpleTaskRunner& task_runner() { return *task_runner_; }
275 TestNowSource* now_src() { return now_src_.get(); }
277 // As this function contains EXPECT macros, to allow debugging it should be
278 // called inside EXPECT_SCOPED like so;
279 // EXPECT_SCOPED(client.InitializeOutputSurfaceAndFirstCommit(scheduler));
280 void InitializeOutputSurfaceAndFirstCommit() {
281 TRACE_EVENT0("cc",
282 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit");
283 DCHECK(scheduler_);
285 // Check the client doesn't have any actions queued when calling this
286 // function.
287 EXPECT_NO_ACTION(client_);
288 EXPECT_FALSE(client_->needs_begin_frames());
290 // Start the initial output surface creation.
291 EXPECT_FALSE(scheduler_->CanStart());
292 scheduler_->SetCanStart();
293 scheduler_->SetVisible(true);
294 scheduler_->SetCanDraw(true);
295 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
297 client_->Reset();
299 // We don't see anything happening until the first impl frame.
300 scheduler_->DidCreateAndInitializeOutputSurface();
301 scheduler_->SetNeedsCommit();
302 EXPECT_TRUE(client_->needs_begin_frames());
303 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
304 client_->Reset();
307 SCOPED_TRACE("Do first frame to commit after initialize.");
308 AdvanceFrame();
310 scheduler_->NotifyBeginMainFrameStarted();
311 scheduler_->NotifyReadyToCommitThenActivateIfNeeded();
313 EXPECT_FALSE(scheduler_->CommitPending());
315 if (scheduler_settings_.using_synchronous_renderer_compositor) {
316 scheduler_->SetNeedsRedraw();
317 scheduler_->OnDrawForOutputSurface();
318 } else {
319 // Run the posted deadline task.
320 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
321 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
324 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
327 client_->Reset();
330 SCOPED_TRACE(
331 "Run second frame so Scheduler calls SetNeedsBeginFrame(false).");
332 AdvanceFrame();
334 if (!scheduler_settings_.using_synchronous_renderer_compositor) {
335 // Run the posted deadline task.
336 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
337 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
340 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
343 EXPECT_FALSE(client_->needs_begin_frames());
344 client_->Reset();
347 // As this function contains EXPECT macros, to allow debugging it should be
348 // called inside EXPECT_SCOPED like so;
349 // EXPECT_SCOPED(client.AdvanceFrame());
350 void AdvanceFrame() {
351 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
352 "FakeSchedulerClient::AdvanceFrame");
353 // Consume any previous deadline first, if no deadline is currently
354 // pending, ImplFrameDeadlinePending will return false straight away and we
355 // will run no tasks.
356 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
357 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
359 // Send the next BeginFrame message if using an external source, otherwise
360 // it will be already in the task queue.
361 if (scheduler_->settings().use_external_begin_frame_source &&
362 scheduler_->FrameProductionThrottled()) {
363 EXPECT_TRUE(client_->needs_begin_frames());
364 SendNextBeginFrame();
367 if (!scheduler_->settings().using_synchronous_renderer_compositor) {
368 // Then run tasks until new deadline is scheduled.
369 EXPECT_TRUE(task_runner_->RunTasksWhile(
370 client_->ImplFrameDeadlinePending(false)));
371 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
375 void SendNextBeginFrame() {
376 DCHECK(scheduler_->settings().use_external_begin_frame_source);
377 // Creep the time forward so that any BeginFrameArgs is not equal to the
378 // last one otherwise we violate the BeginFrameSource contract.
379 now_src_->AdvanceNow(BeginFrameArgs::DefaultInterval());
380 fake_external_begin_frame_source_->TestOnBeginFrame(
381 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()));
384 FakeExternalBeginFrameSource* fake_external_begin_frame_source() const {
385 return fake_external_begin_frame_source_;
388 void MainFrameInHighLatencyMode(
389 int64 begin_main_frame_to_commit_estimate_in_ms,
390 int64 commit_to_activate_estimate_in_ms,
391 bool impl_latency_takes_priority,
392 bool should_send_begin_main_frame);
393 void BeginFramesNotFromClient(bool use_external_begin_frame_source,
394 bool throttle_frame_production);
395 void BeginFramesNotFromClient_SwapThrottled(
396 bool use_external_begin_frame_source,
397 bool throttle_frame_production);
398 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
399 bool impl_side_painting);
400 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting);
402 scoped_refptr<TestNowSource> now_src_;
403 scoped_refptr<OrderedSimpleTaskRunner> task_runner_;
404 FakeExternalBeginFrameSource* fake_external_begin_frame_source_;
405 SchedulerSettings scheduler_settings_;
406 scoped_ptr<FakeSchedulerClient> client_;
407 scoped_ptr<TestScheduler> scheduler_;
410 TEST_F(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) {
411 scheduler_settings_.use_external_begin_frame_source = true;
412 SetUpScheduler(false);
413 scheduler_->SetCanStart();
414 scheduler_->SetVisible(true);
415 scheduler_->SetCanDraw(true);
417 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
418 client_->Reset();
419 scheduler_->DidCreateAndInitializeOutputSurface();
420 EXPECT_NO_ACTION(client_);
423 TEST_F(SchedulerTest, SendBeginFramesToChildren) {
424 scheduler_settings_.use_external_begin_frame_source = true;
425 SetUpScheduler(true);
427 EXPECT_FALSE(client_->begin_frame_is_sent_to_children());
428 scheduler_->SetNeedsCommit();
429 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
430 EXPECT_TRUE(client_->needs_begin_frames());
432 scheduler_->SetChildrenNeedBeginFrames(true);
434 client_->Reset();
435 EXPECT_SCOPED(AdvanceFrame());
436 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
437 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
438 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
439 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
440 EXPECT_TRUE(client_->needs_begin_frames());
443 TEST_F(SchedulerTest, SendBeginFramesToChildrenWithoutCommit) {
444 scheduler_settings_.use_external_begin_frame_source = true;
445 SetUpScheduler(true);
447 EXPECT_FALSE(client_->needs_begin_frames());
448 scheduler_->SetChildrenNeedBeginFrames(true);
449 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
450 EXPECT_TRUE(client_->needs_begin_frames());
452 client_->Reset();
453 EXPECT_SCOPED(AdvanceFrame());
454 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
457 TEST_F(SchedulerTest, RequestCommit) {
458 scheduler_settings_.use_external_begin_frame_source = true;
459 SetUpScheduler(true);
461 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
462 scheduler_->SetNeedsCommit();
463 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
464 client_->Reset();
466 EXPECT_SCOPED(AdvanceFrame());
467 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
468 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
469 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
470 EXPECT_TRUE(client_->needs_begin_frames());
471 client_->Reset();
473 // If we don't swap on the deadline, we wait for the next BeginFrame.
474 task_runner().RunPendingTasks(); // Run posted deadline.
475 EXPECT_NO_ACTION(client_);
476 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
477 EXPECT_TRUE(client_->needs_begin_frames());
478 client_->Reset();
480 // NotifyReadyToCommit should trigger the commit.
481 scheduler_->NotifyBeginMainFrameStarted();
482 scheduler_->NotifyReadyToCommit();
483 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
484 EXPECT_TRUE(client_->needs_begin_frames());
485 client_->Reset();
487 // BeginImplFrame should prepare the draw.
488 EXPECT_SCOPED(AdvanceFrame());
489 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
490 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
491 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
492 EXPECT_TRUE(client_->needs_begin_frames());
493 client_->Reset();
495 // BeginImplFrame deadline should draw.
496 task_runner().RunPendingTasks(); // Run posted deadline.
497 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
498 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
499 EXPECT_TRUE(client_->needs_begin_frames());
500 client_->Reset();
502 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
503 // to avoid excessive toggles.
504 EXPECT_SCOPED(AdvanceFrame());
505 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
506 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
507 client_->Reset();
509 task_runner().RunPendingTasks(); // Run posted deadline.
510 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
511 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
512 client_->Reset();
515 TEST_F(SchedulerTest, RequestCommitAfterSetDeferCommit) {
516 scheduler_settings_.use_external_begin_frame_source = true;
517 SetUpScheduler(true);
519 scheduler_->SetDeferCommits(true);
521 scheduler_->SetNeedsCommit();
522 EXPECT_NO_ACTION(client_);
524 client_->Reset();
525 task_runner().RunPendingTasks();
526 // There are no pending tasks or actions.
527 EXPECT_NO_ACTION(client_);
528 EXPECT_FALSE(client_->needs_begin_frames());
530 client_->Reset();
531 scheduler_->SetDeferCommits(false);
532 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
534 // Start new BeginMainFrame after defer commit is off.
535 client_->Reset();
536 EXPECT_SCOPED(AdvanceFrame());
537 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
538 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
539 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
542 TEST_F(SchedulerTest, DeferCommitWithRedraw) {
543 scheduler_settings_.use_external_begin_frame_source = true;
544 SetUpScheduler(true);
546 scheduler_->SetDeferCommits(true);
548 scheduler_->SetNeedsCommit();
549 EXPECT_NO_ACTION(client_);
551 // The SetNeedsRedraw will override the SetDeferCommits(true), to allow a
552 // begin frame to be needed.
553 client_->Reset();
554 scheduler_->SetNeedsRedraw();
555 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
557 client_->Reset();
558 AdvanceFrame();
559 // BeginMainFrame is not sent during the defer commit is on.
560 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
561 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
563 client_->Reset();
564 task_runner().RunPendingTasks(); // Run posted deadline.
565 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
566 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
567 EXPECT_TRUE(client_->needs_begin_frames());
569 client_->Reset();
570 AdvanceFrame();
571 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
574 TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
575 scheduler_settings_.use_external_begin_frame_source = true;
576 SetUpScheduler(true);
578 // SetNeedsCommit should begin the frame.
579 scheduler_->SetNeedsCommit();
580 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
582 client_->Reset();
583 EXPECT_SCOPED(AdvanceFrame());
584 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
585 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
586 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
588 EXPECT_TRUE(client_->needs_begin_frames());
589 client_->Reset();
591 // Now SetNeedsCommit again. Calling here means we need a second commit.
592 scheduler_->SetNeedsCommit();
593 EXPECT_EQ(client_->num_actions_(), 0);
594 client_->Reset();
596 // Finish the first commit.
597 scheduler_->NotifyBeginMainFrameStarted();
598 scheduler_->NotifyReadyToCommit();
599 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
600 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
601 client_->Reset();
602 task_runner().RunPendingTasks(); // Run posted deadline.
603 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
604 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
605 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
607 // Because we just swapped, the Scheduler should also request the next
608 // BeginImplFrame from the OutputSurface.
609 EXPECT_TRUE(client_->needs_begin_frames());
610 client_->Reset();
611 // Since another commit is needed, the next BeginImplFrame should initiate
612 // the second commit.
613 EXPECT_SCOPED(AdvanceFrame());
614 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
615 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
616 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
617 client_->Reset();
619 // Finishing the commit before the deadline should post a new deadline task
620 // to trigger the deadline early.
621 scheduler_->NotifyBeginMainFrameStarted();
622 scheduler_->NotifyReadyToCommit();
623 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
624 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
625 client_->Reset();
626 task_runner().RunPendingTasks(); // Run posted deadline.
627 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
628 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
629 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
630 EXPECT_TRUE(client_->needs_begin_frames());
631 client_->Reset();
633 // On the next BeginImplFrame, verify we go back to a quiescent state and
634 // no longer request BeginImplFrames.
635 EXPECT_SCOPED(AdvanceFrame());
636 task_runner().RunPendingTasks(); // Run posted deadline.
637 EXPECT_FALSE(client_->needs_begin_frames());
638 client_->Reset();
641 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
642 public:
643 SchedulerClientThatsetNeedsDrawInsideDraw()
644 : FakeSchedulerClient(), request_redraws_(false) {}
646 void ScheduledActionSendBeginMainFrame() override {}
648 void SetRequestRedrawsInsideDraw(bool enable) { request_redraws_ = enable; }
650 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
651 // Only SetNeedsRedraw the first time this is called
652 if (request_redraws_) {
653 scheduler_->SetNeedsRedraw();
655 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
658 DrawResult ScheduledActionDrawAndSwapForced() override {
659 NOTREACHED();
660 return DRAW_SUCCESS;
663 void ScheduledActionCommit() override {}
664 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {}
666 private:
667 bool request_redraws_;
670 // Tests for two different situations:
671 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
672 // a ScheduledActionDrawAndSwap
673 // 2. the scheduler drawing twice inside a single tick
674 TEST_F(SchedulerTest, RequestRedrawInsideDraw) {
675 SchedulerClientThatsetNeedsDrawInsideDraw* client =
676 new SchedulerClientThatsetNeedsDrawInsideDraw;
677 scheduler_settings_.use_external_begin_frame_source = true;
678 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
679 client->SetRequestRedrawsInsideDraw(true);
681 scheduler_->SetNeedsRedraw();
682 EXPECT_TRUE(scheduler_->RedrawPending());
683 EXPECT_TRUE(client->needs_begin_frames());
684 EXPECT_EQ(0, client->num_draws());
686 EXPECT_SCOPED(AdvanceFrame());
687 task_runner().RunPendingTasks(); // Run posted deadline.
688 EXPECT_EQ(1, client->num_draws());
689 EXPECT_TRUE(scheduler_->RedrawPending());
690 EXPECT_TRUE(client->needs_begin_frames());
692 client->SetRequestRedrawsInsideDraw(false);
694 EXPECT_SCOPED(AdvanceFrame());
695 task_runner().RunPendingTasks(); // Run posted deadline.
696 EXPECT_EQ(2, client_->num_draws());
697 EXPECT_FALSE(scheduler_->RedrawPending());
698 EXPECT_TRUE(client->needs_begin_frames());
700 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
701 // swap.
702 EXPECT_SCOPED(AdvanceFrame());
703 task_runner().RunPendingTasks(); // Run posted deadline.
704 EXPECT_EQ(2, client->num_draws());
705 EXPECT_FALSE(scheduler_->RedrawPending());
706 EXPECT_FALSE(client->needs_begin_frames());
709 // Test that requesting redraw inside a failed draw doesn't lose the request.
710 TEST_F(SchedulerTest, RequestRedrawInsideFailedDraw) {
711 SchedulerClientThatsetNeedsDrawInsideDraw* client =
712 new SchedulerClientThatsetNeedsDrawInsideDraw;
713 scheduler_settings_.use_external_begin_frame_source = true;
714 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
716 client->SetRequestRedrawsInsideDraw(true);
717 client->SetDrawWillHappen(false);
719 scheduler_->SetNeedsRedraw();
720 EXPECT_TRUE(scheduler_->RedrawPending());
721 EXPECT_TRUE(client->needs_begin_frames());
722 EXPECT_EQ(0, client->num_draws());
724 // Fail the draw.
725 EXPECT_SCOPED(AdvanceFrame());
726 task_runner().RunPendingTasks(); // Run posted deadline.
727 EXPECT_EQ(1, client->num_draws());
729 // We have a commit pending and the draw failed, and we didn't lose the redraw
730 // request.
731 EXPECT_TRUE(scheduler_->CommitPending());
732 EXPECT_TRUE(scheduler_->RedrawPending());
733 EXPECT_TRUE(client->needs_begin_frames());
735 client->SetRequestRedrawsInsideDraw(false);
737 // Fail the draw again.
738 EXPECT_SCOPED(AdvanceFrame());
739 task_runner().RunPendingTasks(); // Run posted deadline.
740 EXPECT_EQ(2, client->num_draws());
741 EXPECT_TRUE(scheduler_->CommitPending());
742 EXPECT_TRUE(scheduler_->RedrawPending());
743 EXPECT_TRUE(client->needs_begin_frames());
745 // Draw successfully.
746 client->SetDrawWillHappen(true);
747 EXPECT_SCOPED(AdvanceFrame());
748 task_runner().RunPendingTasks(); // Run posted deadline.
749 EXPECT_EQ(3, client->num_draws());
750 EXPECT_TRUE(scheduler_->CommitPending());
751 EXPECT_FALSE(scheduler_->RedrawPending());
752 EXPECT_TRUE(client->needs_begin_frames());
755 class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
756 public:
757 SchedulerClientThatSetNeedsCommitInsideDraw()
758 : set_needs_commit_on_next_draw_(false) {}
760 void ScheduledActionSendBeginMainFrame() override {}
761 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
762 // Only SetNeedsCommit the first time this is called
763 if (set_needs_commit_on_next_draw_) {
764 scheduler_->SetNeedsCommit();
765 set_needs_commit_on_next_draw_ = false;
767 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
770 DrawResult ScheduledActionDrawAndSwapForced() override {
771 NOTREACHED();
772 return DRAW_SUCCESS;
775 void ScheduledActionCommit() override {}
776 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {}
778 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; }
780 private:
781 bool set_needs_commit_on_next_draw_;
784 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
785 // happen inside a ScheduledActionDrawAndSwap
786 TEST_F(SchedulerTest, RequestCommitInsideDraw) {
787 SchedulerClientThatSetNeedsCommitInsideDraw* client =
788 new SchedulerClientThatSetNeedsCommitInsideDraw;
790 scheduler_settings_.use_external_begin_frame_source = true;
791 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
793 EXPECT_FALSE(client->needs_begin_frames());
794 scheduler_->SetNeedsRedraw();
795 EXPECT_TRUE(scheduler_->RedrawPending());
796 EXPECT_EQ(0, client->num_draws());
797 EXPECT_TRUE(client->needs_begin_frames());
799 client->SetNeedsCommitOnNextDraw();
800 EXPECT_SCOPED(AdvanceFrame());
801 client->SetNeedsCommitOnNextDraw();
802 task_runner().RunPendingTasks(); // Run posted deadline.
803 EXPECT_EQ(1, client->num_draws());
804 EXPECT_TRUE(scheduler_->CommitPending());
805 EXPECT_TRUE(client->needs_begin_frames());
806 scheduler_->NotifyBeginMainFrameStarted();
807 scheduler_->NotifyReadyToCommit();
809 EXPECT_SCOPED(AdvanceFrame());
810 task_runner().RunPendingTasks(); // Run posted deadline.
811 EXPECT_EQ(2, client->num_draws());
813 EXPECT_FALSE(scheduler_->RedrawPending());
814 EXPECT_FALSE(scheduler_->CommitPending());
815 EXPECT_TRUE(client->needs_begin_frames());
817 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
818 // swap.
819 EXPECT_SCOPED(AdvanceFrame());
820 task_runner().RunPendingTasks(); // Run posted deadline.
821 EXPECT_EQ(2, client->num_draws());
822 EXPECT_FALSE(scheduler_->RedrawPending());
823 EXPECT_FALSE(scheduler_->CommitPending());
824 EXPECT_FALSE(client->needs_begin_frames());
827 // Tests that when a draw fails then the pending commit should not be dropped.
828 TEST_F(SchedulerTest, RequestCommitInsideFailedDraw) {
829 SchedulerClientThatsetNeedsDrawInsideDraw* client =
830 new SchedulerClientThatsetNeedsDrawInsideDraw;
831 scheduler_settings_.use_external_begin_frame_source = true;
832 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
834 client->SetDrawWillHappen(false);
836 scheduler_->SetNeedsRedraw();
837 EXPECT_TRUE(scheduler_->RedrawPending());
838 EXPECT_TRUE(client->needs_begin_frames());
839 EXPECT_EQ(0, client->num_draws());
841 // Fail the draw.
842 EXPECT_SCOPED(AdvanceFrame());
843 task_runner().RunPendingTasks(); // Run posted deadline.
844 EXPECT_EQ(1, client->num_draws());
846 // We have a commit pending and the draw failed, and we didn't lose the commit
847 // request.
848 EXPECT_TRUE(scheduler_->CommitPending());
849 EXPECT_TRUE(scheduler_->RedrawPending());
850 EXPECT_TRUE(client->needs_begin_frames());
852 // Fail the draw again.
853 EXPECT_SCOPED(AdvanceFrame());
855 task_runner().RunPendingTasks(); // Run posted deadline.
856 EXPECT_EQ(2, client->num_draws());
857 EXPECT_TRUE(scheduler_->CommitPending());
858 EXPECT_TRUE(scheduler_->RedrawPending());
859 EXPECT_TRUE(client->needs_begin_frames());
861 // Draw successfully.
862 client->SetDrawWillHappen(true);
863 EXPECT_SCOPED(AdvanceFrame());
864 task_runner().RunPendingTasks(); // Run posted deadline.
865 EXPECT_EQ(3, client->num_draws());
866 EXPECT_TRUE(scheduler_->CommitPending());
867 EXPECT_FALSE(scheduler_->RedrawPending());
868 EXPECT_TRUE(client->needs_begin_frames());
871 TEST_F(SchedulerTest, NoSwapWhenDrawFails) {
872 SchedulerClientThatSetNeedsCommitInsideDraw* client =
873 new SchedulerClientThatSetNeedsCommitInsideDraw;
874 scheduler_settings_.use_external_begin_frame_source = true;
875 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
877 scheduler_->SetNeedsRedraw();
878 EXPECT_TRUE(scheduler_->RedrawPending());
879 EXPECT_TRUE(client->needs_begin_frames());
880 EXPECT_EQ(0, client->num_draws());
882 // Draw successfully, this starts a new frame.
883 client->SetNeedsCommitOnNextDraw();
884 EXPECT_SCOPED(AdvanceFrame());
885 task_runner().RunPendingTasks(); // Run posted deadline.
886 EXPECT_EQ(1, client->num_draws());
888 scheduler_->SetNeedsRedraw();
889 EXPECT_TRUE(scheduler_->RedrawPending());
890 EXPECT_TRUE(client->needs_begin_frames());
892 // Fail to draw, this should not start a frame.
893 client->SetDrawWillHappen(false);
894 client->SetNeedsCommitOnNextDraw();
895 EXPECT_SCOPED(AdvanceFrame());
896 task_runner().RunPendingTasks(); // Run posted deadline.
897 EXPECT_EQ(2, client->num_draws());
900 class SchedulerClientNeedsPrepareTilesInDraw : public FakeSchedulerClient {
901 public:
902 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
903 scheduler_->SetNeedsPrepareTiles();
904 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
908 // Test prepare tiles is independant of draws.
909 TEST_F(SchedulerTest, PrepareTiles) {
910 SchedulerClientNeedsPrepareTilesInDraw* client =
911 new SchedulerClientNeedsPrepareTilesInDraw;
912 scheduler_settings_.use_external_begin_frame_source = true;
913 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
915 // Request both draw and prepare tiles. PrepareTiles shouldn't
916 // be trigged until BeginImplFrame.
917 client->Reset();
918 scheduler_->SetNeedsPrepareTiles();
919 scheduler_->SetNeedsRedraw();
920 EXPECT_TRUE(scheduler_->RedrawPending());
921 EXPECT_TRUE(scheduler_->PrepareTilesPending());
922 EXPECT_TRUE(client->needs_begin_frames());
923 EXPECT_EQ(0, client->num_draws());
924 EXPECT_FALSE(client->HasAction("ScheduledActionPrepareTiles"));
925 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
927 // We have no immediate actions to perform, so the BeginImplFrame should post
928 // the deadline task.
929 client->Reset();
930 EXPECT_SCOPED(AdvanceFrame());
931 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
932 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
933 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
935 // On the deadline, he actions should have occured in the right order.
936 client->Reset();
937 task_runner().RunPendingTasks(); // Run posted deadline.
938 EXPECT_EQ(1, client->num_draws());
939 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
940 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
941 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
942 client->ActionIndex("ScheduledActionPrepareTiles"));
943 EXPECT_FALSE(scheduler_->RedrawPending());
944 EXPECT_FALSE(scheduler_->PrepareTilesPending());
945 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
947 // Request a draw. We don't need a PrepareTiles yet.
948 client->Reset();
949 scheduler_->SetNeedsRedraw();
950 EXPECT_TRUE(scheduler_->RedrawPending());
951 EXPECT_FALSE(scheduler_->PrepareTilesPending());
952 EXPECT_TRUE(client->needs_begin_frames());
953 EXPECT_EQ(0, client->num_draws());
955 // We have no immediate actions to perform, so the BeginImplFrame should post
956 // the deadline task.
957 client->Reset();
958 EXPECT_SCOPED(AdvanceFrame());
959 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
960 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
961 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
963 // Draw. The draw will trigger SetNeedsPrepareTiles, and
964 // then the PrepareTiles action will be triggered after the Draw.
965 // Afterwards, neither a draw nor PrepareTiles are pending.
966 client->Reset();
967 task_runner().RunPendingTasks(); // Run posted deadline.
968 EXPECT_EQ(1, client->num_draws());
969 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
970 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
971 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
972 client->ActionIndex("ScheduledActionPrepareTiles"));
973 EXPECT_FALSE(scheduler_->RedrawPending());
974 EXPECT_FALSE(scheduler_->PrepareTilesPending());
975 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
977 // We need a BeginImplFrame where we don't swap to go idle.
978 client->Reset();
979 EXPECT_SCOPED(AdvanceFrame());
980 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
981 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
982 client->Reset();
983 task_runner().RunPendingTasks(); // Run posted deadline.
984 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
985 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
986 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
987 EXPECT_EQ(0, client->num_draws());
989 // Now trigger a PrepareTiles outside of a draw. We will then need
990 // a begin-frame for the PrepareTiles, but we don't need a draw.
991 client->Reset();
992 EXPECT_FALSE(client->needs_begin_frames());
993 scheduler_->SetNeedsPrepareTiles();
994 EXPECT_TRUE(client->needs_begin_frames());
995 EXPECT_TRUE(scheduler_->PrepareTilesPending());
996 EXPECT_FALSE(scheduler_->RedrawPending());
998 // BeginImplFrame. There will be no draw, only PrepareTiles.
999 client->Reset();
1000 EXPECT_SCOPED(AdvanceFrame());
1001 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1002 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1003 client->Reset();
1004 task_runner().RunPendingTasks(); // Run posted deadline.
1005 EXPECT_EQ(0, client->num_draws());
1006 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1007 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1008 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1011 // Test that PrepareTiles only happens once per frame. If an external caller
1012 // initiates it, then the state machine should not PrepareTiles on that frame.
1013 TEST_F(SchedulerTest, PrepareTilesOncePerFrame) {
1014 scheduler_settings_.use_external_begin_frame_source = true;
1015 SetUpScheduler(true);
1017 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
1018 // again.
1019 scheduler_->SetNeedsPrepareTiles();
1020 scheduler_->SetNeedsRedraw();
1021 client_->Reset();
1022 EXPECT_SCOPED(AdvanceFrame());
1023 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1024 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1025 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1027 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1028 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1029 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1031 client_->Reset();
1032 task_runner().RunPendingTasks(); // Run posted deadline.
1033 EXPECT_EQ(1, client_->num_draws());
1034 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1035 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1036 EXPECT_FALSE(scheduler_->RedrawPending());
1037 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1038 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1040 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1041 scheduler_->SetNeedsPrepareTiles();
1042 scheduler_->SetNeedsRedraw();
1043 client_->Reset();
1044 EXPECT_SCOPED(AdvanceFrame());
1045 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1046 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1047 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1049 client_->Reset();
1050 task_runner().RunPendingTasks(); // Run posted deadline.
1051 EXPECT_EQ(1, client_->num_draws());
1052 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1053 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1054 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1055 client_->ActionIndex("ScheduledActionPrepareTiles"));
1056 EXPECT_FALSE(scheduler_->RedrawPending());
1057 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1058 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1059 scheduler_->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1061 // If we get another DidPrepareTiles within the same frame, we should
1062 // not PrepareTiles on the next frame.
1063 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1064 scheduler_->SetNeedsPrepareTiles();
1065 scheduler_->SetNeedsRedraw();
1066 client_->Reset();
1067 EXPECT_SCOPED(AdvanceFrame());
1068 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1069 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1070 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1072 EXPECT_TRUE(scheduler_->PrepareTilesPending());
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_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1079 EXPECT_FALSE(scheduler_->RedrawPending());
1080 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1082 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1083 // frame. This verifies we don't alternate calling PrepareTiles once and
1084 // twice.
1085 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1086 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1087 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1088 scheduler_->SetNeedsPrepareTiles();
1089 scheduler_->SetNeedsRedraw();
1090 client_->Reset();
1091 EXPECT_SCOPED(AdvanceFrame());
1092 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1093 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1094 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1096 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1098 client_->Reset();
1099 task_runner().RunPendingTasks(); // Run posted deadline.
1100 EXPECT_EQ(1, client_->num_draws());
1101 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1102 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1103 EXPECT_FALSE(scheduler_->RedrawPending());
1104 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1106 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1107 scheduler_->SetNeedsPrepareTiles();
1108 scheduler_->SetNeedsRedraw();
1109 client_->Reset();
1110 EXPECT_SCOPED(AdvanceFrame());
1111 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1112 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1113 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1115 client_->Reset();
1116 task_runner().RunPendingTasks(); // Run posted deadline.
1117 EXPECT_EQ(1, client_->num_draws());
1118 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1119 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1120 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1121 client_->ActionIndex("ScheduledActionPrepareTiles"));
1122 EXPECT_FALSE(scheduler_->RedrawPending());
1123 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1124 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1125 scheduler_->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1128 TEST_F(SchedulerTest, TriggerBeginFrameDeadlineEarly) {
1129 SchedulerClientNeedsPrepareTilesInDraw* client =
1130 new SchedulerClientNeedsPrepareTilesInDraw;
1131 scheduler_settings_.use_external_begin_frame_source = true;
1132 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1134 scheduler_->SetNeedsRedraw();
1135 EXPECT_SCOPED(AdvanceFrame());
1137 // The deadline should be zero since there is no work other than drawing
1138 // pending.
1139 EXPECT_EQ(base::TimeTicks(), client->posted_begin_impl_frame_deadline());
1142 TEST_F(SchedulerTest, WaitForReadyToDrawDoNotPostDeadline) {
1143 SchedulerClientNeedsPrepareTilesInDraw* client =
1144 new SchedulerClientNeedsPrepareTilesInDraw;
1145 scheduler_settings_.use_external_begin_frame_source = true;
1146 scheduler_settings_.impl_side_painting = true;
1147 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1149 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1150 scheduler_->SetNeedsCommit();
1151 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1152 client_->Reset();
1154 // Begin new frame.
1155 EXPECT_SCOPED(AdvanceFrame());
1156 scheduler_->NotifyBeginMainFrameStarted();
1157 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1158 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1160 client_->Reset();
1161 scheduler_->NotifyReadyToCommit();
1162 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1164 client_->Reset();
1165 scheduler_->NotifyReadyToActivate();
1166 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
1168 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1169 // the mode.
1170 scheduler_->SetWaitForReadyToDraw();
1171 client_->Reset();
1172 task_runner().RunPendingTasks(); // Try to run posted deadline.
1173 // There is no posted deadline.
1174 EXPECT_NO_ACTION(client_);
1176 // Scheduler received ready to draw signal, and posted deadline.
1177 scheduler_->NotifyReadyToDraw();
1178 client_->Reset();
1179 task_runner().RunPendingTasks(); // Run posted deadline.
1180 EXPECT_EQ(1, client_->num_draws());
1181 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1184 TEST_F(SchedulerTest, WaitForReadyToDrawCancelledWhenLostOutputSurface) {
1185 SchedulerClientNeedsPrepareTilesInDraw* client =
1186 new SchedulerClientNeedsPrepareTilesInDraw;
1187 scheduler_settings_.use_external_begin_frame_source = true;
1188 scheduler_settings_.impl_side_painting = true;
1189 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1191 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1192 scheduler_->SetNeedsCommit();
1193 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1194 client_->Reset();
1196 // Begin new frame.
1197 EXPECT_SCOPED(AdvanceFrame());
1198 scheduler_->NotifyBeginMainFrameStarted();
1199 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1200 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1202 client_->Reset();
1203 scheduler_->NotifyReadyToCommit();
1204 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1206 client_->Reset();
1207 scheduler_->NotifyReadyToActivate();
1208 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
1210 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1211 // the mode.
1212 scheduler_->SetWaitForReadyToDraw();
1213 client_->Reset();
1214 task_runner().RunPendingTasks(); // Try to run posted deadline.
1215 // There is no posted deadline.
1216 EXPECT_NO_ACTION(client_);
1218 // Scheduler loses output surface, and stops waiting for ready to draw signal.
1219 client_->Reset();
1220 scheduler_->DidLoseOutputSurface();
1221 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1222 task_runner().RunPendingTasks(); // Run posted deadline.
1223 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
1224 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
1225 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
1228 class SchedulerClientWithFixedEstimates : public FakeSchedulerClient {
1229 public:
1230 SchedulerClientWithFixedEstimates(
1231 base::TimeDelta draw_duration,
1232 base::TimeDelta begin_main_frame_to_commit_duration,
1233 base::TimeDelta commit_to_activate_duration)
1234 : draw_duration_(draw_duration),
1235 begin_main_frame_to_commit_duration_(
1236 begin_main_frame_to_commit_duration),
1237 commit_to_activate_duration_(commit_to_activate_duration) {}
1239 base::TimeDelta DrawDurationEstimate() override { return draw_duration_; }
1240 base::TimeDelta BeginMainFrameToCommitDurationEstimate() override {
1241 return begin_main_frame_to_commit_duration_;
1243 base::TimeDelta CommitToActivateDurationEstimate() override {
1244 return commit_to_activate_duration_;
1247 private:
1248 base::TimeDelta draw_duration_;
1249 base::TimeDelta begin_main_frame_to_commit_duration_;
1250 base::TimeDelta commit_to_activate_duration_;
1253 void SchedulerTest::MainFrameInHighLatencyMode(
1254 int64 begin_main_frame_to_commit_estimate_in_ms,
1255 int64 commit_to_activate_estimate_in_ms,
1256 bool impl_latency_takes_priority,
1257 bool should_send_begin_main_frame) {
1258 // Set up client with specified estimates (draw duration is set to 1).
1259 SchedulerClientWithFixedEstimates* client =
1260 new SchedulerClientWithFixedEstimates(
1261 base::TimeDelta::FromMilliseconds(1),
1262 base::TimeDelta::FromMilliseconds(
1263 begin_main_frame_to_commit_estimate_in_ms),
1264 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms));
1266 scheduler_settings_.use_external_begin_frame_source = true;
1267 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1269 scheduler_->SetImplLatencyTakesPriority(impl_latency_takes_priority);
1271 // Impl thread hits deadline before commit finishes.
1272 scheduler_->SetNeedsCommit();
1273 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1274 EXPECT_SCOPED(AdvanceFrame());
1275 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1276 task_runner().RunPendingTasks(); // Run posted deadline.
1277 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1278 scheduler_->NotifyBeginMainFrameStarted();
1279 scheduler_->NotifyReadyToCommit();
1280 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1281 EXPECT_TRUE(client->HasAction("ScheduledActionSendBeginMainFrame"));
1283 client->Reset();
1284 scheduler_->SetNeedsCommit();
1285 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1286 EXPECT_SCOPED(AdvanceFrame());
1287 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1288 task_runner().RunPendingTasks(); // Run posted deadline.
1289 EXPECT_EQ(scheduler_->MainThreadIsInHighLatencyMode(),
1290 should_send_begin_main_frame);
1291 EXPECT_EQ(client->HasAction("ScheduledActionSendBeginMainFrame"),
1292 should_send_begin_main_frame);
1295 TEST_F(SchedulerTest,
1296 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) {
1297 // Set up client so that estimates indicate that we can commit and activate
1298 // before the deadline (~8ms by default).
1299 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, false, false));
1302 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) {
1303 // Set up client so that estimates indicate that the commit cannot finish
1304 // before the deadline (~8ms by default).
1305 EXPECT_SCOPED(MainFrameInHighLatencyMode(10, 1, false, true));
1308 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) {
1309 // Set up client so that estimates indicate that the activate cannot finish
1310 // before the deadline (~8ms by default).
1311 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true));
1314 TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) {
1315 // Set up client so that estimates indicate that we can commit and activate
1316 // before the deadline (~8ms by default), but also enable impl latency takes
1317 // priority mode.
1318 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true));
1321 TEST_F(SchedulerTest, PollForCommitCompletion) {
1322 // Since we are simulating a long commit, set up a client with draw duration
1323 // estimates that prevent skipping main frames to get to low latency mode.
1324 SchedulerClientWithFixedEstimates* client =
1325 new SchedulerClientWithFixedEstimates(
1326 base::TimeDelta::FromMilliseconds(1),
1327 base::TimeDelta::FromMilliseconds(32),
1328 base::TimeDelta::FromMilliseconds(32));
1329 scheduler_settings_.use_external_begin_frame_source = true;
1330 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1332 client->set_log_anticipated_draw_time_change(true);
1334 BeginFrameArgs frame_args =
1335 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
1336 frame_args.interval = base::TimeDelta::FromMilliseconds(1000);
1338 // At this point, we've drawn a frame. Start another commit, but hold off on
1339 // the NotifyReadyToCommit for now.
1340 EXPECT_FALSE(scheduler_->CommitPending());
1341 scheduler_->SetNeedsCommit();
1342 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args);
1343 EXPECT_TRUE(scheduler_->CommitPending());
1345 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1346 // blocking on the renderer.
1347 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1348 task_runner().RunPendingTasks(); // Run posted deadline.
1349 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1350 scheduler_->DidSwapBuffers();
1352 // Spin the event loop a few times and make sure we get more
1353 // DidAnticipateDrawTimeChange calls every time.
1354 int actions_so_far = client->num_actions_();
1356 // Does three iterations to make sure that the timer is properly repeating.
1357 for (int i = 0; i < 3; ++i) {
1358 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1359 task_runner().DelayToNextTaskTime().InMicroseconds())
1360 << scheduler_->AsValue()->ToString();
1361 task_runner().RunPendingTasks();
1362 EXPECT_GT(client->num_actions_(), actions_so_far);
1363 EXPECT_STREQ(client->Action(client->num_actions_() - 1),
1364 "DidAnticipatedDrawTimeChange");
1365 actions_so_far = client->num_actions_();
1368 // Do the same thing after BeginMainFrame starts but still before activation.
1369 scheduler_->NotifyBeginMainFrameStarted();
1370 for (int i = 0; i < 3; ++i) {
1371 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1372 task_runner().DelayToNextTaskTime().InMicroseconds())
1373 << scheduler_->AsValue()->ToString();
1374 task_runner().RunPendingTasks();
1375 EXPECT_GT(client->num_actions_(), actions_so_far);
1376 EXPECT_STREQ(client->Action(client->num_actions_() - 1),
1377 "DidAnticipatedDrawTimeChange");
1378 actions_so_far = client->num_actions_();
1382 TEST_F(SchedulerTest, BeginRetroFrame) {
1383 scheduler_settings_.use_external_begin_frame_source = true;
1384 SetUpScheduler(true);
1386 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1387 scheduler_->SetNeedsCommit();
1388 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1389 client_->Reset();
1391 // Create a BeginFrame with a long deadline to avoid race conditions.
1392 // This is the first BeginFrame, which will be handled immediately.
1393 BeginFrameArgs args =
1394 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
1395 args.deadline += base::TimeDelta::FromHours(1);
1396 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1397 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1398 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1399 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1400 EXPECT_TRUE(client_->needs_begin_frames());
1401 client_->Reset();
1403 // Queue BeginFrames while we are still handling the previous BeginFrame.
1404 args.frame_time += base::TimeDelta::FromSeconds(1);
1405 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1406 args.frame_time += base::TimeDelta::FromSeconds(1);
1407 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1409 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1410 task_runner().RunPendingTasks(); // Run posted deadline.
1411 EXPECT_NO_ACTION(client_);
1412 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1413 EXPECT_TRUE(client_->needs_begin_frames());
1414 client_->Reset();
1416 // NotifyReadyToCommit should trigger the commit.
1417 scheduler_->NotifyBeginMainFrameStarted();
1418 scheduler_->NotifyReadyToCommit();
1419 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1420 EXPECT_TRUE(client_->needs_begin_frames());
1421 client_->Reset();
1423 // BeginImplFrame should prepare the draw.
1424 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1425 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1426 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1427 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1428 EXPECT_TRUE(client_->needs_begin_frames());
1429 client_->Reset();
1431 // BeginImplFrame deadline should draw.
1432 task_runner().RunPendingTasks(); // Run posted deadline.
1433 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
1434 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1435 EXPECT_TRUE(client_->needs_begin_frames());
1436 client_->Reset();
1438 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1439 // to avoid excessive toggles.
1440 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1441 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
1442 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1443 client_->Reset();
1445 task_runner().RunPendingTasks(); // Run posted deadline.
1446 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1447 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1448 client_->Reset();
1451 TEST_F(SchedulerTest, BeginRetroFrame_SwapThrottled) {
1452 scheduler_settings_.use_external_begin_frame_source = true;
1453 SetUpScheduler(true);
1455 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1457 // To test swap ack throttling, this test disables automatic swap acks.
1458 scheduler_->SetMaxSwapsPending(1);
1459 client_->SetAutomaticSwapAck(false);
1461 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1462 client_->Reset();
1463 scheduler_->SetNeedsCommit();
1464 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1465 client_->Reset();
1467 EXPECT_SCOPED(AdvanceFrame());
1468 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1469 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1470 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1471 EXPECT_TRUE(client_->needs_begin_frames());
1472 client_->Reset();
1474 // Queue BeginFrame while we are still handling the previous BeginFrame.
1475 SendNextBeginFrame();
1476 EXPECT_NO_ACTION(client_);
1477 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1478 EXPECT_TRUE(client_->needs_begin_frames());
1479 client_->Reset();
1481 // NotifyReadyToCommit should trigger the pending commit and draw.
1482 scheduler_->NotifyBeginMainFrameStarted();
1483 scheduler_->NotifyReadyToCommit();
1484 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1485 EXPECT_TRUE(client_->needs_begin_frames());
1486 client_->Reset();
1488 // Swapping will put us into a swap throttled state.
1489 // Run posted deadline.
1490 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1491 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1492 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1493 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1494 EXPECT_TRUE(client_->needs_begin_frames());
1495 client_->Reset();
1497 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1498 // and BeginMainFrame.
1499 scheduler_->SetNeedsCommit();
1500 scheduler_->SetNeedsRedraw();
1501 // Run posted BeginRetroFrame.
1502 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
1503 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
1504 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
1505 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3);
1506 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1507 EXPECT_TRUE(client_->needs_begin_frames());
1508 client_->Reset();
1510 // Let time pass sufficiently beyond the regular deadline but not beyond the
1511 // late deadline.
1512 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1513 base::TimeDelta::FromMicroseconds(1));
1514 task_runner().RunUntilTime(now_src()->Now());
1515 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1517 // Take us out of a swap throttled state.
1518 scheduler_->DidSwapBuffersComplete();
1519 EXPECT_NO_ACTION(client_);
1520 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1521 EXPECT_TRUE(client_->needs_begin_frames());
1522 client_->Reset();
1524 // Verify that the deadline was rescheduled.
1525 task_runner().RunUntilTime(now_src()->Now());
1526 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
1527 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1528 EXPECT_TRUE(client_->needs_begin_frames());
1529 client_->Reset();
1532 TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooEarly) {
1533 scheduler_settings_.use_external_begin_frame_source = true;
1534 SetUpScheduler(true);
1536 scheduler_->SetNeedsCommit();
1537 EXPECT_TRUE(client_->needs_begin_frames());
1538 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1540 client_->Reset();
1541 EXPECT_SCOPED(AdvanceFrame());
1542 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1543 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1544 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1546 client_->Reset();
1547 scheduler_->NotifyBeginMainFrameStarted();
1549 client_->Reset();
1550 SendNextBeginFrame();
1551 // This BeginFrame is queued up as a retro frame.
1552 EXPECT_NO_ACTION(client_);
1553 // The previous deadline is still pending.
1554 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1556 client_->Reset();
1557 // This commit should schedule the (previous) deadline to trigger immediately.
1558 scheduler_->NotifyReadyToCommit();
1559 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1561 client_->Reset();
1562 // The deadline task should trigger causing a draw.
1563 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1564 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1565 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1566 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1568 // Keep animating.
1569 client_->Reset();
1570 scheduler_->SetNeedsAnimate();
1571 scheduler_->SetNeedsRedraw();
1572 EXPECT_NO_ACTION(client_);
1574 // Let's advance sufficiently past the next frame's deadline.
1575 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1576 BeginFrameArgs::DefaultEstimatedParentDrawTime() +
1577 base::TimeDelta::FromMicroseconds(1));
1579 // The retro frame hasn't expired yet.
1580 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
1581 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1582 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1583 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1585 // This is an immediate deadline case.
1586 client_->Reset();
1587 task_runner().RunPendingTasks();
1588 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1589 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
1592 TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooLate) {
1593 scheduler_settings_.use_external_begin_frame_source = true;
1594 SetUpScheduler(true);
1596 scheduler_->SetNeedsCommit();
1597 EXPECT_TRUE(client_->needs_begin_frames());
1598 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1600 client_->Reset();
1601 EXPECT_SCOPED(AdvanceFrame());
1602 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1603 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1604 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1606 client_->Reset();
1607 scheduler_->NotifyBeginMainFrameStarted();
1609 client_->Reset();
1610 SendNextBeginFrame();
1611 // This BeginFrame is queued up as a retro frame.
1612 EXPECT_NO_ACTION(client_);
1613 // The previous deadline is still pending.
1614 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1616 client_->Reset();
1617 // This commit should schedule the (previous) deadline to trigger immediately.
1618 scheduler_->NotifyReadyToCommit();
1619 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1621 client_->Reset();
1622 // The deadline task should trigger causing a draw.
1623 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1624 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1625 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1626 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1628 // Keep animating.
1629 client_->Reset();
1630 scheduler_->SetNeedsAnimate();
1631 scheduler_->SetNeedsRedraw();
1632 EXPECT_NO_ACTION(client_);
1634 // Let's advance sufficiently past the next frame's deadline.
1635 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() +
1636 base::TimeDelta::FromMicroseconds(1));
1638 // The retro frame should've expired.
1639 EXPECT_NO_ACTION(client_);
1642 void SchedulerTest::BeginFramesNotFromClient(
1643 bool use_external_begin_frame_source,
1644 bool throttle_frame_production) {
1645 scheduler_settings_.use_external_begin_frame_source =
1646 use_external_begin_frame_source;
1647 scheduler_settings_.throttle_frame_production = throttle_frame_production;
1648 SetUpScheduler(true);
1650 // SetNeedsCommit should begin the frame on the next BeginImplFrame
1651 // without calling SetNeedsBeginFrame.
1652 scheduler_->SetNeedsCommit();
1653 EXPECT_NO_ACTION(client_);
1654 client_->Reset();
1656 // When the client-driven BeginFrame are disabled, the scheduler posts it's
1657 // own BeginFrame tasks.
1658 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1659 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1660 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1661 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1662 client_->Reset();
1664 // If we don't swap on the deadline, we wait for the next BeginFrame.
1665 task_runner().RunPendingTasks(); // Run posted deadline.
1666 EXPECT_NO_ACTION(client_);
1667 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1668 client_->Reset();
1670 // NotifyReadyToCommit should trigger the commit.
1671 scheduler_->NotifyBeginMainFrameStarted();
1672 scheduler_->NotifyReadyToCommit();
1673 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1674 client_->Reset();
1676 // BeginImplFrame should prepare the draw.
1677 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1678 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1679 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1680 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1681 client_->Reset();
1683 // BeginImplFrame deadline should draw.
1684 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1685 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
1686 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1687 client_->Reset();
1689 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1690 // to avoid excessive toggles.
1691 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1692 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
1693 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1694 client_->Reset();
1696 // Make sure SetNeedsBeginFrame isn't called on the client
1697 // when the BeginFrame is no longer needed.
1698 task_runner().RunPendingTasks(); // Run posted deadline.
1699 EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_);
1700 client_->Reset();
1703 TEST_F(SchedulerTest, SyntheticBeginFrames) {
1704 bool use_external_begin_frame_source = false;
1705 bool throttle_frame_production = true;
1706 BeginFramesNotFromClient(use_external_begin_frame_source,
1707 throttle_frame_production);
1710 TEST_F(SchedulerTest, VSyncThrottlingDisabled) {
1711 bool use_external_begin_frame_source = true;
1712 bool throttle_frame_production = false;
1713 BeginFramesNotFromClient(use_external_begin_frame_source,
1714 throttle_frame_production);
1717 TEST_F(SchedulerTest, SyntheticBeginFrames_And_VSyncThrottlingDisabled) {
1718 bool use_external_begin_frame_source = false;
1719 bool throttle_frame_production = false;
1720 BeginFramesNotFromClient(use_external_begin_frame_source,
1721 throttle_frame_production);
1724 void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
1725 bool use_external_begin_frame_source,
1726 bool throttle_frame_production) {
1727 scheduler_settings_.use_external_begin_frame_source =
1728 use_external_begin_frame_source;
1729 scheduler_settings_.throttle_frame_production = throttle_frame_production;
1730 SetUpScheduler(true);
1732 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1734 // To test swap ack throttling, this test disables automatic swap acks.
1735 scheduler_->SetMaxSwapsPending(1);
1736 client_->SetAutomaticSwapAck(false);
1738 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1739 client_->Reset();
1740 scheduler_->SetNeedsCommit();
1741 EXPECT_NO_ACTION(client_);
1742 client_->Reset();
1744 // Trigger the first BeginImplFrame and BeginMainFrame
1745 EXPECT_SCOPED(AdvanceFrame());
1746 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1747 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1748 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1749 client_->Reset();
1751 // NotifyReadyToCommit should trigger the pending commit and draw.
1752 scheduler_->NotifyBeginMainFrameStarted();
1753 scheduler_->NotifyReadyToCommit();
1754 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1755 client_->Reset();
1757 // Swapping will put us into a swap throttled state.
1758 // Run posted deadline.
1759 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1760 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1761 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1762 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1763 client_->Reset();
1765 // While swap throttled, BeginFrames should trigger BeginImplFrames
1766 // and BeginMainFrame.
1767 scheduler_->SetNeedsCommit();
1768 scheduler_->SetNeedsRedraw();
1769 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
1770 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
1771 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
1772 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3);
1773 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1774 client_->Reset();
1776 // Let time pass sufficiently beyond the regular deadline but not beyond the
1777 // late deadline.
1778 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1779 base::TimeDelta::FromMicroseconds(1));
1780 task_runner().RunUntilTime(now_src()->Now());
1781 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1783 // Take us out of a swap throttled state.
1784 scheduler_->DidSwapBuffersComplete();
1785 EXPECT_NO_ACTION(client_);
1786 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1787 client_->Reset();
1789 // Verify that the deadline was rescheduled.
1790 // We can't use RunUntilTime(now) here because the next frame is also
1791 // scheduled if throttle_frame_production = false.
1792 base::TimeTicks before_deadline = now_src()->Now();
1793 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1794 base::TimeTicks after_deadline = now_src()->Now();
1795 EXPECT_EQ(after_deadline, before_deadline);
1796 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1797 client_->Reset();
1800 TEST_F(SchedulerTest, SyntheticBeginFrames_SwapThrottled) {
1801 bool use_external_begin_frame_source = false;
1802 bool throttle_frame_production = true;
1803 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
1804 throttle_frame_production);
1807 TEST_F(SchedulerTest, VSyncThrottlingDisabled_SwapThrottled) {
1808 bool use_external_begin_frame_source = true;
1809 bool throttle_frame_production = false;
1810 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
1811 throttle_frame_production);
1814 TEST_F(SchedulerTest,
1815 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled) {
1816 bool use_external_begin_frame_source = false;
1817 bool throttle_frame_production = false;
1818 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
1819 throttle_frame_production);
1822 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized) {
1823 scheduler_settings_.use_external_begin_frame_source = true;
1824 SetUpScheduler(false);
1826 scheduler_->SetCanStart();
1827 scheduler_->SetVisible(true);
1828 scheduler_->SetCanDraw(true);
1830 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
1831 client_->Reset();
1832 scheduler_->DidCreateAndInitializeOutputSurface();
1833 EXPECT_NO_ACTION(client_);
1835 scheduler_->DidLoseOutputSurface();
1836 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
1839 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) {
1840 scheduler_settings_.use_external_begin_frame_source = true;
1841 SetUpScheduler(true);
1843 // SetNeedsCommit should begin the frame.
1844 scheduler_->SetNeedsCommit();
1845 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1847 client_->Reset();
1848 EXPECT_SCOPED(AdvanceFrame());
1849 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1850 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1851 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1853 client_->Reset();
1854 scheduler_->DidLoseOutputSurface();
1855 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1856 EXPECT_NO_ACTION(client_);
1858 client_->Reset();
1859 scheduler_->NotifyBeginMainFrameStarted();
1860 scheduler_->NotifyReadyToCommit();
1861 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 1);
1863 client_->Reset();
1864 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1865 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
1866 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
1867 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
1870 void SchedulerTest::DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
1871 bool impl_side_painting) {
1872 scheduler_settings_.impl_side_painting = impl_side_painting;
1873 scheduler_settings_.use_external_begin_frame_source = true;
1874 SetUpScheduler(true);
1876 // SetNeedsCommit should begin the frame.
1877 scheduler_->SetNeedsCommit();
1878 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1880 client_->Reset();
1881 EXPECT_SCOPED(AdvanceFrame());
1882 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1883 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1884 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1886 client_->Reset();
1887 scheduler_->DidLoseOutputSurface();
1888 // Do nothing when impl frame is in deadine pending state.
1889 EXPECT_NO_ACTION(client_);
1891 client_->Reset();
1892 // Run posted deadline.
1893 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1894 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1895 // OnBeginImplFrameDeadline didn't schedule output surface creation because
1896 // main frame is not yet completed.
1897 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1898 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1899 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1901 // BeginImplFrame is not started.
1902 client_->Reset();
1903 task_runner().RunUntilTime(now_src()->Now() +
1904 base::TimeDelta::FromMilliseconds(10));
1905 EXPECT_NO_ACTION(client_);
1906 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1908 client_->Reset();
1909 scheduler_->NotifyBeginMainFrameStarted();
1910 scheduler_->NotifyReadyToCommit();
1911 if (impl_side_painting) {
1912 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 3);
1913 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 3);
1914 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 2, 3);
1915 } else {
1916 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2);
1917 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 2);
1921 TEST_F(SchedulerTest,
1922 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) {
1923 bool impl_side_painting = false;
1924 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
1927 TEST_F(SchedulerTest,
1928 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint) {
1929 bool impl_side_painting = true;
1930 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
1933 void SchedulerTest::DidLoseOutputSurfaceAfterReadyToCommit(
1934 bool impl_side_painting) {
1935 scheduler_settings_.impl_side_painting = impl_side_painting;
1936 scheduler_settings_.use_external_begin_frame_source = true;
1937 SetUpScheduler(true);
1939 // SetNeedsCommit should begin the frame.
1940 scheduler_->SetNeedsCommit();
1941 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1943 client_->Reset();
1944 EXPECT_SCOPED(AdvanceFrame());
1945 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1946 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1947 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1949 client_->Reset();
1950 scheduler_->NotifyBeginMainFrameStarted();
1951 scheduler_->NotifyReadyToCommit();
1952 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1954 client_->Reset();
1955 scheduler_->DidLoseOutputSurface();
1956 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1957 if (impl_side_painting) {
1958 // Sync tree should be forced to activate.
1959 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
1960 } else {
1961 EXPECT_NO_ACTION(client_);
1964 client_->Reset();
1965 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1966 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
1967 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
1968 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
1971 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) {
1972 DidLoseOutputSurfaceAfterReadyToCommit(false);
1975 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting) {
1976 DidLoseOutputSurfaceAfterReadyToCommit(true);
1979 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles) {
1980 scheduler_settings_.use_external_begin_frame_source = true;
1981 SetUpScheduler(true);
1983 scheduler_->SetNeedsPrepareTiles();
1984 scheduler_->SetNeedsRedraw();
1985 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1987 client_->Reset();
1988 EXPECT_SCOPED(AdvanceFrame());
1989 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1990 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1991 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1993 client_->Reset();
1994 scheduler_->DidLoseOutputSurface();
1995 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1996 EXPECT_NO_ACTION(client_);
1998 client_->Reset();
1999 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2000 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 0, 4);
2001 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 4);
2002 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 2, 4);
2003 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 3, 4);
2006 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) {
2007 scheduler_settings_.use_external_begin_frame_source = true;
2008 SetUpScheduler(true);
2010 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2011 scheduler_->SetNeedsCommit();
2012 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2014 // Create a BeginFrame with a long deadline to avoid race conditions.
2015 // This is the first BeginFrame, which will be handled immediately.
2016 client_->Reset();
2017 BeginFrameArgs args =
2018 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2019 args.deadline += base::TimeDelta::FromHours(1);
2020 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2021 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2022 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2023 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2024 EXPECT_TRUE(client_->needs_begin_frames());
2026 // Queue BeginFrames while we are still handling the previous BeginFrame.
2027 args.frame_time += base::TimeDelta::FromSeconds(1);
2028 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2029 args.frame_time += base::TimeDelta::FromSeconds(1);
2030 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2032 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2033 client_->Reset();
2034 task_runner().RunPendingTasks(); // Run posted deadline.
2035 EXPECT_NO_ACTION(client_);
2036 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2037 EXPECT_TRUE(client_->needs_begin_frames());
2039 // NotifyReadyToCommit should trigger the commit.
2040 client_->Reset();
2041 scheduler_->NotifyBeginMainFrameStarted();
2042 scheduler_->NotifyReadyToCommit();
2043 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2044 EXPECT_TRUE(client_->needs_begin_frames());
2046 client_->Reset();
2047 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty());
2048 scheduler_->DidLoseOutputSurface();
2049 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2050 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2051 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2052 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty());
2054 // Posted BeginRetroFrame is aborted.
2055 client_->Reset();
2056 task_runner().RunPendingTasks();
2057 EXPECT_NO_ACTION(client_);
2060 TEST_F(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) {
2061 scheduler_settings_.use_external_begin_frame_source = true;
2062 SetUpScheduler(true);
2064 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2065 scheduler_->SetNeedsCommit();
2066 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2068 // Create a BeginFrame with a long deadline to avoid race conditions.
2069 // This is the first BeginFrame, which will be handled immediately.
2070 client_->Reset();
2071 BeginFrameArgs args =
2072 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2073 args.deadline += base::TimeDelta::FromHours(1);
2074 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2075 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2076 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2077 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2078 EXPECT_TRUE(client_->needs_begin_frames());
2080 // Queue BeginFrames while we are still handling the previous BeginFrame.
2081 args.frame_time += base::TimeDelta::FromSeconds(1);
2082 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2083 args.frame_time += base::TimeDelta::FromSeconds(1);
2084 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2086 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2087 client_->Reset();
2088 task_runner().RunPendingTasks(); // Run posted deadline.
2089 EXPECT_NO_ACTION(client_);
2090 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2091 EXPECT_TRUE(client_->needs_begin_frames());
2093 // NotifyReadyToCommit should trigger the commit.
2094 client_->Reset();
2095 scheduler_->NotifyBeginMainFrameStarted();
2096 scheduler_->NotifyReadyToCommit();
2097 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2098 EXPECT_TRUE(client_->needs_begin_frames());
2100 // BeginImplFrame should prepare the draw.
2101 client_->Reset();
2102 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2103 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2104 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2105 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2106 EXPECT_TRUE(client_->needs_begin_frames());
2108 client_->Reset();
2109 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty());
2110 scheduler_->DidLoseOutputSurface();
2111 EXPECT_NO_ACTION(client_);
2112 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty());
2114 // BeginImplFrame deadline should abort drawing.
2115 client_->Reset();
2116 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2117 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2118 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2119 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2120 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2121 EXPECT_FALSE(client_->needs_begin_frames());
2123 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
2124 client_->Reset();
2125 task_runner().RunPendingTasks();
2126 EXPECT_NO_ACTION(client_);
2129 TEST_F(SchedulerTest, DidLoseOutputSurfaceWithSyntheticBeginFrameSource) {
2130 SetUpScheduler(true);
2132 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2133 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2134 scheduler_->SetNeedsCommit();
2135 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2137 client_->Reset();
2138 AdvanceFrame();
2139 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2140 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2141 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2142 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2144 // NotifyReadyToCommit should trigger the commit.
2145 client_->Reset();
2146 scheduler_->NotifyBeginMainFrameStarted();
2147 scheduler_->NotifyReadyToCommit();
2148 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2149 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2151 client_->Reset();
2152 scheduler_->DidLoseOutputSurface();
2153 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2154 EXPECT_NO_ACTION(client_);
2155 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2157 client_->Reset();
2158 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2159 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 2);
2160 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2161 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2164 TEST_F(SchedulerTest, DidLoseOutputSurfaceWhenIdle) {
2165 scheduler_settings_.use_external_begin_frame_source = true;
2166 SetUpScheduler(true);
2168 // SetNeedsCommit should begin the frame.
2169 scheduler_->SetNeedsCommit();
2170 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2172 client_->Reset();
2173 EXPECT_SCOPED(AdvanceFrame());
2174 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2175 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2176 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2178 client_->Reset();
2179 scheduler_->NotifyBeginMainFrameStarted();
2180 scheduler_->NotifyReadyToCommit();
2181 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2183 client_->Reset();
2184 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2185 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2186 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2188 // Idle time between BeginFrames.
2189 client_->Reset();
2190 scheduler_->DidLoseOutputSurface();
2191 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2192 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2193 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2196 TEST_F(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) {
2197 scheduler_settings_.impl_side_painting = true;
2198 scheduler_settings_.use_external_begin_frame_source = true;
2199 SetUpScheduler(true);
2201 // SetNeedsCommit should begin the frame.
2202 scheduler_->SetNeedsCommit();
2203 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2205 client_->Reset();
2206 EXPECT_SCOPED(AdvanceFrame());
2207 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2208 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2209 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2211 client_->Reset();
2212 scheduler_->NotifyBeginMainFrameStarted();
2213 scheduler_->NotifyReadyToCommit();
2214 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2215 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2217 client_->Reset();
2218 scheduler_->SetVisible(false);
2219 task_runner().RunPendingTasks(); // Run posted deadline.
2221 // Sync tree should be forced to activate.
2222 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 3);
2223 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2224 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2227 // Tests to ensure frame sources can be successfully changed while drawing.
2228 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottled) {
2229 scheduler_settings_.use_external_begin_frame_source = true;
2230 SetUpScheduler(true);
2232 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2233 scheduler_->SetNeedsRedraw();
2234 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2235 client_->Reset();
2237 EXPECT_SCOPED(AdvanceFrame());
2238 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2239 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2240 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2241 EXPECT_TRUE(client_->needs_begin_frames());
2242 client_->Reset();
2243 task_runner().RunPendingTasks(); // Run posted deadline.
2244 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2245 scheduler_->SetNeedsRedraw();
2247 // Switch to an unthrottled frame source.
2248 scheduler_->SetThrottleFrameProduction(false);
2249 client_->Reset();
2251 // Unthrottled frame source will immediately begin a new frame.
2252 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2253 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2254 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2255 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2256 client_->Reset();
2258 // If we don't swap on the deadline, we wait for the next BeginFrame.
2259 task_runner().RunPendingTasks(); // Run posted deadline.
2260 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2261 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2262 client_->Reset();
2265 // Tests to ensure frame sources can be successfully changed while a frame
2266 // deadline is pending.
2267 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottledBeforeDeadline) {
2268 scheduler_settings_.use_external_begin_frame_source = true;
2269 SetUpScheduler(true);
2271 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2272 scheduler_->SetNeedsRedraw();
2273 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2274 client_->Reset();
2276 EXPECT_SCOPED(AdvanceFrame());
2277 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2278 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2280 // Switch to an unthrottled frame source before the frame deadline is hit.
2281 scheduler_->SetThrottleFrameProduction(false);
2282 client_->Reset();
2284 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2285 EXPECT_TRUE(client_->needs_begin_frames());
2286 client_->Reset();
2288 task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame.
2289 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
2290 // Unthrottled frame source will immediately begin a new frame.
2291 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 2);
2292 scheduler_->SetNeedsRedraw();
2293 client_->Reset();
2295 task_runner().RunPendingTasks(); // Run posted deadline.
2296 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2297 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2298 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2299 client_->Reset();
2302 // Tests to ensure that the active frame source can successfully be changed from
2303 // unthrottled to throttled.
2304 TEST_F(SchedulerTest, SwitchFrameSourceToThrottled) {
2305 scheduler_settings_.throttle_frame_production = false;
2306 scheduler_settings_.use_external_begin_frame_source = true;
2307 SetUpScheduler(true);
2309 scheduler_->SetNeedsRedraw();
2310 EXPECT_NO_ACTION(client_);
2311 client_->Reset();
2313 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2314 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2315 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2316 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2317 client_->Reset();
2319 task_runner().RunPendingTasks(); // Run posted deadline.
2320 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2321 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2322 client_->Reset();
2324 // Switch to a throttled frame source.
2325 scheduler_->SetThrottleFrameProduction(true);
2326 client_->Reset();
2328 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2329 scheduler_->SetNeedsRedraw();
2330 task_runner().RunPendingTasks();
2331 EXPECT_NO_ACTION(client_);
2332 client_->Reset();
2334 EXPECT_SCOPED(AdvanceFrame());
2335 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2336 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2337 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2338 EXPECT_TRUE(client_->needs_begin_frames());
2339 client_->Reset();
2340 task_runner().RunPendingTasks(); // Run posted deadline.
2341 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2344 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
2345 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon) {
2346 scheduler_settings_.use_external_begin_frame_source = true;
2347 SetUpScheduler(true);
2349 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2350 scheduler_->SetNeedsCommit();
2351 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2352 client_->Reset();
2354 // Trigger a frame draw.
2355 EXPECT_SCOPED(AdvanceFrame());
2356 scheduler_->NotifyBeginMainFrameStarted();
2357 scheduler_->NotifyReadyToCommit();
2358 task_runner().RunPendingTasks();
2359 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 5);
2360 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 5);
2361 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 5);
2362 EXPECT_ACTION("ScheduledActionAnimate", client_, 3, 5);
2363 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 5);
2364 client_->Reset();
2366 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2367 // and send a SendBeginMainFrameNotExpectedSoon.
2368 EXPECT_SCOPED(AdvanceFrame());
2369 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
2370 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2371 client_->Reset();
2373 task_runner().RunPendingTasks(); // Run posted deadline.
2374 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
2375 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2376 client_->Reset();
2379 TEST_F(SchedulerTest, UsingSynchronousCompositor) {
2380 scheduler_settings_.using_synchronous_renderer_compositor = true;
2381 scheduler_settings_.use_external_begin_frame_source = true;
2382 scheduler_settings_.impl_side_painting = true;
2383 SetUpScheduler(true);
2385 // Compositor thread initiated input/animation.
2386 // --------------------------------------------
2387 scheduler_->SetNeedsAnimate();
2388 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2389 client_->Reset();
2391 // Next vsync.
2392 AdvanceFrame();
2393 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2394 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
2395 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
2396 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2397 client_->Reset();
2399 // Continue with animation.
2400 scheduler_->SetNeedsAnimate();
2401 EXPECT_NO_ACTION(client_);
2403 // Android onDraw.
2404 scheduler_->SetNeedsRedraw();
2405 scheduler_->OnDrawForOutputSurface();
2406 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
2407 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2408 client_->Reset();
2410 // Next vsync.
2411 AdvanceFrame();
2412 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2413 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
2414 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
2415 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2416 client_->Reset();
2418 // Android onDraw.
2419 scheduler_->SetNeedsRedraw();
2420 scheduler_->OnDrawForOutputSurface();
2421 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
2422 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2423 client_->Reset();
2425 // Idle on next vsync.
2426 AdvanceFrame();
2427 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2428 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2429 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2430 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2431 client_->Reset();
2433 // Android onDraw after idle.
2434 // --------------------------
2435 scheduler_->SetNeedsRedraw();
2436 scheduler_->OnDrawForOutputSurface();
2437 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3);
2438 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
2439 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3);
2440 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2441 client_->Reset();
2443 // Idle on next vsync.
2444 AdvanceFrame();
2445 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2446 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2447 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2448 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2449 client_->Reset();
2451 // Main thread initiated activity.
2452 // -------------------------------
2453 scheduler_->SetNeedsCommit();
2454 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2455 client_->Reset();
2457 // Next vsync.
2458 AdvanceFrame();
2459 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2460 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2461 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2462 client_->Reset();
2464 scheduler_->NotifyBeginMainFrameStarted();
2465 EXPECT_NO_ACTION(client_);
2467 // Next vsync.
2468 AdvanceFrame();
2469 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
2470 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2471 client_->Reset();
2473 scheduler_->NotifyReadyToCommit();
2474 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2475 client_->Reset();
2477 scheduler_->NotifyReadyToActivate();
2478 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2479 client_->Reset();
2481 // Next vsync.
2482 AdvanceFrame();
2483 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2484 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
2485 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
2486 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2487 client_->Reset();
2489 // Android onDraw.
2490 scheduler_->SetNeedsRedraw();
2491 scheduler_->OnDrawForOutputSurface();
2492 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
2493 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2494 client_->Reset();
2496 // Idle on next vsync.
2497 AdvanceFrame();
2498 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2499 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2500 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2501 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2502 client_->Reset();
2505 TEST_F(SchedulerTest, AuthoritativeVSyncInterval) {
2506 SetUpScheduler(true);
2508 base::TimeDelta initial_interval =
2509 scheduler_->begin_impl_frame_args().interval;
2510 base::TimeDelta authoritative_interval =
2511 base::TimeDelta::FromMilliseconds(33);
2513 scheduler_->SetNeedsCommit();
2514 EXPECT_SCOPED(AdvanceFrame());
2516 EXPECT_EQ(initial_interval, scheduler_->begin_impl_frame_args().interval);
2518 scheduler_->NotifyBeginMainFrameStarted();
2519 scheduler_->NotifyReadyToCommit();
2520 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2522 scheduler_->SetAuthoritativeVSyncInterval(authoritative_interval);
2524 EXPECT_SCOPED(AdvanceFrame());
2526 // At the next BeginFrame, authoritative interval is used instead of previous
2527 // interval.
2528 EXPECT_NE(initial_interval, scheduler_->begin_impl_frame_args().interval);
2529 EXPECT_EQ(authoritative_interval,
2530 scheduler_->begin_impl_frame_args().interval);
2533 } // namespace
2534 } // namespace cc