[Enhanced Bookmark] Change "Bookmark Bar" to "Bookmark bar" on Android
[chromium-blink-merge.git] / cc / scheduler / scheduler_unittest.cc
blobdacc03ce21ae118e553ad78b10324a5e45a3d9e9
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 DidAnticipatedDrawTimeChange(base::TimeTicks) override {
145 if (log_anticipated_draw_time_change_)
146 PushAction("DidAnticipatedDrawTimeChange");
148 base::TimeDelta DrawDurationEstimate() override { return base::TimeDelta(); }
149 base::TimeDelta BeginMainFrameToCommitDurationEstimate() override {
150 return base::TimeDelta();
152 base::TimeDelta CommitToActivateDurationEstimate() override {
153 return base::TimeDelta();
156 void DidBeginImplFrameDeadline() override {}
158 void SendBeginFramesToChildren(const BeginFrameArgs& args) override {
159 begin_frame_is_sent_to_children_ = true;
162 void SendBeginMainFrameNotExpectedSoon() override {
163 PushAction("SendBeginMainFrameNotExpectedSoon");
166 base::Callback<bool(void)> ImplFrameDeadlinePending(bool state) {
167 return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback,
168 base::Unretained(this),
169 state);
172 bool begin_frame_is_sent_to_children() const {
173 return begin_frame_is_sent_to_children_;
176 void PushAction(const char* description) {
177 actions_.push_back(description);
178 states_.push_back(scheduler_->AsValue());
181 protected:
182 bool ImplFrameDeadlinePendingCallback(bool state) {
183 return scheduler_->BeginImplFrameDeadlinePending() == state;
186 bool draw_will_happen_;
187 bool swap_will_happen_if_draw_happens_;
188 bool automatic_swap_ack_;
189 int num_draws_;
190 bool log_anticipated_draw_time_change_;
191 bool begin_frame_is_sent_to_children_;
192 base::TimeTicks posted_begin_impl_frame_deadline_;
193 std::vector<const char*> actions_;
194 std::vector<scoped_refptr<base::trace_event::ConvertableToTraceFormat>>
195 states_;
196 TestScheduler* scheduler_;
199 class FakeExternalBeginFrameSource : public BeginFrameSourceMixIn {
200 public:
201 explicit FakeExternalBeginFrameSource(FakeSchedulerClient* client)
202 : client_(client) {}
203 ~FakeExternalBeginFrameSource() override {}
205 void OnNeedsBeginFramesChange(bool needs_begin_frames) override {
206 if (needs_begin_frames) {
207 client_->PushAction("SetNeedsBeginFrames(true)");
208 } else {
209 client_->PushAction("SetNeedsBeginFrames(false)");
213 void TestOnBeginFrame(const BeginFrameArgs& args) {
214 return CallOnBeginFrame(args);
217 private:
218 FakeSchedulerClient* client_;
221 class SchedulerTest : public testing::Test {
222 public:
223 SchedulerTest()
224 : now_src_(TestNowSource::Create()),
225 task_runner_(new OrderedSimpleTaskRunner(now_src_, true)),
226 fake_external_begin_frame_source_(nullptr) {
227 // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval()
228 now_src_->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
229 // Fail if we need to run 100 tasks in a row.
230 task_runner_->SetRunTaskLimit(100);
233 ~SchedulerTest() override {}
235 protected:
236 TestScheduler* CreateScheduler() {
237 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source;
238 if (scheduler_settings_.use_external_begin_frame_source) {
239 fake_external_begin_frame_source.reset(
240 new FakeExternalBeginFrameSource(client_.get()));
241 fake_external_begin_frame_source_ =
242 fake_external_begin_frame_source.get();
244 scheduler_ = TestScheduler::Create(now_src_, client_.get(),
245 scheduler_settings_, 0, task_runner_,
246 fake_external_begin_frame_source.Pass());
247 DCHECK(scheduler_);
248 client_->set_scheduler(scheduler_.get());
249 return scheduler_.get();
252 void CreateSchedulerAndInitSurface() {
253 CreateScheduler();
254 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit());
257 void SetUpScheduler(bool initSurface) {
258 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient), initSurface);
261 void SetUpScheduler(scoped_ptr<FakeSchedulerClient> client,
262 bool initSurface) {
263 client_ = client.Pass();
264 if (initSurface)
265 CreateSchedulerAndInitSurface();
266 else
267 CreateScheduler();
270 OrderedSimpleTaskRunner& task_runner() { return *task_runner_; }
271 TestNowSource* now_src() { return now_src_.get(); }
273 // As this function contains EXPECT macros, to allow debugging it should be
274 // called inside EXPECT_SCOPED like so;
275 // EXPECT_SCOPED(client.InitializeOutputSurfaceAndFirstCommit(scheduler));
276 void InitializeOutputSurfaceAndFirstCommit() {
277 TRACE_EVENT0("cc",
278 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit");
279 DCHECK(scheduler_);
281 // Check the client doesn't have any actions queued when calling this
282 // function.
283 EXPECT_NO_ACTION(client_);
284 EXPECT_FALSE(client_->needs_begin_frames());
286 // Start the initial output surface creation.
287 EXPECT_FALSE(scheduler_->CanStart());
288 scheduler_->SetCanStart();
289 scheduler_->SetVisible(true);
290 scheduler_->SetCanDraw(true);
291 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
293 client_->Reset();
295 // We don't see anything happening until the first impl frame.
296 scheduler_->DidCreateAndInitializeOutputSurface();
297 scheduler_->SetNeedsCommit();
298 EXPECT_TRUE(client_->needs_begin_frames());
299 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
300 client_->Reset();
303 SCOPED_TRACE("Do first frame to commit after initialize.");
304 AdvanceFrame();
306 scheduler_->NotifyBeginMainFrameStarted();
307 scheduler_->NotifyReadyToCommitThenActivateIfNeeded();
309 // Run the posted deadline task.
310 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
311 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
312 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
314 EXPECT_FALSE(scheduler_->CommitPending());
317 client_->Reset();
320 SCOPED_TRACE(
321 "Run second frame so Scheduler calls SetNeedsBeginFrame(false).");
322 AdvanceFrame();
324 // Run the posted deadline task.
325 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
326 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
327 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
330 EXPECT_FALSE(client_->needs_begin_frames());
331 client_->Reset();
334 // As this function contains EXPECT macros, to allow debugging it should be
335 // called inside EXPECT_SCOPED like so;
336 // EXPECT_SCOPED(client.AdvanceFrame());
337 void AdvanceFrame() {
338 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
339 "FakeSchedulerClient::AdvanceFrame");
340 // Consume any previous deadline first, if no deadline is currently
341 // pending, ImplFrameDeadlinePending will return false straight away and we
342 // will run no tasks.
343 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
344 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
346 // Send the next BeginFrame message if using an external source, otherwise
347 // it will be already in the task queue.
348 if (scheduler_->settings().use_external_begin_frame_source &&
349 scheduler_->FrameProductionThrottled()) {
350 SendNextBeginFrame();
351 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
354 // Then run tasks until new deadline is scheduled.
355 EXPECT_TRUE(
356 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(false)));
357 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
360 void SendNextBeginFrame() {
361 DCHECK(scheduler_->settings().use_external_begin_frame_source);
362 // Creep the time forward so that any BeginFrameArgs is not equal to the
363 // last one otherwise we violate the BeginFrameSource contract.
364 now_src_->AdvanceNow(BeginFrameArgs::DefaultInterval());
365 fake_external_begin_frame_source_->TestOnBeginFrame(
366 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()));
369 FakeExternalBeginFrameSource* fake_external_begin_frame_source() const {
370 return fake_external_begin_frame_source_;
373 void MainFrameInHighLatencyMode(
374 int64 begin_main_frame_to_commit_estimate_in_ms,
375 int64 commit_to_activate_estimate_in_ms,
376 bool impl_latency_takes_priority,
377 bool should_send_begin_main_frame);
378 void BeginFramesNotFromClient(bool use_external_begin_frame_source,
379 bool throttle_frame_production);
380 void BeginFramesNotFromClient_SwapThrottled(
381 bool use_external_begin_frame_source,
382 bool throttle_frame_production);
383 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
384 bool impl_side_painting);
385 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting);
387 scoped_refptr<TestNowSource> now_src_;
388 scoped_refptr<OrderedSimpleTaskRunner> task_runner_;
389 FakeExternalBeginFrameSource* fake_external_begin_frame_source_;
390 SchedulerSettings scheduler_settings_;
391 scoped_ptr<FakeSchedulerClient> client_;
392 scoped_ptr<TestScheduler> scheduler_;
395 TEST_F(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) {
396 scheduler_settings_.use_external_begin_frame_source = true;
397 SetUpScheduler(false);
398 scheduler_->SetCanStart();
399 scheduler_->SetVisible(true);
400 scheduler_->SetCanDraw(true);
402 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
403 client_->Reset();
404 scheduler_->DidCreateAndInitializeOutputSurface();
405 EXPECT_NO_ACTION(client_);
408 TEST_F(SchedulerTest, SendBeginFramesToChildren) {
409 scheduler_settings_.use_external_begin_frame_source = true;
410 SetUpScheduler(true);
412 EXPECT_FALSE(client_->begin_frame_is_sent_to_children());
413 scheduler_->SetNeedsCommit();
414 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
415 EXPECT_TRUE(client_->needs_begin_frames());
417 scheduler_->SetChildrenNeedBeginFrames(true);
419 client_->Reset();
420 EXPECT_SCOPED(AdvanceFrame());
421 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
422 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
423 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
424 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
425 EXPECT_TRUE(client_->needs_begin_frames());
428 TEST_F(SchedulerTest, SendBeginFramesToChildrenWithoutCommit) {
429 scheduler_settings_.use_external_begin_frame_source = true;
430 SetUpScheduler(true);
432 EXPECT_FALSE(client_->needs_begin_frames());
433 scheduler_->SetChildrenNeedBeginFrames(true);
434 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
435 EXPECT_TRUE(client_->needs_begin_frames());
437 client_->Reset();
438 EXPECT_SCOPED(AdvanceFrame());
439 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
442 TEST_F(SchedulerTest, RequestCommit) {
443 scheduler_settings_.use_external_begin_frame_source = true;
444 SetUpScheduler(true);
446 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
447 scheduler_->SetNeedsCommit();
448 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
449 client_->Reset();
451 EXPECT_SCOPED(AdvanceFrame());
452 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
453 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
454 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
455 EXPECT_TRUE(client_->needs_begin_frames());
456 client_->Reset();
458 // If we don't swap on the deadline, we wait for the next BeginFrame.
459 task_runner().RunPendingTasks(); // Run posted deadline.
460 EXPECT_NO_ACTION(client_);
461 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
462 EXPECT_TRUE(client_->needs_begin_frames());
463 client_->Reset();
465 // NotifyReadyToCommit should trigger the commit.
466 scheduler_->NotifyBeginMainFrameStarted();
467 scheduler_->NotifyReadyToCommit();
468 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
469 EXPECT_TRUE(client_->needs_begin_frames());
470 client_->Reset();
472 // BeginImplFrame should prepare the draw.
473 EXPECT_SCOPED(AdvanceFrame());
474 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
475 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
476 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
477 EXPECT_TRUE(client_->needs_begin_frames());
478 client_->Reset();
480 // BeginImplFrame deadline should draw.
481 task_runner().RunPendingTasks(); // Run posted deadline.
482 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
483 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
484 EXPECT_TRUE(client_->needs_begin_frames());
485 client_->Reset();
487 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
488 // to avoid excessive toggles.
489 EXPECT_SCOPED(AdvanceFrame());
490 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
491 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
492 client_->Reset();
494 task_runner().RunPendingTasks(); // Run posted deadline.
495 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
496 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
497 client_->Reset();
500 TEST_F(SchedulerTest, RequestCommitAfterSetDeferCommit) {
501 scheduler_settings_.use_external_begin_frame_source = true;
502 SetUpScheduler(true);
504 scheduler_->SetDeferCommits(true);
506 scheduler_->SetNeedsCommit();
507 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
509 client_->Reset();
510 AdvanceFrame();
511 // BeginMainFrame is not sent during the defer commit is on.
512 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
514 client_->Reset();
515 task_runner().RunPendingTasks(); // Run posted deadline.
516 // There is no posted deadline.
517 EXPECT_NO_ACTION(client_);
518 EXPECT_TRUE(client_->needs_begin_frames());
520 client_->Reset();
521 scheduler_->SetDeferCommits(false);
522 EXPECT_NO_ACTION(client_);
524 // Start new BeginMainFrame after defer commit is off.
525 client_->Reset();
526 AdvanceFrame();
527 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
528 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
529 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
532 TEST_F(SchedulerTest, DeferCommitWithRedraw) {
533 scheduler_settings_.use_external_begin_frame_source = true;
534 SetUpScheduler(true);
536 scheduler_->SetDeferCommits(true);
538 scheduler_->SetNeedsCommit();
539 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
541 client_->Reset();
542 scheduler_->SetNeedsRedraw();
543 EXPECT_NO_ACTION(client_);
545 client_->Reset();
546 AdvanceFrame();
547 // BeginMainFrame is not sent during the defer commit is on.
548 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
549 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
551 client_->Reset();
552 task_runner().RunPendingTasks(); // Run posted deadline.
553 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
554 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
555 EXPECT_TRUE(client_->needs_begin_frames());
557 client_->Reset();
558 AdvanceFrame();
559 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
562 TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
563 scheduler_settings_.use_external_begin_frame_source = true;
564 SetUpScheduler(true);
566 // SetNeedsCommit should begin the frame.
567 scheduler_->SetNeedsCommit();
568 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
570 client_->Reset();
571 EXPECT_SCOPED(AdvanceFrame());
572 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
573 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
574 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
576 EXPECT_TRUE(client_->needs_begin_frames());
577 client_->Reset();
579 // Now SetNeedsCommit again. Calling here means we need a second commit.
580 scheduler_->SetNeedsCommit();
581 EXPECT_EQ(client_->num_actions_(), 0);
582 client_->Reset();
584 // Finish the first commit.
585 scheduler_->NotifyBeginMainFrameStarted();
586 scheduler_->NotifyReadyToCommit();
587 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
588 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
589 client_->Reset();
590 task_runner().RunPendingTasks(); // Run posted deadline.
591 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
592 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
593 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
595 // Because we just swapped, the Scheduler should also request the next
596 // BeginImplFrame from the OutputSurface.
597 EXPECT_TRUE(client_->needs_begin_frames());
598 client_->Reset();
599 // Since another commit is needed, the next BeginImplFrame should initiate
600 // the second commit.
601 EXPECT_SCOPED(AdvanceFrame());
602 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
603 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
604 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
605 client_->Reset();
607 // Finishing the commit before the deadline should post a new deadline task
608 // to trigger the deadline early.
609 scheduler_->NotifyBeginMainFrameStarted();
610 scheduler_->NotifyReadyToCommit();
611 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
612 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
613 client_->Reset();
614 task_runner().RunPendingTasks(); // Run posted deadline.
615 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
616 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
617 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
618 EXPECT_TRUE(client_->needs_begin_frames());
619 client_->Reset();
621 // On the next BeginImplFrame, verify we go back to a quiescent state and
622 // no longer request BeginImplFrames.
623 EXPECT_SCOPED(AdvanceFrame());
624 task_runner().RunPendingTasks(); // Run posted deadline.
625 EXPECT_FALSE(client_->needs_begin_frames());
626 client_->Reset();
629 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
630 public:
631 SchedulerClientThatsetNeedsDrawInsideDraw()
632 : FakeSchedulerClient(), request_redraws_(false) {}
634 void ScheduledActionSendBeginMainFrame() override {}
636 void SetRequestRedrawsInsideDraw(bool enable) { request_redraws_ = enable; }
638 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
639 // Only SetNeedsRedraw the first time this is called
640 if (request_redraws_) {
641 scheduler_->SetNeedsRedraw();
643 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
646 DrawResult ScheduledActionDrawAndSwapForced() override {
647 NOTREACHED();
648 return DRAW_SUCCESS;
651 void ScheduledActionCommit() override {}
652 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {}
654 private:
655 bool request_redraws_;
658 // Tests for two different situations:
659 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
660 // a ScheduledActionDrawAndSwap
661 // 2. the scheduler drawing twice inside a single tick
662 TEST_F(SchedulerTest, RequestRedrawInsideDraw) {
663 SchedulerClientThatsetNeedsDrawInsideDraw* client =
664 new SchedulerClientThatsetNeedsDrawInsideDraw;
665 scheduler_settings_.use_external_begin_frame_source = true;
666 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
667 client->SetRequestRedrawsInsideDraw(true);
669 scheduler_->SetNeedsRedraw();
670 EXPECT_TRUE(scheduler_->RedrawPending());
671 EXPECT_TRUE(client->needs_begin_frames());
672 EXPECT_EQ(0, client->num_draws());
674 EXPECT_SCOPED(AdvanceFrame());
675 task_runner().RunPendingTasks(); // Run posted deadline.
676 EXPECT_EQ(1, client->num_draws());
677 EXPECT_TRUE(scheduler_->RedrawPending());
678 EXPECT_TRUE(client->needs_begin_frames());
680 client->SetRequestRedrawsInsideDraw(false);
682 EXPECT_SCOPED(AdvanceFrame());
683 task_runner().RunPendingTasks(); // Run posted deadline.
684 EXPECT_EQ(2, client_->num_draws());
685 EXPECT_FALSE(scheduler_->RedrawPending());
686 EXPECT_TRUE(client->needs_begin_frames());
688 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
689 // swap.
690 EXPECT_SCOPED(AdvanceFrame());
691 task_runner().RunPendingTasks(); // Run posted deadline.
692 EXPECT_EQ(2, client->num_draws());
693 EXPECT_FALSE(scheduler_->RedrawPending());
694 EXPECT_FALSE(client->needs_begin_frames());
697 // Test that requesting redraw inside a failed draw doesn't lose the request.
698 TEST_F(SchedulerTest, RequestRedrawInsideFailedDraw) {
699 SchedulerClientThatsetNeedsDrawInsideDraw* client =
700 new SchedulerClientThatsetNeedsDrawInsideDraw;
701 scheduler_settings_.use_external_begin_frame_source = true;
702 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
704 client->SetRequestRedrawsInsideDraw(true);
705 client->SetDrawWillHappen(false);
707 scheduler_->SetNeedsRedraw();
708 EXPECT_TRUE(scheduler_->RedrawPending());
709 EXPECT_TRUE(client->needs_begin_frames());
710 EXPECT_EQ(0, client->num_draws());
712 // Fail the draw.
713 EXPECT_SCOPED(AdvanceFrame());
714 task_runner().RunPendingTasks(); // Run posted deadline.
715 EXPECT_EQ(1, client->num_draws());
717 // We have a commit pending and the draw failed, and we didn't lose the redraw
718 // request.
719 EXPECT_TRUE(scheduler_->CommitPending());
720 EXPECT_TRUE(scheduler_->RedrawPending());
721 EXPECT_TRUE(client->needs_begin_frames());
723 client->SetRequestRedrawsInsideDraw(false);
725 // Fail the draw again.
726 EXPECT_SCOPED(AdvanceFrame());
727 task_runner().RunPendingTasks(); // Run posted deadline.
728 EXPECT_EQ(2, client->num_draws());
729 EXPECT_TRUE(scheduler_->CommitPending());
730 EXPECT_TRUE(scheduler_->RedrawPending());
731 EXPECT_TRUE(client->needs_begin_frames());
733 // Draw successfully.
734 client->SetDrawWillHappen(true);
735 EXPECT_SCOPED(AdvanceFrame());
736 task_runner().RunPendingTasks(); // Run posted deadline.
737 EXPECT_EQ(3, client->num_draws());
738 EXPECT_TRUE(scheduler_->CommitPending());
739 EXPECT_FALSE(scheduler_->RedrawPending());
740 EXPECT_TRUE(client->needs_begin_frames());
743 class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
744 public:
745 SchedulerClientThatSetNeedsCommitInsideDraw()
746 : set_needs_commit_on_next_draw_(false) {}
748 void ScheduledActionSendBeginMainFrame() override {}
749 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
750 // Only SetNeedsCommit the first time this is called
751 if (set_needs_commit_on_next_draw_) {
752 scheduler_->SetNeedsCommit();
753 set_needs_commit_on_next_draw_ = false;
755 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
758 DrawResult ScheduledActionDrawAndSwapForced() override {
759 NOTREACHED();
760 return DRAW_SUCCESS;
763 void ScheduledActionCommit() override {}
764 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {}
766 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; }
768 private:
769 bool set_needs_commit_on_next_draw_;
772 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
773 // happen inside a ScheduledActionDrawAndSwap
774 TEST_F(SchedulerTest, RequestCommitInsideDraw) {
775 SchedulerClientThatSetNeedsCommitInsideDraw* client =
776 new SchedulerClientThatSetNeedsCommitInsideDraw;
778 scheduler_settings_.use_external_begin_frame_source = true;
779 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
781 EXPECT_FALSE(client->needs_begin_frames());
782 scheduler_->SetNeedsRedraw();
783 EXPECT_TRUE(scheduler_->RedrawPending());
784 EXPECT_EQ(0, client->num_draws());
785 EXPECT_TRUE(client->needs_begin_frames());
787 client->SetNeedsCommitOnNextDraw();
788 EXPECT_SCOPED(AdvanceFrame());
789 client->SetNeedsCommitOnNextDraw();
790 task_runner().RunPendingTasks(); // Run posted deadline.
791 EXPECT_EQ(1, client->num_draws());
792 EXPECT_TRUE(scheduler_->CommitPending());
793 EXPECT_TRUE(client->needs_begin_frames());
794 scheduler_->NotifyBeginMainFrameStarted();
795 scheduler_->NotifyReadyToCommit();
797 EXPECT_SCOPED(AdvanceFrame());
798 task_runner().RunPendingTasks(); // Run posted deadline.
799 EXPECT_EQ(2, client->num_draws());
801 EXPECT_FALSE(scheduler_->RedrawPending());
802 EXPECT_FALSE(scheduler_->CommitPending());
803 EXPECT_TRUE(client->needs_begin_frames());
805 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
806 // swap.
807 EXPECT_SCOPED(AdvanceFrame());
808 task_runner().RunPendingTasks(); // Run posted deadline.
809 EXPECT_EQ(2, client->num_draws());
810 EXPECT_FALSE(scheduler_->RedrawPending());
811 EXPECT_FALSE(scheduler_->CommitPending());
812 EXPECT_FALSE(client->needs_begin_frames());
815 // Tests that when a draw fails then the pending commit should not be dropped.
816 TEST_F(SchedulerTest, RequestCommitInsideFailedDraw) {
817 SchedulerClientThatsetNeedsDrawInsideDraw* client =
818 new SchedulerClientThatsetNeedsDrawInsideDraw;
819 scheduler_settings_.use_external_begin_frame_source = true;
820 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
822 client->SetDrawWillHappen(false);
824 scheduler_->SetNeedsRedraw();
825 EXPECT_TRUE(scheduler_->RedrawPending());
826 EXPECT_TRUE(client->needs_begin_frames());
827 EXPECT_EQ(0, client->num_draws());
829 // Fail the draw.
830 EXPECT_SCOPED(AdvanceFrame());
831 task_runner().RunPendingTasks(); // Run posted deadline.
832 EXPECT_EQ(1, client->num_draws());
834 // We have a commit pending and the draw failed, and we didn't lose the commit
835 // request.
836 EXPECT_TRUE(scheduler_->CommitPending());
837 EXPECT_TRUE(scheduler_->RedrawPending());
838 EXPECT_TRUE(client->needs_begin_frames());
840 // Fail the draw again.
841 EXPECT_SCOPED(AdvanceFrame());
843 task_runner().RunPendingTasks(); // Run posted deadline.
844 EXPECT_EQ(2, client->num_draws());
845 EXPECT_TRUE(scheduler_->CommitPending());
846 EXPECT_TRUE(scheduler_->RedrawPending());
847 EXPECT_TRUE(client->needs_begin_frames());
849 // Draw successfully.
850 client->SetDrawWillHappen(true);
851 EXPECT_SCOPED(AdvanceFrame());
852 task_runner().RunPendingTasks(); // Run posted deadline.
853 EXPECT_EQ(3, client->num_draws());
854 EXPECT_TRUE(scheduler_->CommitPending());
855 EXPECT_FALSE(scheduler_->RedrawPending());
856 EXPECT_TRUE(client->needs_begin_frames());
859 TEST_F(SchedulerTest, NoSwapWhenDrawFails) {
860 SchedulerClientThatSetNeedsCommitInsideDraw* client =
861 new SchedulerClientThatSetNeedsCommitInsideDraw;
862 scheduler_settings_.use_external_begin_frame_source = true;
863 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
865 scheduler_->SetNeedsRedraw();
866 EXPECT_TRUE(scheduler_->RedrawPending());
867 EXPECT_TRUE(client->needs_begin_frames());
868 EXPECT_EQ(0, client->num_draws());
870 // Draw successfully, this starts a new frame.
871 client->SetNeedsCommitOnNextDraw();
872 EXPECT_SCOPED(AdvanceFrame());
873 task_runner().RunPendingTasks(); // Run posted deadline.
874 EXPECT_EQ(1, client->num_draws());
876 scheduler_->SetNeedsRedraw();
877 EXPECT_TRUE(scheduler_->RedrawPending());
878 EXPECT_TRUE(client->needs_begin_frames());
880 // Fail to draw, this should not start a frame.
881 client->SetDrawWillHappen(false);
882 client->SetNeedsCommitOnNextDraw();
883 EXPECT_SCOPED(AdvanceFrame());
884 task_runner().RunPendingTasks(); // Run posted deadline.
885 EXPECT_EQ(2, client->num_draws());
888 class SchedulerClientNeedsPrepareTilesInDraw : public FakeSchedulerClient {
889 public:
890 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
891 scheduler_->SetNeedsPrepareTiles();
892 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
896 // Test prepare tiles is independant of draws.
897 TEST_F(SchedulerTest, PrepareTiles) {
898 SchedulerClientNeedsPrepareTilesInDraw* client =
899 new SchedulerClientNeedsPrepareTilesInDraw;
900 scheduler_settings_.use_external_begin_frame_source = true;
901 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
903 // Request both draw and prepare tiles. PrepareTiles shouldn't
904 // be trigged until BeginImplFrame.
905 client->Reset();
906 scheduler_->SetNeedsPrepareTiles();
907 scheduler_->SetNeedsRedraw();
908 EXPECT_TRUE(scheduler_->RedrawPending());
909 EXPECT_TRUE(scheduler_->PrepareTilesPending());
910 EXPECT_TRUE(client->needs_begin_frames());
911 EXPECT_EQ(0, client->num_draws());
912 EXPECT_FALSE(client->HasAction("ScheduledActionPrepareTiles"));
913 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
915 // We have no immediate actions to perform, so the BeginImplFrame should post
916 // the deadline task.
917 client->Reset();
918 EXPECT_SCOPED(AdvanceFrame());
919 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
920 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
921 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
923 // On the deadline, he actions should have occured in the right order.
924 client->Reset();
925 task_runner().RunPendingTasks(); // Run posted deadline.
926 EXPECT_EQ(1, client->num_draws());
927 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
928 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
929 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
930 client->ActionIndex("ScheduledActionPrepareTiles"));
931 EXPECT_FALSE(scheduler_->RedrawPending());
932 EXPECT_FALSE(scheduler_->PrepareTilesPending());
933 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
935 // Request a draw. We don't need a PrepareTiles yet.
936 client->Reset();
937 scheduler_->SetNeedsRedraw();
938 EXPECT_TRUE(scheduler_->RedrawPending());
939 EXPECT_FALSE(scheduler_->PrepareTilesPending());
940 EXPECT_TRUE(client->needs_begin_frames());
941 EXPECT_EQ(0, client->num_draws());
943 // We have no immediate actions to perform, so the BeginImplFrame should post
944 // the deadline task.
945 client->Reset();
946 EXPECT_SCOPED(AdvanceFrame());
947 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
948 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
949 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
951 // Draw. The draw will trigger SetNeedsPrepareTiles, and
952 // then the PrepareTiles action will be triggered after the Draw.
953 // Afterwards, neither a draw nor PrepareTiles are pending.
954 client->Reset();
955 task_runner().RunPendingTasks(); // Run posted deadline.
956 EXPECT_EQ(1, client->num_draws());
957 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
958 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
959 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
960 client->ActionIndex("ScheduledActionPrepareTiles"));
961 EXPECT_FALSE(scheduler_->RedrawPending());
962 EXPECT_FALSE(scheduler_->PrepareTilesPending());
963 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
965 // We need a BeginImplFrame where we don't swap to go idle.
966 client->Reset();
967 EXPECT_SCOPED(AdvanceFrame());
968 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
969 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
970 client->Reset();
971 task_runner().RunPendingTasks(); // Run posted deadline.
972 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
973 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
974 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
975 EXPECT_EQ(0, client->num_draws());
977 // Now trigger a PrepareTiles outside of a draw. We will then need
978 // a begin-frame for the PrepareTiles, but we don't need a draw.
979 client->Reset();
980 EXPECT_FALSE(client->needs_begin_frames());
981 scheduler_->SetNeedsPrepareTiles();
982 EXPECT_TRUE(client->needs_begin_frames());
983 EXPECT_TRUE(scheduler_->PrepareTilesPending());
984 EXPECT_FALSE(scheduler_->RedrawPending());
986 // BeginImplFrame. There will be no draw, only PrepareTiles.
987 client->Reset();
988 EXPECT_SCOPED(AdvanceFrame());
989 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
990 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
991 client->Reset();
992 task_runner().RunPendingTasks(); // Run posted deadline.
993 EXPECT_EQ(0, client->num_draws());
994 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
995 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
996 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
999 // Test that PrepareTiles only happens once per frame. If an external caller
1000 // initiates it, then the state machine should not PrepareTiles on that frame.
1001 TEST_F(SchedulerTest, PrepareTilesOncePerFrame) {
1002 scheduler_settings_.use_external_begin_frame_source = true;
1003 SetUpScheduler(true);
1005 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
1006 // again.
1007 scheduler_->SetNeedsPrepareTiles();
1008 scheduler_->SetNeedsRedraw();
1009 client_->Reset();
1010 EXPECT_SCOPED(AdvanceFrame());
1011 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1012 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1013 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1015 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1016 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1017 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1019 client_->Reset();
1020 task_runner().RunPendingTasks(); // Run posted deadline.
1021 EXPECT_EQ(1, client_->num_draws());
1022 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1023 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1024 EXPECT_FALSE(scheduler_->RedrawPending());
1025 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1026 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1028 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1029 scheduler_->SetNeedsPrepareTiles();
1030 scheduler_->SetNeedsRedraw();
1031 client_->Reset();
1032 EXPECT_SCOPED(AdvanceFrame());
1033 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1034 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1035 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1037 client_->Reset();
1038 task_runner().RunPendingTasks(); // Run posted deadline.
1039 EXPECT_EQ(1, client_->num_draws());
1040 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1041 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1042 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1043 client_->ActionIndex("ScheduledActionPrepareTiles"));
1044 EXPECT_FALSE(scheduler_->RedrawPending());
1045 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1046 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1047 scheduler_->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1049 // If we get another DidPrepareTiles within the same frame, we should
1050 // not PrepareTiles on the next frame.
1051 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1052 scheduler_->SetNeedsPrepareTiles();
1053 scheduler_->SetNeedsRedraw();
1054 client_->Reset();
1055 EXPECT_SCOPED(AdvanceFrame());
1056 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1057 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1058 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1060 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1062 client_->Reset();
1063 task_runner().RunPendingTasks(); // Run posted deadline.
1064 EXPECT_EQ(1, client_->num_draws());
1065 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1066 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1067 EXPECT_FALSE(scheduler_->RedrawPending());
1068 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1070 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1071 // frame. This verifies we don't alternate calling PrepareTiles once and
1072 // twice.
1073 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1074 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1075 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1076 scheduler_->SetNeedsPrepareTiles();
1077 scheduler_->SetNeedsRedraw();
1078 client_->Reset();
1079 EXPECT_SCOPED(AdvanceFrame());
1080 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1081 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1082 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1084 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1086 client_->Reset();
1087 task_runner().RunPendingTasks(); // Run posted deadline.
1088 EXPECT_EQ(1, client_->num_draws());
1089 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1090 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1091 EXPECT_FALSE(scheduler_->RedrawPending());
1092 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1094 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1095 scheduler_->SetNeedsPrepareTiles();
1096 scheduler_->SetNeedsRedraw();
1097 client_->Reset();
1098 EXPECT_SCOPED(AdvanceFrame());
1099 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1100 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1101 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1103 client_->Reset();
1104 task_runner().RunPendingTasks(); // Run posted deadline.
1105 EXPECT_EQ(1, client_->num_draws());
1106 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1107 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1108 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1109 client_->ActionIndex("ScheduledActionPrepareTiles"));
1110 EXPECT_FALSE(scheduler_->RedrawPending());
1111 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1112 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1113 scheduler_->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1116 TEST_F(SchedulerTest, TriggerBeginFrameDeadlineEarly) {
1117 SchedulerClientNeedsPrepareTilesInDraw* client =
1118 new SchedulerClientNeedsPrepareTilesInDraw;
1119 scheduler_settings_.use_external_begin_frame_source = true;
1120 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1122 scheduler_->SetNeedsRedraw();
1123 EXPECT_SCOPED(AdvanceFrame());
1125 // The deadline should be zero since there is no work other than drawing
1126 // pending.
1127 EXPECT_EQ(base::TimeTicks(), client->posted_begin_impl_frame_deadline());
1130 class SchedulerClientWithFixedEstimates : public FakeSchedulerClient {
1131 public:
1132 SchedulerClientWithFixedEstimates(
1133 base::TimeDelta draw_duration,
1134 base::TimeDelta begin_main_frame_to_commit_duration,
1135 base::TimeDelta commit_to_activate_duration)
1136 : draw_duration_(draw_duration),
1137 begin_main_frame_to_commit_duration_(
1138 begin_main_frame_to_commit_duration),
1139 commit_to_activate_duration_(commit_to_activate_duration) {}
1141 base::TimeDelta DrawDurationEstimate() override { return draw_duration_; }
1142 base::TimeDelta BeginMainFrameToCommitDurationEstimate() override {
1143 return begin_main_frame_to_commit_duration_;
1145 base::TimeDelta CommitToActivateDurationEstimate() override {
1146 return commit_to_activate_duration_;
1149 private:
1150 base::TimeDelta draw_duration_;
1151 base::TimeDelta begin_main_frame_to_commit_duration_;
1152 base::TimeDelta commit_to_activate_duration_;
1155 void SchedulerTest::MainFrameInHighLatencyMode(
1156 int64 begin_main_frame_to_commit_estimate_in_ms,
1157 int64 commit_to_activate_estimate_in_ms,
1158 bool impl_latency_takes_priority,
1159 bool should_send_begin_main_frame) {
1160 // Set up client with specified estimates (draw duration is set to 1).
1161 SchedulerClientWithFixedEstimates* client =
1162 new SchedulerClientWithFixedEstimates(
1163 base::TimeDelta::FromMilliseconds(1),
1164 base::TimeDelta::FromMilliseconds(
1165 begin_main_frame_to_commit_estimate_in_ms),
1166 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms));
1168 scheduler_settings_.use_external_begin_frame_source = true;
1169 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1171 scheduler_->SetImplLatencyTakesPriority(impl_latency_takes_priority);
1173 // Impl thread hits deadline before commit finishes.
1174 scheduler_->SetNeedsCommit();
1175 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1176 EXPECT_SCOPED(AdvanceFrame());
1177 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1178 task_runner().RunPendingTasks(); // Run posted deadline.
1179 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1180 scheduler_->NotifyBeginMainFrameStarted();
1181 scheduler_->NotifyReadyToCommit();
1182 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1183 EXPECT_TRUE(client->HasAction("ScheduledActionSendBeginMainFrame"));
1185 client->Reset();
1186 scheduler_->SetNeedsCommit();
1187 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1188 EXPECT_SCOPED(AdvanceFrame());
1189 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1190 task_runner().RunPendingTasks(); // Run posted deadline.
1191 EXPECT_EQ(scheduler_->MainThreadIsInHighLatencyMode(),
1192 should_send_begin_main_frame);
1193 EXPECT_EQ(client->HasAction("ScheduledActionSendBeginMainFrame"),
1194 should_send_begin_main_frame);
1197 TEST_F(SchedulerTest,
1198 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) {
1199 // Set up client so that estimates indicate that we can commit and activate
1200 // before the deadline (~8ms by default).
1201 MainFrameInHighLatencyMode(1, 1, false, false);
1204 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) {
1205 // Set up client so that estimates indicate that the commit cannot finish
1206 // before the deadline (~8ms by default).
1207 MainFrameInHighLatencyMode(10, 1, false, true);
1210 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) {
1211 // Set up client so that estimates indicate that the activate cannot finish
1212 // before the deadline (~8ms by default).
1213 MainFrameInHighLatencyMode(1, 10, false, true);
1216 TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) {
1217 // Set up client so that estimates indicate that we can commit and activate
1218 // before the deadline (~8ms by default), but also enable impl latency takes
1219 // priority mode.
1220 MainFrameInHighLatencyMode(1, 1, true, true);
1223 TEST_F(SchedulerTest, PollForCommitCompletion) {
1224 // Since we are simulating a long commit, set up a client with draw duration
1225 // estimates that prevent skipping main frames to get to low latency mode.
1226 SchedulerClientWithFixedEstimates* client =
1227 new SchedulerClientWithFixedEstimates(
1228 base::TimeDelta::FromMilliseconds(1),
1229 base::TimeDelta::FromMilliseconds(32),
1230 base::TimeDelta::FromMilliseconds(32));
1231 scheduler_settings_.use_external_begin_frame_source = true;
1232 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1234 client->set_log_anticipated_draw_time_change(true);
1236 BeginFrameArgs frame_args =
1237 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
1238 frame_args.interval = base::TimeDelta::FromMilliseconds(1000);
1240 // At this point, we've drawn a frame. Start another commit, but hold off on
1241 // the NotifyReadyToCommit for now.
1242 EXPECT_FALSE(scheduler_->CommitPending());
1243 scheduler_->SetNeedsCommit();
1244 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args);
1245 EXPECT_TRUE(scheduler_->CommitPending());
1247 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1248 // blocking on the renderer.
1249 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1250 task_runner().RunPendingTasks(); // Run posted deadline.
1251 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1252 scheduler_->DidSwapBuffers();
1254 // Spin the event loop a few times and make sure we get more
1255 // DidAnticipateDrawTimeChange calls every time.
1256 int actions_so_far = client->num_actions_();
1258 // Does three iterations to make sure that the timer is properly repeating.
1259 for (int i = 0; i < 3; ++i) {
1260 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1261 task_runner().DelayToNextTaskTime().InMicroseconds())
1262 << scheduler_->AsValue()->ToString();
1263 task_runner().RunPendingTasks();
1264 EXPECT_GT(client->num_actions_(), actions_so_far);
1265 EXPECT_STREQ(client->Action(client->num_actions_() - 1),
1266 "DidAnticipatedDrawTimeChange");
1267 actions_so_far = client->num_actions_();
1270 // Do the same thing after BeginMainFrame starts but still before activation.
1271 scheduler_->NotifyBeginMainFrameStarted();
1272 for (int i = 0; i < 3; ++i) {
1273 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1274 task_runner().DelayToNextTaskTime().InMicroseconds())
1275 << scheduler_->AsValue()->ToString();
1276 task_runner().RunPendingTasks();
1277 EXPECT_GT(client->num_actions_(), actions_so_far);
1278 EXPECT_STREQ(client->Action(client->num_actions_() - 1),
1279 "DidAnticipatedDrawTimeChange");
1280 actions_so_far = client->num_actions_();
1284 TEST_F(SchedulerTest, BeginRetroFrame) {
1285 scheduler_settings_.use_external_begin_frame_source = true;
1286 SetUpScheduler(true);
1288 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1289 scheduler_->SetNeedsCommit();
1290 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1291 client_->Reset();
1293 // Create a BeginFrame with a long deadline to avoid race conditions.
1294 // This is the first BeginFrame, which will be handled immediately.
1295 BeginFrameArgs args =
1296 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
1297 args.deadline += base::TimeDelta::FromHours(1);
1298 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1299 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1300 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1301 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1302 EXPECT_TRUE(client_->needs_begin_frames());
1303 client_->Reset();
1305 // Queue BeginFrames while we are still handling the previous BeginFrame.
1306 args.frame_time += base::TimeDelta::FromSeconds(1);
1307 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1308 args.frame_time += base::TimeDelta::FromSeconds(1);
1309 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1311 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1312 task_runner().RunPendingTasks(); // Run posted deadline.
1313 EXPECT_NO_ACTION(client_);
1314 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1315 EXPECT_TRUE(client_->needs_begin_frames());
1316 client_->Reset();
1318 // NotifyReadyToCommit should trigger the commit.
1319 scheduler_->NotifyBeginMainFrameStarted();
1320 scheduler_->NotifyReadyToCommit();
1321 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1322 EXPECT_TRUE(client_->needs_begin_frames());
1323 client_->Reset();
1325 // BeginImplFrame should prepare the draw.
1326 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1327 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1328 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1329 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1330 EXPECT_TRUE(client_->needs_begin_frames());
1331 client_->Reset();
1333 // BeginImplFrame deadline should draw.
1334 task_runner().RunPendingTasks(); // Run posted deadline.
1335 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
1336 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1337 EXPECT_TRUE(client_->needs_begin_frames());
1338 client_->Reset();
1340 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1341 // to avoid excessive toggles.
1342 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1343 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
1344 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1345 client_->Reset();
1347 task_runner().RunPendingTasks(); // Run posted deadline.
1348 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1349 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1350 client_->Reset();
1353 TEST_F(SchedulerTest, BeginRetroFrame_SwapThrottled) {
1354 scheduler_settings_.use_external_begin_frame_source = true;
1355 SetUpScheduler(true);
1357 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1359 // To test swap ack throttling, this test disables automatic swap acks.
1360 scheduler_->SetMaxSwapsPending(1);
1361 client_->SetAutomaticSwapAck(false);
1363 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1364 client_->Reset();
1365 scheduler_->SetNeedsCommit();
1366 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1367 client_->Reset();
1369 EXPECT_SCOPED(AdvanceFrame());
1370 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1371 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1372 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1373 EXPECT_TRUE(client_->needs_begin_frames());
1374 client_->Reset();
1376 // Queue BeginFrame while we are still handling the previous BeginFrame.
1377 SendNextBeginFrame();
1378 EXPECT_NO_ACTION(client_);
1379 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1380 EXPECT_TRUE(client_->needs_begin_frames());
1381 client_->Reset();
1383 // NotifyReadyToCommit should trigger the pending commit and draw.
1384 scheduler_->NotifyBeginMainFrameStarted();
1385 scheduler_->NotifyReadyToCommit();
1386 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1387 EXPECT_TRUE(client_->needs_begin_frames());
1388 client_->Reset();
1390 // Swapping will put us into a swap throttled state.
1391 // Run posted deadline.
1392 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1393 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1394 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1395 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1396 EXPECT_TRUE(client_->needs_begin_frames());
1397 client_->Reset();
1399 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1400 // but not a BeginMainFrame or draw.
1401 scheduler_->SetNeedsCommit();
1402 scheduler_->SetNeedsRedraw();
1403 // Run posted BeginRetroFrame.
1404 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
1405 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1406 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1407 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1408 EXPECT_TRUE(client_->needs_begin_frames());
1409 client_->Reset();
1411 // Let time pass sufficiently beyond the regular deadline but not beyond the
1412 // late deadline.
1413 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1414 base::TimeDelta::FromMicroseconds(1));
1415 task_runner().RunUntilTime(now_src()->Now());
1416 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1418 // Take us out of a swap throttled state.
1419 scheduler_->DidSwapBuffersComplete();
1420 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
1421 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1422 EXPECT_TRUE(client_->needs_begin_frames());
1423 client_->Reset();
1425 // Verify that the deadline was rescheduled.
1426 task_runner().RunUntilTime(now_src()->Now());
1427 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
1428 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1429 EXPECT_TRUE(client_->needs_begin_frames());
1430 client_->Reset();
1433 TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooEarly) {
1434 scheduler_settings_.use_external_begin_frame_source = true;
1435 SetUpScheduler(true);
1437 scheduler_->SetNeedsCommit();
1438 EXPECT_TRUE(client_->needs_begin_frames());
1439 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1441 client_->Reset();
1442 EXPECT_SCOPED(AdvanceFrame());
1443 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1444 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1445 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1447 client_->Reset();
1448 scheduler_->NotifyBeginMainFrameStarted();
1450 client_->Reset();
1451 SendNextBeginFrame();
1452 // This BeginFrame is queued up as a retro frame.
1453 EXPECT_NO_ACTION(client_);
1454 // The previous deadline is still pending.
1455 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1457 client_->Reset();
1458 // This commit should schedule the (previous) deadline to trigger immediately.
1459 scheduler_->NotifyReadyToCommit();
1460 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1462 client_->Reset();
1463 // The deadline task should trigger causing a draw.
1464 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1465 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1466 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1467 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1469 // Keep animating.
1470 client_->Reset();
1471 scheduler_->SetNeedsAnimate();
1472 scheduler_->SetNeedsRedraw();
1473 EXPECT_NO_ACTION(client_);
1475 // Let's advance sufficiently past the next frame's deadline.
1476 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1477 BeginFrameArgs::DefaultEstimatedParentDrawTime() +
1478 base::TimeDelta::FromMicroseconds(1));
1480 // The retro frame hasn't expired yet.
1481 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
1482 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1483 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1484 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1486 // This is an immediate deadline case.
1487 client_->Reset();
1488 task_runner().RunPendingTasks();
1489 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1490 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
1493 TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooLate) {
1494 scheduler_settings_.use_external_begin_frame_source = true;
1495 SetUpScheduler(true);
1497 scheduler_->SetNeedsCommit();
1498 EXPECT_TRUE(client_->needs_begin_frames());
1499 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1501 client_->Reset();
1502 EXPECT_SCOPED(AdvanceFrame());
1503 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1504 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1505 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1507 client_->Reset();
1508 scheduler_->NotifyBeginMainFrameStarted();
1510 client_->Reset();
1511 SendNextBeginFrame();
1512 // This BeginFrame is queued up as a retro frame.
1513 EXPECT_NO_ACTION(client_);
1514 // The previous deadline is still pending.
1515 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1517 client_->Reset();
1518 // This commit should schedule the (previous) deadline to trigger immediately.
1519 scheduler_->NotifyReadyToCommit();
1520 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1522 client_->Reset();
1523 // The deadline task should trigger causing a draw.
1524 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1525 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1526 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1527 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1529 // Keep animating.
1530 client_->Reset();
1531 scheduler_->SetNeedsAnimate();
1532 scheduler_->SetNeedsRedraw();
1533 EXPECT_NO_ACTION(client_);
1535 // Let's advance sufficiently past the next frame's deadline.
1536 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() +
1537 base::TimeDelta::FromMicroseconds(1));
1539 // The retro frame should've expired.
1540 EXPECT_NO_ACTION(client_);
1543 void SchedulerTest::BeginFramesNotFromClient(
1544 bool use_external_begin_frame_source,
1545 bool throttle_frame_production) {
1546 scheduler_settings_.use_external_begin_frame_source =
1547 use_external_begin_frame_source;
1548 scheduler_settings_.throttle_frame_production = throttle_frame_production;
1549 SetUpScheduler(true);
1551 // SetNeedsCommit should begin the frame on the next BeginImplFrame
1552 // without calling SetNeedsBeginFrame.
1553 scheduler_->SetNeedsCommit();
1554 EXPECT_NO_ACTION(client_);
1555 client_->Reset();
1557 // When the client-driven BeginFrame are disabled, the scheduler posts it's
1558 // own BeginFrame tasks.
1559 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1560 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1561 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1562 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1563 client_->Reset();
1565 // If we don't swap on the deadline, we wait for the next BeginFrame.
1566 task_runner().RunPendingTasks(); // Run posted deadline.
1567 EXPECT_NO_ACTION(client_);
1568 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1569 client_->Reset();
1571 // NotifyReadyToCommit should trigger the commit.
1572 scheduler_->NotifyBeginMainFrameStarted();
1573 scheduler_->NotifyReadyToCommit();
1574 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1575 client_->Reset();
1577 // BeginImplFrame should prepare the draw.
1578 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1579 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1580 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1581 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1582 client_->Reset();
1584 // BeginImplFrame deadline should draw.
1585 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1586 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
1587 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1588 client_->Reset();
1590 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1591 // to avoid excessive toggles.
1592 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1593 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
1594 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1595 client_->Reset();
1597 // Make sure SetNeedsBeginFrame isn't called on the client
1598 // when the BeginFrame is no longer needed.
1599 task_runner().RunPendingTasks(); // Run posted deadline.
1600 EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_);
1601 client_->Reset();
1604 TEST_F(SchedulerTest, SyntheticBeginFrames) {
1605 bool use_external_begin_frame_source = false;
1606 bool throttle_frame_production = true;
1607 BeginFramesNotFromClient(use_external_begin_frame_source,
1608 throttle_frame_production);
1611 TEST_F(SchedulerTest, VSyncThrottlingDisabled) {
1612 bool use_external_begin_frame_source = true;
1613 bool throttle_frame_production = false;
1614 BeginFramesNotFromClient(use_external_begin_frame_source,
1615 throttle_frame_production);
1618 TEST_F(SchedulerTest, SyntheticBeginFrames_And_VSyncThrottlingDisabled) {
1619 bool use_external_begin_frame_source = false;
1620 bool throttle_frame_production = false;
1621 BeginFramesNotFromClient(use_external_begin_frame_source,
1622 throttle_frame_production);
1625 void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
1626 bool use_external_begin_frame_source,
1627 bool throttle_frame_production) {
1628 scheduler_settings_.use_external_begin_frame_source =
1629 use_external_begin_frame_source;
1630 scheduler_settings_.throttle_frame_production = throttle_frame_production;
1631 SetUpScheduler(true);
1633 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1635 // To test swap ack throttling, this test disables automatic swap acks.
1636 scheduler_->SetMaxSwapsPending(1);
1637 client_->SetAutomaticSwapAck(false);
1639 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1640 client_->Reset();
1641 scheduler_->SetNeedsCommit();
1642 EXPECT_NO_ACTION(client_);
1643 client_->Reset();
1645 // Trigger the first BeginImplFrame and BeginMainFrame
1646 EXPECT_SCOPED(AdvanceFrame());
1647 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1648 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1649 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1650 client_->Reset();
1652 // NotifyReadyToCommit should trigger the pending commit and draw.
1653 scheduler_->NotifyBeginMainFrameStarted();
1654 scheduler_->NotifyReadyToCommit();
1655 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1656 client_->Reset();
1658 // Swapping will put us into a swap throttled state.
1659 // Run posted deadline.
1660 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1661 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1662 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1663 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1664 client_->Reset();
1666 // While swap throttled, BeginFrames should trigger BeginImplFrames,
1667 // but not a BeginMainFrame or draw.
1668 scheduler_->SetNeedsCommit();
1669 scheduler_->SetNeedsRedraw();
1670 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
1671 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1672 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1673 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1674 client_->Reset();
1676 // Let time pass sufficiently beyond the regular deadline but not beyond the
1677 // late deadline.
1678 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1679 base::TimeDelta::FromMicroseconds(1));
1680 task_runner().RunUntilTime(now_src()->Now());
1681 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1683 // Take us out of a swap throttled state.
1684 scheduler_->DidSwapBuffersComplete();
1685 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
1686 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1687 client_->Reset();
1689 // Verify that the deadline was rescheduled.
1690 // We can't use RunUntilTime(now) here because the next frame is also
1691 // scheduled if throttle_frame_production = false.
1692 base::TimeTicks before_deadline = now_src()->Now();
1693 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1694 base::TimeTicks after_deadline = now_src()->Now();
1695 EXPECT_EQ(after_deadline, before_deadline);
1696 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1697 client_->Reset();
1700 TEST_F(SchedulerTest, SyntheticBeginFrames_SwapThrottled) {
1701 bool use_external_begin_frame_source = false;
1702 bool throttle_frame_production = true;
1703 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
1704 throttle_frame_production);
1707 TEST_F(SchedulerTest, VSyncThrottlingDisabled_SwapThrottled) {
1708 bool use_external_begin_frame_source = true;
1709 bool throttle_frame_production = false;
1710 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
1711 throttle_frame_production);
1714 TEST_F(SchedulerTest,
1715 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled) {
1716 bool use_external_begin_frame_source = false;
1717 bool throttle_frame_production = false;
1718 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
1719 throttle_frame_production);
1722 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized) {
1723 scheduler_settings_.use_external_begin_frame_source = true;
1724 SetUpScheduler(false);
1726 scheduler_->SetCanStart();
1727 scheduler_->SetVisible(true);
1728 scheduler_->SetCanDraw(true);
1730 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
1731 client_->Reset();
1732 scheduler_->DidCreateAndInitializeOutputSurface();
1733 EXPECT_NO_ACTION(client_);
1735 scheduler_->DidLoseOutputSurface();
1736 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
1739 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) {
1740 scheduler_settings_.use_external_begin_frame_source = true;
1741 SetUpScheduler(true);
1743 // SetNeedsCommit should begin the frame.
1744 scheduler_->SetNeedsCommit();
1745 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1747 client_->Reset();
1748 EXPECT_SCOPED(AdvanceFrame());
1749 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1750 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1751 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1753 client_->Reset();
1754 scheduler_->DidLoseOutputSurface();
1755 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1756 EXPECT_NO_ACTION(client_);
1758 client_->Reset();
1759 scheduler_->NotifyBeginMainFrameStarted();
1760 scheduler_->NotifyReadyToCommit();
1761 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 1);
1763 client_->Reset();
1764 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1765 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
1766 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
1767 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
1770 void SchedulerTest::DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
1771 bool impl_side_painting) {
1772 scheduler_settings_.impl_side_painting = impl_side_painting;
1773 scheduler_settings_.use_external_begin_frame_source = true;
1774 SetUpScheduler(true);
1776 // SetNeedsCommit should begin the frame.
1777 scheduler_->SetNeedsCommit();
1778 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1780 client_->Reset();
1781 EXPECT_SCOPED(AdvanceFrame());
1782 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1783 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1784 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1786 client_->Reset();
1787 scheduler_->DidLoseOutputSurface();
1788 // Do nothing when impl frame is in deadine pending state.
1789 EXPECT_NO_ACTION(client_);
1791 client_->Reset();
1792 // Run posted deadline.
1793 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1794 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1795 // OnBeginImplFrameDeadline didn't schedule output surface creation because
1796 // main frame is not yet completed.
1797 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1798 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1799 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1801 // BeginImplFrame is not started.
1802 client_->Reset();
1803 task_runner().RunUntilTime(now_src()->Now() +
1804 base::TimeDelta::FromMilliseconds(10));
1805 EXPECT_NO_ACTION(client_);
1806 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1808 client_->Reset();
1809 scheduler_->NotifyBeginMainFrameStarted();
1810 scheduler_->NotifyReadyToCommit();
1811 if (impl_side_painting) {
1812 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 3);
1813 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 3);
1814 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 2, 3);
1815 } else {
1816 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2);
1817 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 2);
1821 TEST_F(SchedulerTest,
1822 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) {
1823 bool impl_side_painting = false;
1824 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
1827 TEST_F(SchedulerTest,
1828 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint) {
1829 bool impl_side_painting = true;
1830 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
1833 void SchedulerTest::DidLoseOutputSurfaceAfterReadyToCommit(
1834 bool impl_side_painting) {
1835 scheduler_settings_.impl_side_painting = impl_side_painting;
1836 scheduler_settings_.use_external_begin_frame_source = true;
1837 SetUpScheduler(true);
1839 // SetNeedsCommit should begin the frame.
1840 scheduler_->SetNeedsCommit();
1841 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1843 client_->Reset();
1844 EXPECT_SCOPED(AdvanceFrame());
1845 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1846 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1847 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1849 client_->Reset();
1850 scheduler_->NotifyBeginMainFrameStarted();
1851 scheduler_->NotifyReadyToCommit();
1852 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1854 client_->Reset();
1855 scheduler_->DidLoseOutputSurface();
1856 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1857 if (impl_side_painting) {
1858 // Sync tree should be forced to activate.
1859 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
1860 } else {
1861 EXPECT_NO_ACTION(client_);
1864 client_->Reset();
1865 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1866 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
1867 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
1868 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
1871 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) {
1872 DidLoseOutputSurfaceAfterReadyToCommit(false);
1875 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting) {
1876 DidLoseOutputSurfaceAfterReadyToCommit(true);
1879 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles) {
1880 scheduler_settings_.use_external_begin_frame_source = true;
1881 SetUpScheduler(true);
1883 scheduler_->SetNeedsPrepareTiles();
1884 scheduler_->SetNeedsRedraw();
1885 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1887 client_->Reset();
1888 EXPECT_SCOPED(AdvanceFrame());
1889 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1890 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1891 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1893 client_->Reset();
1894 scheduler_->DidLoseOutputSurface();
1895 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1896 EXPECT_NO_ACTION(client_);
1898 client_->Reset();
1899 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1900 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 0, 4);
1901 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 4);
1902 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 2, 4);
1903 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 3, 4);
1906 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) {
1907 scheduler_settings_.use_external_begin_frame_source = true;
1908 SetUpScheduler(true);
1910 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1911 scheduler_->SetNeedsCommit();
1912 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1914 // Create a BeginFrame with a long deadline to avoid race conditions.
1915 // This is the first BeginFrame, which will be handled immediately.
1916 client_->Reset();
1917 BeginFrameArgs args =
1918 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
1919 args.deadline += base::TimeDelta::FromHours(1);
1920 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1921 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1922 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1923 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1924 EXPECT_TRUE(client_->needs_begin_frames());
1926 // Queue BeginFrames while we are still handling the previous BeginFrame.
1927 args.frame_time += base::TimeDelta::FromSeconds(1);
1928 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1929 args.frame_time += base::TimeDelta::FromSeconds(1);
1930 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1932 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1933 client_->Reset();
1934 task_runner().RunPendingTasks(); // Run posted deadline.
1935 EXPECT_NO_ACTION(client_);
1936 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1937 EXPECT_TRUE(client_->needs_begin_frames());
1939 // NotifyReadyToCommit should trigger the commit.
1940 client_->Reset();
1941 scheduler_->NotifyBeginMainFrameStarted();
1942 scheduler_->NotifyReadyToCommit();
1943 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1944 EXPECT_TRUE(client_->needs_begin_frames());
1946 client_->Reset();
1947 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty());
1948 scheduler_->DidLoseOutputSurface();
1949 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
1950 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
1951 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
1952 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty());
1954 // Posted BeginRetroFrame is aborted.
1955 client_->Reset();
1956 task_runner().RunPendingTasks();
1957 EXPECT_NO_ACTION(client_);
1960 TEST_F(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) {
1961 scheduler_settings_.use_external_begin_frame_source = true;
1962 SetUpScheduler(true);
1964 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1965 scheduler_->SetNeedsCommit();
1966 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1968 // Create a BeginFrame with a long deadline to avoid race conditions.
1969 // This is the first BeginFrame, which will be handled immediately.
1970 client_->Reset();
1971 BeginFrameArgs args =
1972 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
1973 args.deadline += base::TimeDelta::FromHours(1);
1974 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1975 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1976 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1977 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1978 EXPECT_TRUE(client_->needs_begin_frames());
1980 // Queue BeginFrames while we are still handling the previous BeginFrame.
1981 args.frame_time += base::TimeDelta::FromSeconds(1);
1982 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1983 args.frame_time += base::TimeDelta::FromSeconds(1);
1984 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1986 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1987 client_->Reset();
1988 task_runner().RunPendingTasks(); // Run posted deadline.
1989 EXPECT_NO_ACTION(client_);
1990 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1991 EXPECT_TRUE(client_->needs_begin_frames());
1993 // NotifyReadyToCommit should trigger the commit.
1994 client_->Reset();
1995 scheduler_->NotifyBeginMainFrameStarted();
1996 scheduler_->NotifyReadyToCommit();
1997 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1998 EXPECT_TRUE(client_->needs_begin_frames());
2000 // BeginImplFrame should prepare the draw.
2001 client_->Reset();
2002 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2003 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2004 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2005 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2006 EXPECT_TRUE(client_->needs_begin_frames());
2008 client_->Reset();
2009 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty());
2010 scheduler_->DidLoseOutputSurface();
2011 EXPECT_NO_ACTION(client_);
2012 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty());
2014 // BeginImplFrame deadline should abort drawing.
2015 client_->Reset();
2016 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2017 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2018 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2019 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2020 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2021 EXPECT_FALSE(client_->needs_begin_frames());
2023 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
2024 client_->Reset();
2025 task_runner().RunPendingTasks();
2026 EXPECT_NO_ACTION(client_);
2029 TEST_F(SchedulerTest, DidLoseOutputSurfaceWithSyntheticBeginFrameSource) {
2030 SetUpScheduler(true);
2032 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2033 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2034 scheduler_->SetNeedsCommit();
2035 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2037 client_->Reset();
2038 AdvanceFrame();
2039 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2040 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2041 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2042 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2044 // NotifyReadyToCommit should trigger the commit.
2045 client_->Reset();
2046 scheduler_->NotifyBeginMainFrameStarted();
2047 scheduler_->NotifyReadyToCommit();
2048 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2049 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2051 client_->Reset();
2052 scheduler_->DidLoseOutputSurface();
2053 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2054 EXPECT_NO_ACTION(client_);
2055 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2057 client_->Reset();
2058 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2059 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 2);
2060 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2061 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2064 TEST_F(SchedulerTest, DidLoseOutputSurfaceWhenIdle) {
2065 scheduler_settings_.use_external_begin_frame_source = true;
2066 SetUpScheduler(true);
2068 // SetNeedsCommit should begin the frame.
2069 scheduler_->SetNeedsCommit();
2070 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2072 client_->Reset();
2073 EXPECT_SCOPED(AdvanceFrame());
2074 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2075 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2076 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2078 client_->Reset();
2079 scheduler_->NotifyBeginMainFrameStarted();
2080 scheduler_->NotifyReadyToCommit();
2081 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2083 client_->Reset();
2084 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2085 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2086 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2088 // Idle time between BeginFrames.
2089 client_->Reset();
2090 scheduler_->DidLoseOutputSurface();
2091 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2092 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2093 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2096 TEST_F(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) {
2097 scheduler_settings_.impl_side_painting = true;
2098 scheduler_settings_.use_external_begin_frame_source = true;
2099 SetUpScheduler(true);
2101 // SetNeedsCommit should begin the frame.
2102 scheduler_->SetNeedsCommit();
2103 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2105 client_->Reset();
2106 EXPECT_SCOPED(AdvanceFrame());
2107 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2108 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2109 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2111 client_->Reset();
2112 scheduler_->NotifyBeginMainFrameStarted();
2113 scheduler_->NotifyReadyToCommit();
2114 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2116 client_->Reset();
2117 scheduler_->SetVisible(false);
2118 // Sync tree should be forced to activate.
2119 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
2120 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2);
2123 // Tests to ensure frame sources can be successfully changed while drawing.
2124 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottled) {
2125 scheduler_settings_.use_external_begin_frame_source = true;
2126 SetUpScheduler(true);
2128 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2129 scheduler_->SetNeedsRedraw();
2130 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2131 client_->Reset();
2133 EXPECT_SCOPED(AdvanceFrame());
2134 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2135 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2136 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2137 EXPECT_TRUE(client_->needs_begin_frames());
2138 client_->Reset();
2139 task_runner().RunPendingTasks(); // Run posted deadline.
2140 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2141 scheduler_->SetNeedsRedraw();
2143 // Switch to an unthrottled frame source.
2144 scheduler_->SetThrottleFrameProduction(false);
2145 client_->Reset();
2147 // Unthrottled frame source will immediately begin a new frame.
2148 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2149 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2150 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2151 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2152 client_->Reset();
2154 // If we don't swap on the deadline, we wait for the next BeginFrame.
2155 task_runner().RunPendingTasks(); // Run posted deadline.
2156 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2157 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2158 client_->Reset();
2161 // Tests to ensure frame sources can be successfully changed while a frame
2162 // deadline is pending.
2163 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottledBeforeDeadline) {
2164 scheduler_settings_.use_external_begin_frame_source = true;
2165 SetUpScheduler(true);
2167 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2168 scheduler_->SetNeedsRedraw();
2169 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2170 client_->Reset();
2172 EXPECT_SCOPED(AdvanceFrame());
2173 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2174 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2176 // Switch to an unthrottled frame source before the frame deadline is hit.
2177 scheduler_->SetThrottleFrameProduction(false);
2178 client_->Reset();
2180 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2181 EXPECT_TRUE(client_->needs_begin_frames());
2182 client_->Reset();
2184 task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame.
2185 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
2186 // Unthrottled frame source will immediately begin a new frame.
2187 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 2);
2188 scheduler_->SetNeedsRedraw();
2189 client_->Reset();
2191 task_runner().RunPendingTasks(); // Run posted deadline.
2192 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2193 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2194 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2195 client_->Reset();
2198 // Tests to ensure that the active frame source can successfully be changed from
2199 // unthrottled to throttled.
2200 TEST_F(SchedulerTest, SwitchFrameSourceToThrottled) {
2201 scheduler_settings_.throttle_frame_production = false;
2202 scheduler_settings_.use_external_begin_frame_source = true;
2203 SetUpScheduler(true);
2205 scheduler_->SetNeedsRedraw();
2206 EXPECT_NO_ACTION(client_);
2207 client_->Reset();
2209 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2210 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2211 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2212 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2213 client_->Reset();
2215 task_runner().RunPendingTasks(); // Run posted deadline.
2216 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2217 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2218 client_->Reset();
2220 // Switch to a throttled frame source.
2221 scheduler_->SetThrottleFrameProduction(true);
2222 client_->Reset();
2224 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2225 scheduler_->SetNeedsRedraw();
2226 task_runner().RunPendingTasks();
2227 EXPECT_NO_ACTION(client_);
2228 client_->Reset();
2230 EXPECT_SCOPED(AdvanceFrame());
2231 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2232 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2233 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2234 EXPECT_TRUE(client_->needs_begin_frames());
2235 client_->Reset();
2236 task_runner().RunPendingTasks(); // Run posted deadline.
2237 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2240 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
2241 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon) {
2242 scheduler_settings_.use_external_begin_frame_source = true;
2243 SetUpScheduler(true);
2245 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2246 scheduler_->SetNeedsCommit();
2247 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2248 client_->Reset();
2250 // Trigger a frame draw.
2251 EXPECT_SCOPED(AdvanceFrame());
2252 scheduler_->NotifyBeginMainFrameStarted();
2253 scheduler_->NotifyReadyToCommit();
2254 task_runner().RunPendingTasks();
2255 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 5);
2256 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 5);
2257 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 5);
2258 EXPECT_ACTION("ScheduledActionAnimate", client_, 3, 5);
2259 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 5);
2260 client_->Reset();
2262 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2263 // and send a SendBeginMainFrameNotExpectedSoon.
2264 EXPECT_SCOPED(AdvanceFrame());
2265 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
2266 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2267 client_->Reset();
2269 task_runner().RunPendingTasks(); // Run posted deadline.
2270 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
2271 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2272 client_->Reset();
2275 TEST_F(SchedulerTest, AuthoritativeVSyncInterval) {
2276 SetUpScheduler(true);
2278 base::TimeDelta initial_interval =
2279 scheduler_->begin_impl_frame_args().interval;
2280 base::TimeDelta authoritative_interval =
2281 base::TimeDelta::FromMilliseconds(33);
2283 scheduler_->SetNeedsCommit();
2284 EXPECT_SCOPED(AdvanceFrame());
2286 EXPECT_EQ(initial_interval, scheduler_->begin_impl_frame_args().interval);
2288 scheduler_->NotifyBeginMainFrameStarted();
2289 scheduler_->NotifyReadyToCommit();
2290 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2292 scheduler_->SetAuthoritativeVSyncInterval(authoritative_interval);
2294 EXPECT_SCOPED(AdvanceFrame());
2296 // At the next BeginFrame, authoritative interval is used instead of previous
2297 // interval.
2298 EXPECT_NE(initial_interval, scheduler_->begin_impl_frame_args().interval);
2299 EXPECT_EQ(authoritative_interval,
2300 scheduler_->begin_impl_frame_args().interval);
2303 } // namespace
2304 } // namespace cc