Roll src/third_party/WebKit d26421b:4b1dbe3 (svn 194839:194840)
[chromium-blink-merge.git] / cc / scheduler / scheduler_unittest.cc
blobc03c79b05b8f0c7ce1f4b708036dfe5371aa8ad4
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, VideoNeedsBeginFrames) {
458 scheduler_settings_.use_external_begin_frame_source = true;
459 SetUpScheduler(true);
461 scheduler_->SetVideoNeedsBeginFrames(true);
462 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
463 EXPECT_TRUE(client_->needs_begin_frames());
465 client_->Reset();
466 EXPECT_SCOPED(AdvanceFrame());
467 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
468 // WillBeginImplFrame is responsible for sending BeginFrames to video.
469 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
471 client_->Reset();
472 EXPECT_SCOPED(AdvanceFrame());
473 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
474 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
476 client_->Reset();
477 scheduler_->SetVideoNeedsBeginFrames(false);
478 EXPECT_NO_ACTION(client_);
480 client_->Reset();
481 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
482 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
483 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
484 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
485 EXPECT_FALSE(client_->needs_begin_frames());
488 TEST_F(SchedulerTest, RequestCommit) {
489 scheduler_settings_.use_external_begin_frame_source = true;
490 SetUpScheduler(true);
492 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
493 scheduler_->SetNeedsCommit();
494 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
495 client_->Reset();
497 EXPECT_SCOPED(AdvanceFrame());
498 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
499 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
500 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
501 EXPECT_TRUE(client_->needs_begin_frames());
502 client_->Reset();
504 // If we don't swap on the deadline, we wait for the next BeginFrame.
505 task_runner().RunPendingTasks(); // Run posted deadline.
506 EXPECT_NO_ACTION(client_);
507 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
508 EXPECT_TRUE(client_->needs_begin_frames());
509 client_->Reset();
511 // NotifyReadyToCommit should trigger the commit.
512 scheduler_->NotifyBeginMainFrameStarted();
513 scheduler_->NotifyReadyToCommit();
514 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
515 EXPECT_TRUE(client_->needs_begin_frames());
516 client_->Reset();
518 // BeginImplFrame should prepare the draw.
519 EXPECT_SCOPED(AdvanceFrame());
520 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
521 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
522 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
523 EXPECT_TRUE(client_->needs_begin_frames());
524 client_->Reset();
526 // BeginImplFrame deadline should draw.
527 task_runner().RunPendingTasks(); // Run posted deadline.
528 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
529 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
530 EXPECT_TRUE(client_->needs_begin_frames());
531 client_->Reset();
533 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
534 // to avoid excessive toggles.
535 EXPECT_SCOPED(AdvanceFrame());
536 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
537 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
538 client_->Reset();
540 task_runner().RunPendingTasks(); // Run posted deadline.
541 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
542 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
543 client_->Reset();
546 TEST_F(SchedulerTest, RequestCommitAfterSetDeferCommit) {
547 scheduler_settings_.use_external_begin_frame_source = true;
548 SetUpScheduler(true);
550 scheduler_->SetDeferCommits(true);
552 scheduler_->SetNeedsCommit();
553 EXPECT_NO_ACTION(client_);
555 client_->Reset();
556 task_runner().RunPendingTasks();
557 // There are no pending tasks or actions.
558 EXPECT_NO_ACTION(client_);
559 EXPECT_FALSE(client_->needs_begin_frames());
561 client_->Reset();
562 scheduler_->SetDeferCommits(false);
563 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
565 // Start new BeginMainFrame after defer commit is off.
566 client_->Reset();
567 EXPECT_SCOPED(AdvanceFrame());
568 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
569 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
570 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
573 TEST_F(SchedulerTest, DeferCommitWithRedraw) {
574 scheduler_settings_.use_external_begin_frame_source = true;
575 SetUpScheduler(true);
577 scheduler_->SetDeferCommits(true);
579 scheduler_->SetNeedsCommit();
580 EXPECT_NO_ACTION(client_);
582 // The SetNeedsRedraw will override the SetDeferCommits(true), to allow a
583 // begin frame to be needed.
584 client_->Reset();
585 scheduler_->SetNeedsRedraw();
586 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
588 client_->Reset();
589 AdvanceFrame();
590 // BeginMainFrame is not sent during the defer commit is on.
591 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
592 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
594 client_->Reset();
595 task_runner().RunPendingTasks(); // Run posted deadline.
596 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
597 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
598 EXPECT_TRUE(client_->needs_begin_frames());
600 client_->Reset();
601 AdvanceFrame();
602 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
605 TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
606 scheduler_settings_.use_external_begin_frame_source = true;
607 SetUpScheduler(true);
609 // SetNeedsCommit should begin the frame.
610 scheduler_->SetNeedsCommit();
611 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
613 client_->Reset();
614 EXPECT_SCOPED(AdvanceFrame());
615 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
616 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
617 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
619 EXPECT_TRUE(client_->needs_begin_frames());
620 client_->Reset();
622 // Now SetNeedsCommit again. Calling here means we need a second commit.
623 scheduler_->SetNeedsCommit();
624 EXPECT_EQ(client_->num_actions_(), 0);
625 client_->Reset();
627 // Finish the first commit.
628 scheduler_->NotifyBeginMainFrameStarted();
629 scheduler_->NotifyReadyToCommit();
630 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
631 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
632 client_->Reset();
633 task_runner().RunPendingTasks(); // Run posted deadline.
634 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
635 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
636 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
638 // Because we just swapped, the Scheduler should also request the next
639 // BeginImplFrame from the OutputSurface.
640 EXPECT_TRUE(client_->needs_begin_frames());
641 client_->Reset();
642 // Since another commit is needed, the next BeginImplFrame should initiate
643 // the second commit.
644 EXPECT_SCOPED(AdvanceFrame());
645 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
646 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
647 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
648 client_->Reset();
650 // Finishing the commit before the deadline should post a new deadline task
651 // to trigger the deadline early.
652 scheduler_->NotifyBeginMainFrameStarted();
653 scheduler_->NotifyReadyToCommit();
654 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
655 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
656 client_->Reset();
657 task_runner().RunPendingTasks(); // Run posted deadline.
658 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
659 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
660 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
661 EXPECT_TRUE(client_->needs_begin_frames());
662 client_->Reset();
664 // On the next BeginImplFrame, verify we go back to a quiescent state and
665 // no longer request BeginImplFrames.
666 EXPECT_SCOPED(AdvanceFrame());
667 task_runner().RunPendingTasks(); // Run posted deadline.
668 EXPECT_FALSE(client_->needs_begin_frames());
669 client_->Reset();
672 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
673 public:
674 SchedulerClientThatsetNeedsDrawInsideDraw()
675 : FakeSchedulerClient(), request_redraws_(false) {}
677 void ScheduledActionSendBeginMainFrame() override {}
679 void SetRequestRedrawsInsideDraw(bool enable) { request_redraws_ = enable; }
681 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
682 // Only SetNeedsRedraw the first time this is called
683 if (request_redraws_) {
684 scheduler_->SetNeedsRedraw();
686 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
689 DrawResult ScheduledActionDrawAndSwapForced() override {
690 NOTREACHED();
691 return DRAW_SUCCESS;
694 void ScheduledActionCommit() override {}
695 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {}
697 private:
698 bool request_redraws_;
701 // Tests for two different situations:
702 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
703 // a ScheduledActionDrawAndSwap
704 // 2. the scheduler drawing twice inside a single tick
705 TEST_F(SchedulerTest, RequestRedrawInsideDraw) {
706 SchedulerClientThatsetNeedsDrawInsideDraw* client =
707 new SchedulerClientThatsetNeedsDrawInsideDraw;
708 scheduler_settings_.use_external_begin_frame_source = true;
709 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
710 client->SetRequestRedrawsInsideDraw(true);
712 scheduler_->SetNeedsRedraw();
713 EXPECT_TRUE(scheduler_->RedrawPending());
714 EXPECT_TRUE(client->needs_begin_frames());
715 EXPECT_EQ(0, client->num_draws());
717 EXPECT_SCOPED(AdvanceFrame());
718 task_runner().RunPendingTasks(); // Run posted deadline.
719 EXPECT_EQ(1, client->num_draws());
720 EXPECT_TRUE(scheduler_->RedrawPending());
721 EXPECT_TRUE(client->needs_begin_frames());
723 client->SetRequestRedrawsInsideDraw(false);
725 EXPECT_SCOPED(AdvanceFrame());
726 task_runner().RunPendingTasks(); // Run posted deadline.
727 EXPECT_EQ(2, client_->num_draws());
728 EXPECT_FALSE(scheduler_->RedrawPending());
729 EXPECT_TRUE(client->needs_begin_frames());
731 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
732 // swap.
733 EXPECT_SCOPED(AdvanceFrame());
734 task_runner().RunPendingTasks(); // Run posted deadline.
735 EXPECT_EQ(2, client->num_draws());
736 EXPECT_FALSE(scheduler_->RedrawPending());
737 EXPECT_FALSE(client->needs_begin_frames());
740 // Test that requesting redraw inside a failed draw doesn't lose the request.
741 TEST_F(SchedulerTest, RequestRedrawInsideFailedDraw) {
742 SchedulerClientThatsetNeedsDrawInsideDraw* client =
743 new SchedulerClientThatsetNeedsDrawInsideDraw;
744 scheduler_settings_.use_external_begin_frame_source = true;
745 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
747 client->SetRequestRedrawsInsideDraw(true);
748 client->SetDrawWillHappen(false);
750 scheduler_->SetNeedsRedraw();
751 EXPECT_TRUE(scheduler_->RedrawPending());
752 EXPECT_TRUE(client->needs_begin_frames());
753 EXPECT_EQ(0, client->num_draws());
755 // Fail the draw.
756 EXPECT_SCOPED(AdvanceFrame());
757 task_runner().RunPendingTasks(); // Run posted deadline.
758 EXPECT_EQ(1, client->num_draws());
760 // We have a commit pending and the draw failed, and we didn't lose the redraw
761 // request.
762 EXPECT_TRUE(scheduler_->CommitPending());
763 EXPECT_TRUE(scheduler_->RedrawPending());
764 EXPECT_TRUE(client->needs_begin_frames());
766 client->SetRequestRedrawsInsideDraw(false);
768 // Fail the draw again.
769 EXPECT_SCOPED(AdvanceFrame());
770 task_runner().RunPendingTasks(); // Run posted deadline.
771 EXPECT_EQ(2, client->num_draws());
772 EXPECT_TRUE(scheduler_->CommitPending());
773 EXPECT_TRUE(scheduler_->RedrawPending());
774 EXPECT_TRUE(client->needs_begin_frames());
776 // Draw successfully.
777 client->SetDrawWillHappen(true);
778 EXPECT_SCOPED(AdvanceFrame());
779 task_runner().RunPendingTasks(); // Run posted deadline.
780 EXPECT_EQ(3, client->num_draws());
781 EXPECT_TRUE(scheduler_->CommitPending());
782 EXPECT_FALSE(scheduler_->RedrawPending());
783 EXPECT_TRUE(client->needs_begin_frames());
786 class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
787 public:
788 SchedulerClientThatSetNeedsCommitInsideDraw()
789 : set_needs_commit_on_next_draw_(false) {}
791 void ScheduledActionSendBeginMainFrame() override {}
792 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
793 // Only SetNeedsCommit the first time this is called
794 if (set_needs_commit_on_next_draw_) {
795 scheduler_->SetNeedsCommit();
796 set_needs_commit_on_next_draw_ = false;
798 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
801 DrawResult ScheduledActionDrawAndSwapForced() override {
802 NOTREACHED();
803 return DRAW_SUCCESS;
806 void ScheduledActionCommit() override {}
807 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {}
809 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; }
811 private:
812 bool set_needs_commit_on_next_draw_;
815 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
816 // happen inside a ScheduledActionDrawAndSwap
817 TEST_F(SchedulerTest, RequestCommitInsideDraw) {
818 SchedulerClientThatSetNeedsCommitInsideDraw* client =
819 new SchedulerClientThatSetNeedsCommitInsideDraw;
821 scheduler_settings_.use_external_begin_frame_source = true;
822 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
824 EXPECT_FALSE(client->needs_begin_frames());
825 scheduler_->SetNeedsRedraw();
826 EXPECT_TRUE(scheduler_->RedrawPending());
827 EXPECT_EQ(0, client->num_draws());
828 EXPECT_TRUE(client->needs_begin_frames());
830 client->SetNeedsCommitOnNextDraw();
831 EXPECT_SCOPED(AdvanceFrame());
832 client->SetNeedsCommitOnNextDraw();
833 task_runner().RunPendingTasks(); // Run posted deadline.
834 EXPECT_EQ(1, client->num_draws());
835 EXPECT_TRUE(scheduler_->CommitPending());
836 EXPECT_TRUE(client->needs_begin_frames());
837 scheduler_->NotifyBeginMainFrameStarted();
838 scheduler_->NotifyReadyToCommit();
840 EXPECT_SCOPED(AdvanceFrame());
841 task_runner().RunPendingTasks(); // Run posted deadline.
842 EXPECT_EQ(2, client->num_draws());
844 EXPECT_FALSE(scheduler_->RedrawPending());
845 EXPECT_FALSE(scheduler_->CommitPending());
846 EXPECT_TRUE(client->needs_begin_frames());
848 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
849 // swap.
850 EXPECT_SCOPED(AdvanceFrame());
851 task_runner().RunPendingTasks(); // Run posted deadline.
852 EXPECT_EQ(2, client->num_draws());
853 EXPECT_FALSE(scheduler_->RedrawPending());
854 EXPECT_FALSE(scheduler_->CommitPending());
855 EXPECT_FALSE(client->needs_begin_frames());
858 // Tests that when a draw fails then the pending commit should not be dropped.
859 TEST_F(SchedulerTest, RequestCommitInsideFailedDraw) {
860 SchedulerClientThatsetNeedsDrawInsideDraw* client =
861 new SchedulerClientThatsetNeedsDrawInsideDraw;
862 scheduler_settings_.use_external_begin_frame_source = true;
863 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
865 client->SetDrawWillHappen(false);
867 scheduler_->SetNeedsRedraw();
868 EXPECT_TRUE(scheduler_->RedrawPending());
869 EXPECT_TRUE(client->needs_begin_frames());
870 EXPECT_EQ(0, client->num_draws());
872 // Fail the draw.
873 EXPECT_SCOPED(AdvanceFrame());
874 task_runner().RunPendingTasks(); // Run posted deadline.
875 EXPECT_EQ(1, client->num_draws());
877 // We have a commit pending and the draw failed, and we didn't lose the commit
878 // request.
879 EXPECT_TRUE(scheduler_->CommitPending());
880 EXPECT_TRUE(scheduler_->RedrawPending());
881 EXPECT_TRUE(client->needs_begin_frames());
883 // Fail the draw again.
884 EXPECT_SCOPED(AdvanceFrame());
886 task_runner().RunPendingTasks(); // Run posted deadline.
887 EXPECT_EQ(2, client->num_draws());
888 EXPECT_TRUE(scheduler_->CommitPending());
889 EXPECT_TRUE(scheduler_->RedrawPending());
890 EXPECT_TRUE(client->needs_begin_frames());
892 // Draw successfully.
893 client->SetDrawWillHappen(true);
894 EXPECT_SCOPED(AdvanceFrame());
895 task_runner().RunPendingTasks(); // Run posted deadline.
896 EXPECT_EQ(3, client->num_draws());
897 EXPECT_TRUE(scheduler_->CommitPending());
898 EXPECT_FALSE(scheduler_->RedrawPending());
899 EXPECT_TRUE(client->needs_begin_frames());
902 TEST_F(SchedulerTest, NoSwapWhenDrawFails) {
903 SchedulerClientThatSetNeedsCommitInsideDraw* client =
904 new SchedulerClientThatSetNeedsCommitInsideDraw;
905 scheduler_settings_.use_external_begin_frame_source = true;
906 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
908 scheduler_->SetNeedsRedraw();
909 EXPECT_TRUE(scheduler_->RedrawPending());
910 EXPECT_TRUE(client->needs_begin_frames());
911 EXPECT_EQ(0, client->num_draws());
913 // Draw successfully, this starts a new frame.
914 client->SetNeedsCommitOnNextDraw();
915 EXPECT_SCOPED(AdvanceFrame());
916 task_runner().RunPendingTasks(); // Run posted deadline.
917 EXPECT_EQ(1, client->num_draws());
919 scheduler_->SetNeedsRedraw();
920 EXPECT_TRUE(scheduler_->RedrawPending());
921 EXPECT_TRUE(client->needs_begin_frames());
923 // Fail to draw, this should not start a frame.
924 client->SetDrawWillHappen(false);
925 client->SetNeedsCommitOnNextDraw();
926 EXPECT_SCOPED(AdvanceFrame());
927 task_runner().RunPendingTasks(); // Run posted deadline.
928 EXPECT_EQ(2, client->num_draws());
931 class SchedulerClientNeedsPrepareTilesInDraw : public FakeSchedulerClient {
932 public:
933 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
934 scheduler_->SetNeedsPrepareTiles();
935 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
939 // Test prepare tiles is independant of draws.
940 TEST_F(SchedulerTest, PrepareTiles) {
941 SchedulerClientNeedsPrepareTilesInDraw* client =
942 new SchedulerClientNeedsPrepareTilesInDraw;
943 scheduler_settings_.use_external_begin_frame_source = true;
944 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
946 // Request both draw and prepare tiles. PrepareTiles shouldn't
947 // be trigged until BeginImplFrame.
948 client->Reset();
949 scheduler_->SetNeedsPrepareTiles();
950 scheduler_->SetNeedsRedraw();
951 EXPECT_TRUE(scheduler_->RedrawPending());
952 EXPECT_TRUE(scheduler_->PrepareTilesPending());
953 EXPECT_TRUE(client->needs_begin_frames());
954 EXPECT_EQ(0, client->num_draws());
955 EXPECT_FALSE(client->HasAction("ScheduledActionPrepareTiles"));
956 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
958 // We have no immediate actions to perform, so the BeginImplFrame should post
959 // the deadline task.
960 client->Reset();
961 EXPECT_SCOPED(AdvanceFrame());
962 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
963 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
964 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
966 // On the deadline, he actions should have occured in the right order.
967 client->Reset();
968 task_runner().RunPendingTasks(); // Run posted deadline.
969 EXPECT_EQ(1, client->num_draws());
970 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
971 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
972 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
973 client->ActionIndex("ScheduledActionPrepareTiles"));
974 EXPECT_FALSE(scheduler_->RedrawPending());
975 EXPECT_FALSE(scheduler_->PrepareTilesPending());
976 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
978 // Request a draw. We don't need a PrepareTiles yet.
979 client->Reset();
980 scheduler_->SetNeedsRedraw();
981 EXPECT_TRUE(scheduler_->RedrawPending());
982 EXPECT_FALSE(scheduler_->PrepareTilesPending());
983 EXPECT_TRUE(client->needs_begin_frames());
984 EXPECT_EQ(0, client->num_draws());
986 // We have no immediate actions to perform, so the BeginImplFrame should post
987 // the deadline task.
988 client->Reset();
989 EXPECT_SCOPED(AdvanceFrame());
990 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
991 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
992 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
994 // Draw. The draw will trigger SetNeedsPrepareTiles, and
995 // then the PrepareTiles action will be triggered after the Draw.
996 // Afterwards, neither a draw nor PrepareTiles are pending.
997 client->Reset();
998 task_runner().RunPendingTasks(); // Run posted deadline.
999 EXPECT_EQ(1, client->num_draws());
1000 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1001 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1002 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1003 client->ActionIndex("ScheduledActionPrepareTiles"));
1004 EXPECT_FALSE(scheduler_->RedrawPending());
1005 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1006 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1008 // We need a BeginImplFrame where we don't swap to go idle.
1009 client->Reset();
1010 EXPECT_SCOPED(AdvanceFrame());
1011 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1012 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1013 client->Reset();
1014 task_runner().RunPendingTasks(); // Run posted deadline.
1015 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1016 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1017 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1018 EXPECT_EQ(0, client->num_draws());
1020 // Now trigger a PrepareTiles outside of a draw. We will then need
1021 // a begin-frame for the PrepareTiles, but we don't need a draw.
1022 client->Reset();
1023 EXPECT_FALSE(client->needs_begin_frames());
1024 scheduler_->SetNeedsPrepareTiles();
1025 EXPECT_TRUE(client->needs_begin_frames());
1026 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1027 EXPECT_FALSE(scheduler_->RedrawPending());
1029 // BeginImplFrame. There will be no draw, only PrepareTiles.
1030 client->Reset();
1031 EXPECT_SCOPED(AdvanceFrame());
1032 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1033 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1034 client->Reset();
1035 task_runner().RunPendingTasks(); // Run posted deadline.
1036 EXPECT_EQ(0, client->num_draws());
1037 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1038 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1039 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1042 // Test that PrepareTiles only happens once per frame. If an external caller
1043 // initiates it, then the state machine should not PrepareTiles on that frame.
1044 TEST_F(SchedulerTest, PrepareTilesOncePerFrame) {
1045 scheduler_settings_.use_external_begin_frame_source = true;
1046 SetUpScheduler(true);
1048 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
1049 // again.
1050 scheduler_->SetNeedsPrepareTiles();
1051 scheduler_->SetNeedsRedraw();
1052 client_->Reset();
1053 EXPECT_SCOPED(AdvanceFrame());
1054 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1055 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1056 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1058 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1059 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1060 EXPECT_FALSE(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_->PrepareTilesPending());
1069 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1071 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1072 scheduler_->SetNeedsPrepareTiles();
1073 scheduler_->SetNeedsRedraw();
1074 client_->Reset();
1075 EXPECT_SCOPED(AdvanceFrame());
1076 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1077 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1078 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1080 client_->Reset();
1081 task_runner().RunPendingTasks(); // Run posted deadline.
1082 EXPECT_EQ(1, client_->num_draws());
1083 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1084 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1085 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1086 client_->ActionIndex("ScheduledActionPrepareTiles"));
1087 EXPECT_FALSE(scheduler_->RedrawPending());
1088 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1089 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1090 scheduler_->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1092 // If we get another DidPrepareTiles within the same frame, we should
1093 // not PrepareTiles on the next frame.
1094 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
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 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1105 client_->Reset();
1106 task_runner().RunPendingTasks(); // Run posted deadline.
1107 EXPECT_EQ(1, client_->num_draws());
1108 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1109 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1110 EXPECT_FALSE(scheduler_->RedrawPending());
1111 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1113 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1114 // frame. This verifies we don't alternate calling PrepareTiles once and
1115 // twice.
1116 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1117 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1118 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1119 scheduler_->SetNeedsPrepareTiles();
1120 scheduler_->SetNeedsRedraw();
1121 client_->Reset();
1122 EXPECT_SCOPED(AdvanceFrame());
1123 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1124 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1125 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1127 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1129 client_->Reset();
1130 task_runner().RunPendingTasks(); // Run posted deadline.
1131 EXPECT_EQ(1, client_->num_draws());
1132 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1133 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1134 EXPECT_FALSE(scheduler_->RedrawPending());
1135 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1137 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1138 scheduler_->SetNeedsPrepareTiles();
1139 scheduler_->SetNeedsRedraw();
1140 client_->Reset();
1141 EXPECT_SCOPED(AdvanceFrame());
1142 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1143 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1144 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1146 client_->Reset();
1147 task_runner().RunPendingTasks(); // Run posted deadline.
1148 EXPECT_EQ(1, client_->num_draws());
1149 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1150 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1151 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1152 client_->ActionIndex("ScheduledActionPrepareTiles"));
1153 EXPECT_FALSE(scheduler_->RedrawPending());
1154 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1155 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1156 scheduler_->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1159 TEST_F(SchedulerTest, TriggerBeginFrameDeadlineEarly) {
1160 SchedulerClientNeedsPrepareTilesInDraw* client =
1161 new SchedulerClientNeedsPrepareTilesInDraw;
1162 scheduler_settings_.use_external_begin_frame_source = true;
1163 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1165 scheduler_->SetNeedsRedraw();
1166 EXPECT_SCOPED(AdvanceFrame());
1168 // The deadline should be zero since there is no work other than drawing
1169 // pending.
1170 EXPECT_EQ(base::TimeTicks(), client->posted_begin_impl_frame_deadline());
1173 TEST_F(SchedulerTest, WaitForReadyToDrawDoNotPostDeadline) {
1174 SchedulerClientNeedsPrepareTilesInDraw* client =
1175 new SchedulerClientNeedsPrepareTilesInDraw;
1176 scheduler_settings_.use_external_begin_frame_source = true;
1177 scheduler_settings_.impl_side_painting = true;
1178 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1180 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1181 scheduler_->SetNeedsCommit();
1182 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1183 client_->Reset();
1185 // Begin new frame.
1186 EXPECT_SCOPED(AdvanceFrame());
1187 scheduler_->NotifyBeginMainFrameStarted();
1188 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1189 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1191 client_->Reset();
1192 scheduler_->NotifyReadyToCommit();
1193 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1195 client_->Reset();
1196 scheduler_->NotifyReadyToActivate();
1197 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
1199 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1200 // the mode.
1201 scheduler_->SetWaitForReadyToDraw();
1202 client_->Reset();
1203 task_runner().RunPendingTasks(); // Try to run posted deadline.
1204 // There is no posted deadline.
1205 EXPECT_NO_ACTION(client_);
1207 // Scheduler received ready to draw signal, and posted deadline.
1208 scheduler_->NotifyReadyToDraw();
1209 client_->Reset();
1210 task_runner().RunPendingTasks(); // Run posted deadline.
1211 EXPECT_EQ(1, client_->num_draws());
1212 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1215 TEST_F(SchedulerTest, WaitForReadyToDrawCancelledWhenLostOutputSurface) {
1216 SchedulerClientNeedsPrepareTilesInDraw* client =
1217 new SchedulerClientNeedsPrepareTilesInDraw;
1218 scheduler_settings_.use_external_begin_frame_source = true;
1219 scheduler_settings_.impl_side_painting = true;
1220 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1222 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1223 scheduler_->SetNeedsCommit();
1224 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1225 client_->Reset();
1227 // Begin new frame.
1228 EXPECT_SCOPED(AdvanceFrame());
1229 scheduler_->NotifyBeginMainFrameStarted();
1230 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1231 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1233 client_->Reset();
1234 scheduler_->NotifyReadyToCommit();
1235 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1237 client_->Reset();
1238 scheduler_->NotifyReadyToActivate();
1239 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
1241 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1242 // the mode.
1243 scheduler_->SetWaitForReadyToDraw();
1244 client_->Reset();
1245 task_runner().RunPendingTasks(); // Try to run posted deadline.
1246 // There is no posted deadline.
1247 EXPECT_NO_ACTION(client_);
1249 // Scheduler loses output surface, and stops waiting for ready to draw signal.
1250 client_->Reset();
1251 scheduler_->DidLoseOutputSurface();
1252 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1253 task_runner().RunPendingTasks(); // Run posted deadline.
1254 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
1255 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
1256 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
1259 class SchedulerClientWithFixedEstimates : public FakeSchedulerClient {
1260 public:
1261 SchedulerClientWithFixedEstimates(
1262 base::TimeDelta draw_duration,
1263 base::TimeDelta begin_main_frame_to_commit_duration,
1264 base::TimeDelta commit_to_activate_duration)
1265 : draw_duration_(draw_duration),
1266 begin_main_frame_to_commit_duration_(
1267 begin_main_frame_to_commit_duration),
1268 commit_to_activate_duration_(commit_to_activate_duration) {}
1270 base::TimeDelta DrawDurationEstimate() override { return draw_duration_; }
1271 base::TimeDelta BeginMainFrameToCommitDurationEstimate() override {
1272 return begin_main_frame_to_commit_duration_;
1274 base::TimeDelta CommitToActivateDurationEstimate() override {
1275 return commit_to_activate_duration_;
1278 private:
1279 base::TimeDelta draw_duration_;
1280 base::TimeDelta begin_main_frame_to_commit_duration_;
1281 base::TimeDelta commit_to_activate_duration_;
1284 void SchedulerTest::MainFrameInHighLatencyMode(
1285 int64 begin_main_frame_to_commit_estimate_in_ms,
1286 int64 commit_to_activate_estimate_in_ms,
1287 bool impl_latency_takes_priority,
1288 bool should_send_begin_main_frame) {
1289 // Set up client with specified estimates (draw duration is set to 1).
1290 SchedulerClientWithFixedEstimates* client =
1291 new SchedulerClientWithFixedEstimates(
1292 base::TimeDelta::FromMilliseconds(1),
1293 base::TimeDelta::FromMilliseconds(
1294 begin_main_frame_to_commit_estimate_in_ms),
1295 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms));
1297 scheduler_settings_.use_external_begin_frame_source = true;
1298 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1300 scheduler_->SetImplLatencyTakesPriority(impl_latency_takes_priority);
1302 // Impl thread hits deadline before commit finishes.
1303 scheduler_->SetNeedsCommit();
1304 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1305 EXPECT_SCOPED(AdvanceFrame());
1306 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1307 task_runner().RunPendingTasks(); // Run posted deadline.
1308 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1309 scheduler_->NotifyBeginMainFrameStarted();
1310 scheduler_->NotifyReadyToCommit();
1311 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1312 EXPECT_TRUE(client->HasAction("ScheduledActionSendBeginMainFrame"));
1314 client->Reset();
1315 scheduler_->SetNeedsCommit();
1316 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1317 EXPECT_SCOPED(AdvanceFrame());
1318 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1319 task_runner().RunPendingTasks(); // Run posted deadline.
1320 EXPECT_EQ(scheduler_->MainThreadIsInHighLatencyMode(),
1321 should_send_begin_main_frame);
1322 EXPECT_EQ(client->HasAction("ScheduledActionSendBeginMainFrame"),
1323 should_send_begin_main_frame);
1326 TEST_F(SchedulerTest,
1327 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) {
1328 // Set up client so that estimates indicate that we can commit and activate
1329 // before the deadline (~8ms by default).
1330 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, false, false));
1333 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) {
1334 // Set up client so that estimates indicate that the commit cannot finish
1335 // before the deadline (~8ms by default).
1336 EXPECT_SCOPED(MainFrameInHighLatencyMode(10, 1, false, true));
1339 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) {
1340 // Set up client so that estimates indicate that the activate cannot finish
1341 // before the deadline (~8ms by default).
1342 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true));
1345 TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) {
1346 // Set up client so that estimates indicate that we can commit and activate
1347 // before the deadline (~8ms by default), but also enable impl latency takes
1348 // priority mode.
1349 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true));
1352 TEST_F(SchedulerTest, PollForCommitCompletion) {
1353 // Since we are simulating a long commit, set up a client with draw duration
1354 // estimates that prevent skipping main frames to get to low latency mode.
1355 SchedulerClientWithFixedEstimates* client =
1356 new SchedulerClientWithFixedEstimates(
1357 base::TimeDelta::FromMilliseconds(1),
1358 base::TimeDelta::FromMilliseconds(32),
1359 base::TimeDelta::FromMilliseconds(32));
1360 scheduler_settings_.use_external_begin_frame_source = true;
1361 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1363 client->set_log_anticipated_draw_time_change(true);
1365 BeginFrameArgs frame_args =
1366 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
1367 frame_args.interval = base::TimeDelta::FromMilliseconds(1000);
1369 // At this point, we've drawn a frame. Start another commit, but hold off on
1370 // the NotifyReadyToCommit for now.
1371 EXPECT_FALSE(scheduler_->CommitPending());
1372 scheduler_->SetNeedsCommit();
1373 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args);
1374 EXPECT_TRUE(scheduler_->CommitPending());
1376 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1377 // blocking on the renderer.
1378 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1379 task_runner().RunPendingTasks(); // Run posted deadline.
1380 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1381 scheduler_->DidSwapBuffers();
1383 // Spin the event loop a few times and make sure we get more
1384 // DidAnticipateDrawTimeChange calls every time.
1385 int actions_so_far = client->num_actions_();
1387 // Does three iterations to make sure that the timer is properly repeating.
1388 for (int i = 0; i < 3; ++i) {
1389 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1390 task_runner().DelayToNextTaskTime().InMicroseconds())
1391 << scheduler_->AsValue()->ToString();
1392 task_runner().RunPendingTasks();
1393 EXPECT_GT(client->num_actions_(), actions_so_far);
1394 EXPECT_STREQ(client->Action(client->num_actions_() - 1),
1395 "DidAnticipatedDrawTimeChange");
1396 actions_so_far = client->num_actions_();
1399 // Do the same thing after BeginMainFrame starts but still before activation.
1400 scheduler_->NotifyBeginMainFrameStarted();
1401 for (int i = 0; i < 3; ++i) {
1402 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1403 task_runner().DelayToNextTaskTime().InMicroseconds())
1404 << scheduler_->AsValue()->ToString();
1405 task_runner().RunPendingTasks();
1406 EXPECT_GT(client->num_actions_(), actions_so_far);
1407 EXPECT_STREQ(client->Action(client->num_actions_() - 1),
1408 "DidAnticipatedDrawTimeChange");
1409 actions_so_far = client->num_actions_();
1413 TEST_F(SchedulerTest, BeginRetroFrame) {
1414 scheduler_settings_.use_external_begin_frame_source = true;
1415 SetUpScheduler(true);
1417 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1418 scheduler_->SetNeedsCommit();
1419 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1420 client_->Reset();
1422 // Create a BeginFrame with a long deadline to avoid race conditions.
1423 // This is the first BeginFrame, which will be handled immediately.
1424 BeginFrameArgs args =
1425 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
1426 args.deadline += base::TimeDelta::FromHours(1);
1427 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1428 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1429 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1430 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1431 EXPECT_TRUE(client_->needs_begin_frames());
1432 client_->Reset();
1434 // Queue BeginFrames while we are still handling the previous BeginFrame.
1435 args.frame_time += base::TimeDelta::FromSeconds(1);
1436 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1437 args.frame_time += base::TimeDelta::FromSeconds(1);
1438 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1440 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1441 task_runner().RunPendingTasks(); // Run posted deadline.
1442 EXPECT_NO_ACTION(client_);
1443 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1444 EXPECT_TRUE(client_->needs_begin_frames());
1445 client_->Reset();
1447 // NotifyReadyToCommit should trigger the commit.
1448 scheduler_->NotifyBeginMainFrameStarted();
1449 scheduler_->NotifyReadyToCommit();
1450 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1451 EXPECT_TRUE(client_->needs_begin_frames());
1452 client_->Reset();
1454 // BeginImplFrame should prepare the draw.
1455 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1456 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1457 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1458 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1459 EXPECT_TRUE(client_->needs_begin_frames());
1460 client_->Reset();
1462 // BeginImplFrame deadline should draw.
1463 task_runner().RunPendingTasks(); // Run posted deadline.
1464 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
1465 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1466 EXPECT_TRUE(client_->needs_begin_frames());
1467 client_->Reset();
1469 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1470 // to avoid excessive toggles.
1471 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1472 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
1473 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1474 client_->Reset();
1476 task_runner().RunPendingTasks(); // Run posted deadline.
1477 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1478 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1479 client_->Reset();
1482 TEST_F(SchedulerTest, BeginRetroFrame_SwapThrottled) {
1483 scheduler_settings_.use_external_begin_frame_source = true;
1484 SetUpScheduler(true);
1486 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1488 // To test swap ack throttling, this test disables automatic swap acks.
1489 scheduler_->SetMaxSwapsPending(1);
1490 client_->SetAutomaticSwapAck(false);
1492 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1493 client_->Reset();
1494 scheduler_->SetNeedsCommit();
1495 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1496 client_->Reset();
1498 EXPECT_SCOPED(AdvanceFrame());
1499 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1500 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1501 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1502 EXPECT_TRUE(client_->needs_begin_frames());
1503 client_->Reset();
1505 // Queue BeginFrame while we are still handling the previous BeginFrame.
1506 SendNextBeginFrame();
1507 EXPECT_NO_ACTION(client_);
1508 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1509 EXPECT_TRUE(client_->needs_begin_frames());
1510 client_->Reset();
1512 // NotifyReadyToCommit should trigger the pending commit and draw.
1513 scheduler_->NotifyBeginMainFrameStarted();
1514 scheduler_->NotifyReadyToCommit();
1515 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1516 EXPECT_TRUE(client_->needs_begin_frames());
1517 client_->Reset();
1519 // Swapping will put us into a swap throttled state.
1520 // Run posted deadline.
1521 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1522 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1523 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1524 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1525 EXPECT_TRUE(client_->needs_begin_frames());
1526 client_->Reset();
1528 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1529 // but not a BeginMainFrame or draw.
1530 scheduler_->SetNeedsCommit();
1531 scheduler_->SetNeedsRedraw();
1532 // Run posted BeginRetroFrame.
1533 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
1534 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1535 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1536 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1537 EXPECT_TRUE(client_->needs_begin_frames());
1538 client_->Reset();
1540 // Let time pass sufficiently beyond the regular deadline but not beyond the
1541 // late deadline.
1542 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1543 base::TimeDelta::FromMicroseconds(1));
1544 task_runner().RunUntilTime(now_src()->Now());
1545 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1547 // Take us out of a swap throttled state.
1548 scheduler_->DidSwapBuffersComplete();
1549 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
1550 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1551 EXPECT_TRUE(client_->needs_begin_frames());
1552 client_->Reset();
1554 // Verify that the deadline was rescheduled.
1555 task_runner().RunUntilTime(now_src()->Now());
1556 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
1557 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1558 EXPECT_TRUE(client_->needs_begin_frames());
1559 client_->Reset();
1562 TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooEarly) {
1563 scheduler_settings_.use_external_begin_frame_source = true;
1564 SetUpScheduler(true);
1566 scheduler_->SetNeedsCommit();
1567 EXPECT_TRUE(client_->needs_begin_frames());
1568 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1570 client_->Reset();
1571 EXPECT_SCOPED(AdvanceFrame());
1572 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1573 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1574 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1576 client_->Reset();
1577 scheduler_->NotifyBeginMainFrameStarted();
1579 client_->Reset();
1580 SendNextBeginFrame();
1581 // This BeginFrame is queued up as a retro frame.
1582 EXPECT_NO_ACTION(client_);
1583 // The previous deadline is still pending.
1584 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1586 client_->Reset();
1587 // This commit should schedule the (previous) deadline to trigger immediately.
1588 scheduler_->NotifyReadyToCommit();
1589 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1591 client_->Reset();
1592 // The deadline task should trigger causing a draw.
1593 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1594 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1595 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1596 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1598 // Keep animating.
1599 client_->Reset();
1600 scheduler_->SetNeedsAnimate();
1601 scheduler_->SetNeedsRedraw();
1602 EXPECT_NO_ACTION(client_);
1604 // Let's advance sufficiently past the next frame's deadline.
1605 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1606 BeginFrameArgs::DefaultEstimatedParentDrawTime() +
1607 base::TimeDelta::FromMicroseconds(1));
1609 // The retro frame hasn't expired yet.
1610 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
1611 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1612 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1613 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1615 // This is an immediate deadline case.
1616 client_->Reset();
1617 task_runner().RunPendingTasks();
1618 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1619 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
1622 TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooLate) {
1623 scheduler_settings_.use_external_begin_frame_source = true;
1624 SetUpScheduler(true);
1626 scheduler_->SetNeedsCommit();
1627 EXPECT_TRUE(client_->needs_begin_frames());
1628 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1630 client_->Reset();
1631 EXPECT_SCOPED(AdvanceFrame());
1632 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1633 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1634 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1636 client_->Reset();
1637 scheduler_->NotifyBeginMainFrameStarted();
1639 client_->Reset();
1640 SendNextBeginFrame();
1641 // This BeginFrame is queued up as a retro frame.
1642 EXPECT_NO_ACTION(client_);
1643 // The previous deadline is still pending.
1644 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1646 client_->Reset();
1647 // This commit should schedule the (previous) deadline to trigger immediately.
1648 scheduler_->NotifyReadyToCommit();
1649 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1651 client_->Reset();
1652 // The deadline task should trigger causing a draw.
1653 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1654 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1655 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1656 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1658 // Keep animating.
1659 client_->Reset();
1660 scheduler_->SetNeedsAnimate();
1661 scheduler_->SetNeedsRedraw();
1662 EXPECT_NO_ACTION(client_);
1664 // Let's advance sufficiently past the next frame's deadline.
1665 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() +
1666 base::TimeDelta::FromMicroseconds(1));
1668 // The retro frame should've expired.
1669 EXPECT_NO_ACTION(client_);
1672 void SchedulerTest::BeginFramesNotFromClient(
1673 bool use_external_begin_frame_source,
1674 bool throttle_frame_production) {
1675 scheduler_settings_.use_external_begin_frame_source =
1676 use_external_begin_frame_source;
1677 scheduler_settings_.throttle_frame_production = throttle_frame_production;
1678 SetUpScheduler(true);
1680 // SetNeedsCommit should begin the frame on the next BeginImplFrame
1681 // without calling SetNeedsBeginFrame.
1682 scheduler_->SetNeedsCommit();
1683 EXPECT_NO_ACTION(client_);
1684 client_->Reset();
1686 // When the client-driven BeginFrame are disabled, the scheduler posts it's
1687 // own BeginFrame tasks.
1688 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1689 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1690 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1691 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1692 client_->Reset();
1694 // If we don't swap on the deadline, we wait for the next BeginFrame.
1695 task_runner().RunPendingTasks(); // Run posted deadline.
1696 EXPECT_NO_ACTION(client_);
1697 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1698 client_->Reset();
1700 // NotifyReadyToCommit should trigger the commit.
1701 scheduler_->NotifyBeginMainFrameStarted();
1702 scheduler_->NotifyReadyToCommit();
1703 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1704 client_->Reset();
1706 // BeginImplFrame should prepare the draw.
1707 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1708 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1709 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1710 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1711 client_->Reset();
1713 // BeginImplFrame deadline should draw.
1714 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1715 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
1716 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1717 client_->Reset();
1719 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1720 // to avoid excessive toggles.
1721 task_runner().RunPendingTasks(); // Run posted BeginFrame.
1722 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
1723 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1724 client_->Reset();
1726 // Make sure SetNeedsBeginFrame isn't called on the client
1727 // when the BeginFrame is no longer needed.
1728 task_runner().RunPendingTasks(); // Run posted deadline.
1729 EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_);
1730 client_->Reset();
1733 TEST_F(SchedulerTest, SyntheticBeginFrames) {
1734 bool use_external_begin_frame_source = false;
1735 bool throttle_frame_production = true;
1736 BeginFramesNotFromClient(use_external_begin_frame_source,
1737 throttle_frame_production);
1740 TEST_F(SchedulerTest, VSyncThrottlingDisabled) {
1741 bool use_external_begin_frame_source = true;
1742 bool throttle_frame_production = false;
1743 BeginFramesNotFromClient(use_external_begin_frame_source,
1744 throttle_frame_production);
1747 TEST_F(SchedulerTest, SyntheticBeginFrames_And_VSyncThrottlingDisabled) {
1748 bool use_external_begin_frame_source = false;
1749 bool throttle_frame_production = false;
1750 BeginFramesNotFromClient(use_external_begin_frame_source,
1751 throttle_frame_production);
1754 void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
1755 bool use_external_begin_frame_source,
1756 bool throttle_frame_production) {
1757 scheduler_settings_.use_external_begin_frame_source =
1758 use_external_begin_frame_source;
1759 scheduler_settings_.throttle_frame_production = throttle_frame_production;
1760 SetUpScheduler(true);
1762 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1764 // To test swap ack throttling, this test disables automatic swap acks.
1765 scheduler_->SetMaxSwapsPending(1);
1766 client_->SetAutomaticSwapAck(false);
1768 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1769 client_->Reset();
1770 scheduler_->SetNeedsCommit();
1771 EXPECT_NO_ACTION(client_);
1772 client_->Reset();
1774 // Trigger the first BeginImplFrame and BeginMainFrame
1775 EXPECT_SCOPED(AdvanceFrame());
1776 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1777 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1778 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1779 client_->Reset();
1781 // NotifyReadyToCommit should trigger the pending commit and draw.
1782 scheduler_->NotifyBeginMainFrameStarted();
1783 scheduler_->NotifyReadyToCommit();
1784 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1785 client_->Reset();
1787 // Swapping will put us into a swap throttled state.
1788 // Run posted deadline.
1789 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1790 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1791 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1792 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1793 client_->Reset();
1795 // While swap throttled, BeginFrames should trigger BeginImplFrames,
1796 // but not a BeginMainFrame or draw.
1797 scheduler_->SetNeedsCommit();
1798 scheduler_->SetNeedsRedraw();
1799 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
1800 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1801 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1802 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1803 client_->Reset();
1805 // Let time pass sufficiently beyond the regular deadline but not beyond the
1806 // late deadline.
1807 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1808 base::TimeDelta::FromMicroseconds(1));
1809 task_runner().RunUntilTime(now_src()->Now());
1810 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1812 // Take us out of a swap throttled state.
1813 scheduler_->DidSwapBuffersComplete();
1814 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
1815 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1816 client_->Reset();
1818 // Verify that the deadline was rescheduled.
1819 // We can't use RunUntilTime(now) here because the next frame is also
1820 // scheduled if throttle_frame_production = false.
1821 base::TimeTicks before_deadline = now_src()->Now();
1822 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1823 base::TimeTicks after_deadline = now_src()->Now();
1824 EXPECT_EQ(after_deadline, before_deadline);
1825 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1826 client_->Reset();
1829 TEST_F(SchedulerTest, SyntheticBeginFrames_SwapThrottled) {
1830 bool use_external_begin_frame_source = false;
1831 bool throttle_frame_production = true;
1832 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
1833 throttle_frame_production);
1836 TEST_F(SchedulerTest, VSyncThrottlingDisabled_SwapThrottled) {
1837 bool use_external_begin_frame_source = true;
1838 bool throttle_frame_production = false;
1839 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
1840 throttle_frame_production);
1843 TEST_F(SchedulerTest,
1844 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled) {
1845 bool use_external_begin_frame_source = false;
1846 bool throttle_frame_production = false;
1847 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
1848 throttle_frame_production);
1851 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized) {
1852 scheduler_settings_.use_external_begin_frame_source = true;
1853 SetUpScheduler(false);
1855 scheduler_->SetCanStart();
1856 scheduler_->SetVisible(true);
1857 scheduler_->SetCanDraw(true);
1859 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
1860 client_->Reset();
1861 scheduler_->DidCreateAndInitializeOutputSurface();
1862 EXPECT_NO_ACTION(client_);
1864 scheduler_->DidLoseOutputSurface();
1865 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
1868 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) {
1869 scheduler_settings_.use_external_begin_frame_source = true;
1870 SetUpScheduler(true);
1872 // SetNeedsCommit should begin the frame.
1873 scheduler_->SetNeedsCommit();
1874 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1876 client_->Reset();
1877 EXPECT_SCOPED(AdvanceFrame());
1878 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1879 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1880 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1882 client_->Reset();
1883 scheduler_->DidLoseOutputSurface();
1884 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1885 EXPECT_NO_ACTION(client_);
1887 client_->Reset();
1888 scheduler_->NotifyBeginMainFrameStarted();
1889 scheduler_->NotifyReadyToCommit();
1890 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 1);
1892 client_->Reset();
1893 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1894 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
1895 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
1896 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
1899 void SchedulerTest::DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
1900 bool impl_side_painting) {
1901 scheduler_settings_.impl_side_painting = impl_side_painting;
1902 scheduler_settings_.use_external_begin_frame_source = true;
1903 SetUpScheduler(true);
1905 // SetNeedsCommit should begin the frame.
1906 scheduler_->SetNeedsCommit();
1907 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1909 client_->Reset();
1910 EXPECT_SCOPED(AdvanceFrame());
1911 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1912 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1913 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1915 client_->Reset();
1916 scheduler_->DidLoseOutputSurface();
1917 // Do nothing when impl frame is in deadine pending state.
1918 EXPECT_NO_ACTION(client_);
1920 client_->Reset();
1921 // Run posted deadline.
1922 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1923 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1924 // OnBeginImplFrameDeadline didn't schedule output surface creation because
1925 // main frame is not yet completed.
1926 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1927 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1928 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1930 // BeginImplFrame is not started.
1931 client_->Reset();
1932 task_runner().RunUntilTime(now_src()->Now() +
1933 base::TimeDelta::FromMilliseconds(10));
1934 EXPECT_NO_ACTION(client_);
1935 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1937 client_->Reset();
1938 scheduler_->NotifyBeginMainFrameStarted();
1939 scheduler_->NotifyReadyToCommit();
1940 if (impl_side_painting) {
1941 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 3);
1942 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 3);
1943 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 2, 3);
1944 } else {
1945 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2);
1946 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 2);
1950 TEST_F(SchedulerTest,
1951 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) {
1952 bool impl_side_painting = false;
1953 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
1956 TEST_F(SchedulerTest,
1957 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint) {
1958 bool impl_side_painting = true;
1959 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
1962 void SchedulerTest::DidLoseOutputSurfaceAfterReadyToCommit(
1963 bool impl_side_painting) {
1964 scheduler_settings_.impl_side_painting = impl_side_painting;
1965 scheduler_settings_.use_external_begin_frame_source = true;
1966 SetUpScheduler(true);
1968 // SetNeedsCommit should begin the frame.
1969 scheduler_->SetNeedsCommit();
1970 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1972 client_->Reset();
1973 EXPECT_SCOPED(AdvanceFrame());
1974 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1975 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1976 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1978 client_->Reset();
1979 scheduler_->NotifyBeginMainFrameStarted();
1980 scheduler_->NotifyReadyToCommit();
1981 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1983 client_->Reset();
1984 scheduler_->DidLoseOutputSurface();
1985 // SetNeedsBeginFrames(false) is not called until the end of the frame.
1986 if (impl_side_painting) {
1987 // Sync tree should be forced to activate.
1988 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
1989 } else {
1990 EXPECT_NO_ACTION(client_);
1993 client_->Reset();
1994 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1995 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
1996 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
1997 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2000 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) {
2001 DidLoseOutputSurfaceAfterReadyToCommit(false);
2004 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting) {
2005 DidLoseOutputSurfaceAfterReadyToCommit(true);
2008 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles) {
2009 scheduler_settings_.use_external_begin_frame_source = true;
2010 SetUpScheduler(true);
2012 scheduler_->SetNeedsPrepareTiles();
2013 scheduler_->SetNeedsRedraw();
2014 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2016 client_->Reset();
2017 EXPECT_SCOPED(AdvanceFrame());
2018 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2019 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2020 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2022 client_->Reset();
2023 scheduler_->DidLoseOutputSurface();
2024 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2025 EXPECT_NO_ACTION(client_);
2027 client_->Reset();
2028 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2029 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 0, 4);
2030 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 4);
2031 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 2, 4);
2032 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 3, 4);
2035 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) {
2036 scheduler_settings_.use_external_begin_frame_source = true;
2037 SetUpScheduler(true);
2039 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2040 scheduler_->SetNeedsCommit();
2041 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2043 // Create a BeginFrame with a long deadline to avoid race conditions.
2044 // This is the first BeginFrame, which will be handled immediately.
2045 client_->Reset();
2046 BeginFrameArgs args =
2047 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2048 args.deadline += base::TimeDelta::FromHours(1);
2049 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2050 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2051 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2052 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2053 EXPECT_TRUE(client_->needs_begin_frames());
2055 // Queue BeginFrames while we are still handling the previous BeginFrame.
2056 args.frame_time += base::TimeDelta::FromSeconds(1);
2057 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2058 args.frame_time += base::TimeDelta::FromSeconds(1);
2059 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2061 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2062 client_->Reset();
2063 task_runner().RunPendingTasks(); // Run posted deadline.
2064 EXPECT_NO_ACTION(client_);
2065 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2066 EXPECT_TRUE(client_->needs_begin_frames());
2068 // NotifyReadyToCommit should trigger the commit.
2069 client_->Reset();
2070 scheduler_->NotifyBeginMainFrameStarted();
2071 scheduler_->NotifyReadyToCommit();
2072 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2073 EXPECT_TRUE(client_->needs_begin_frames());
2075 client_->Reset();
2076 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty());
2077 scheduler_->DidLoseOutputSurface();
2078 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2079 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2080 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2081 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty());
2083 // Posted BeginRetroFrame is aborted.
2084 client_->Reset();
2085 task_runner().RunPendingTasks();
2086 EXPECT_NO_ACTION(client_);
2089 TEST_F(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) {
2090 scheduler_settings_.use_external_begin_frame_source = true;
2091 SetUpScheduler(true);
2093 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2094 scheduler_->SetNeedsCommit();
2095 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2097 // Create a BeginFrame with a long deadline to avoid race conditions.
2098 // This is the first BeginFrame, which will be handled immediately.
2099 client_->Reset();
2100 BeginFrameArgs args =
2101 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2102 args.deadline += base::TimeDelta::FromHours(1);
2103 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2104 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2105 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2106 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2107 EXPECT_TRUE(client_->needs_begin_frames());
2109 // Queue BeginFrames while we are still handling the previous BeginFrame.
2110 args.frame_time += base::TimeDelta::FromSeconds(1);
2111 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2112 args.frame_time += base::TimeDelta::FromSeconds(1);
2113 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2115 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2116 client_->Reset();
2117 task_runner().RunPendingTasks(); // Run posted deadline.
2118 EXPECT_NO_ACTION(client_);
2119 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2120 EXPECT_TRUE(client_->needs_begin_frames());
2122 // NotifyReadyToCommit should trigger the commit.
2123 client_->Reset();
2124 scheduler_->NotifyBeginMainFrameStarted();
2125 scheduler_->NotifyReadyToCommit();
2126 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2127 EXPECT_TRUE(client_->needs_begin_frames());
2129 // BeginImplFrame should prepare the draw.
2130 client_->Reset();
2131 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2132 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2133 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2134 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2135 EXPECT_TRUE(client_->needs_begin_frames());
2137 client_->Reset();
2138 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty());
2139 scheduler_->DidLoseOutputSurface();
2140 EXPECT_NO_ACTION(client_);
2141 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty());
2143 // BeginImplFrame deadline should abort drawing.
2144 client_->Reset();
2145 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2146 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2147 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2148 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2149 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2150 EXPECT_FALSE(client_->needs_begin_frames());
2152 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
2153 client_->Reset();
2154 task_runner().RunPendingTasks();
2155 EXPECT_NO_ACTION(client_);
2158 TEST_F(SchedulerTest, DidLoseOutputSurfaceWithSyntheticBeginFrameSource) {
2159 SetUpScheduler(true);
2161 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2162 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2163 scheduler_->SetNeedsCommit();
2164 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2166 client_->Reset();
2167 AdvanceFrame();
2168 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2169 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2170 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2171 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2173 // NotifyReadyToCommit should trigger the commit.
2174 client_->Reset();
2175 scheduler_->NotifyBeginMainFrameStarted();
2176 scheduler_->NotifyReadyToCommit();
2177 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2178 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2180 client_->Reset();
2181 scheduler_->DidLoseOutputSurface();
2182 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2183 EXPECT_NO_ACTION(client_);
2184 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2186 client_->Reset();
2187 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2188 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 2);
2189 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2190 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2193 TEST_F(SchedulerTest, DidLoseOutputSurfaceWhenIdle) {
2194 scheduler_settings_.use_external_begin_frame_source = true;
2195 SetUpScheduler(true);
2197 // SetNeedsCommit should begin the frame.
2198 scheduler_->SetNeedsCommit();
2199 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2201 client_->Reset();
2202 EXPECT_SCOPED(AdvanceFrame());
2203 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2204 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2205 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2207 client_->Reset();
2208 scheduler_->NotifyBeginMainFrameStarted();
2209 scheduler_->NotifyReadyToCommit();
2210 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2212 client_->Reset();
2213 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2214 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2215 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2217 // Idle time between BeginFrames.
2218 client_->Reset();
2219 scheduler_->DidLoseOutputSurface();
2220 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2221 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2222 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2225 TEST_F(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) {
2226 scheduler_settings_.impl_side_painting = true;
2227 scheduler_settings_.use_external_begin_frame_source = true;
2228 SetUpScheduler(true);
2230 // SetNeedsCommit should begin the frame.
2231 scheduler_->SetNeedsCommit();
2232 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2234 client_->Reset();
2235 EXPECT_SCOPED(AdvanceFrame());
2236 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2237 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2238 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2240 client_->Reset();
2241 scheduler_->NotifyBeginMainFrameStarted();
2242 scheduler_->NotifyReadyToCommit();
2243 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2244 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2246 client_->Reset();
2247 scheduler_->SetVisible(false);
2248 task_runner().RunPendingTasks(); // Run posted deadline.
2250 // Sync tree should be forced to activate.
2251 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 3);
2252 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2253 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2256 // Tests to ensure frame sources can be successfully changed while drawing.
2257 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottled) {
2258 scheduler_settings_.use_external_begin_frame_source = true;
2259 SetUpScheduler(true);
2261 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2262 scheduler_->SetNeedsRedraw();
2263 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2264 client_->Reset();
2266 EXPECT_SCOPED(AdvanceFrame());
2267 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2268 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2269 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2270 EXPECT_TRUE(client_->needs_begin_frames());
2271 client_->Reset();
2272 task_runner().RunPendingTasks(); // Run posted deadline.
2273 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2274 scheduler_->SetNeedsRedraw();
2276 // Switch to an unthrottled frame source.
2277 scheduler_->SetThrottleFrameProduction(false);
2278 client_->Reset();
2280 // Unthrottled frame source will immediately begin a new frame.
2281 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2282 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2283 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2284 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2285 client_->Reset();
2287 // If we don't swap on the deadline, we wait for the next BeginFrame.
2288 task_runner().RunPendingTasks(); // Run posted deadline.
2289 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2290 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2291 client_->Reset();
2294 // Tests to ensure frame sources can be successfully changed while a frame
2295 // deadline is pending.
2296 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottledBeforeDeadline) {
2297 scheduler_settings_.use_external_begin_frame_source = true;
2298 SetUpScheduler(true);
2300 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2301 scheduler_->SetNeedsRedraw();
2302 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2303 client_->Reset();
2305 EXPECT_SCOPED(AdvanceFrame());
2306 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2307 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2309 // Switch to an unthrottled frame source before the frame deadline is hit.
2310 scheduler_->SetThrottleFrameProduction(false);
2311 client_->Reset();
2313 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2314 EXPECT_TRUE(client_->needs_begin_frames());
2315 client_->Reset();
2317 task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame.
2318 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
2319 // Unthrottled frame source will immediately begin a new frame.
2320 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 2);
2321 scheduler_->SetNeedsRedraw();
2322 client_->Reset();
2324 task_runner().RunPendingTasks(); // Run posted deadline.
2325 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2326 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2327 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2328 client_->Reset();
2331 // Tests to ensure that the active frame source can successfully be changed from
2332 // unthrottled to throttled.
2333 TEST_F(SchedulerTest, SwitchFrameSourceToThrottled) {
2334 scheduler_settings_.throttle_frame_production = false;
2335 scheduler_settings_.use_external_begin_frame_source = true;
2336 SetUpScheduler(true);
2338 scheduler_->SetNeedsRedraw();
2339 EXPECT_NO_ACTION(client_);
2340 client_->Reset();
2342 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2343 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2344 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2345 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2346 client_->Reset();
2348 task_runner().RunPendingTasks(); // Run posted deadline.
2349 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2350 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2351 client_->Reset();
2353 // Switch to a throttled frame source.
2354 scheduler_->SetThrottleFrameProduction(true);
2355 client_->Reset();
2357 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2358 scheduler_->SetNeedsRedraw();
2359 task_runner().RunPendingTasks();
2360 EXPECT_NO_ACTION(client_);
2361 client_->Reset();
2363 EXPECT_SCOPED(AdvanceFrame());
2364 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2365 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2366 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2367 EXPECT_TRUE(client_->needs_begin_frames());
2368 client_->Reset();
2369 task_runner().RunPendingTasks(); // Run posted deadline.
2370 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2373 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
2374 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon) {
2375 scheduler_settings_.use_external_begin_frame_source = true;
2376 SetUpScheduler(true);
2378 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2379 scheduler_->SetNeedsCommit();
2380 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2381 client_->Reset();
2383 // Trigger a frame draw.
2384 EXPECT_SCOPED(AdvanceFrame());
2385 scheduler_->NotifyBeginMainFrameStarted();
2386 scheduler_->NotifyReadyToCommit();
2387 task_runner().RunPendingTasks();
2388 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 5);
2389 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 5);
2390 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 5);
2391 EXPECT_ACTION("ScheduledActionAnimate", client_, 3, 5);
2392 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 5);
2393 client_->Reset();
2395 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2396 // and send a SendBeginMainFrameNotExpectedSoon.
2397 EXPECT_SCOPED(AdvanceFrame());
2398 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
2399 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2400 client_->Reset();
2402 task_runner().RunPendingTasks(); // Run posted deadline.
2403 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
2404 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2405 client_->Reset();
2408 TEST_F(SchedulerTest, SynchronousCompositorAnimation) {
2409 scheduler_settings_.using_synchronous_renderer_compositor = true;
2410 scheduler_settings_.use_external_begin_frame_source = true;
2411 scheduler_settings_.impl_side_painting = true;
2412 SetUpScheduler(true);
2414 scheduler_->SetNeedsAnimate();
2415 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2416 client_->Reset();
2418 // Next vsync.
2419 AdvanceFrame();
2420 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2421 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
2422 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
2423 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2424 client_->Reset();
2426 // Continue with animation.
2427 scheduler_->SetNeedsAnimate();
2428 EXPECT_NO_ACTION(client_);
2430 // Android onDraw.
2431 scheduler_->SetNeedsRedraw();
2432 scheduler_->OnDrawForOutputSurface();
2433 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
2434 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2435 client_->Reset();
2437 // Next vsync.
2438 AdvanceFrame();
2439 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2440 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
2441 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
2442 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2443 client_->Reset();
2445 // Android onDraw.
2446 scheduler_->SetNeedsRedraw();
2447 scheduler_->OnDrawForOutputSurface();
2448 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
2449 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2450 client_->Reset();
2452 // Idle on next vsync.
2453 AdvanceFrame();
2454 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2455 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2456 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2457 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2458 client_->Reset();
2461 TEST_F(SchedulerTest, SynchronousCompositorOnDrawDuringIdle) {
2462 scheduler_settings_.using_synchronous_renderer_compositor = true;
2463 scheduler_settings_.use_external_begin_frame_source = true;
2464 scheduler_settings_.impl_side_painting = true;
2465 SetUpScheduler(true);
2467 scheduler_->SetNeedsRedraw();
2468 scheduler_->OnDrawForOutputSurface();
2469 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3);
2470 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
2471 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3);
2472 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2473 client_->Reset();
2475 // Idle on next vsync.
2476 AdvanceFrame();
2477 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2478 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2479 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2480 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2481 client_->Reset();
2484 TEST_F(SchedulerTest, SynchronousCompositorCommit) {
2485 scheduler_settings_.using_synchronous_renderer_compositor = true;
2486 scheduler_settings_.use_external_begin_frame_source = true;
2487 scheduler_settings_.impl_side_painting = true;
2488 SetUpScheduler(true);
2490 scheduler_->SetNeedsCommit();
2491 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2492 client_->Reset();
2494 // Next vsync.
2495 AdvanceFrame();
2496 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2497 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2498 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2499 client_->Reset();
2501 scheduler_->NotifyBeginMainFrameStarted();
2502 EXPECT_NO_ACTION(client_);
2504 // Next vsync.
2505 AdvanceFrame();
2506 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
2507 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2508 client_->Reset();
2510 scheduler_->NotifyReadyToCommit();
2511 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2512 client_->Reset();
2514 scheduler_->NotifyReadyToActivate();
2515 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2516 client_->Reset();
2518 // Next vsync.
2519 AdvanceFrame();
2520 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2521 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
2522 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
2523 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2524 client_->Reset();
2526 // Android onDraw.
2527 scheduler_->SetNeedsRedraw();
2528 scheduler_->OnDrawForOutputSurface();
2529 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
2530 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2531 client_->Reset();
2533 // Idle on next vsync.
2534 AdvanceFrame();
2535 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2536 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2537 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2538 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2539 client_->Reset();
2542 TEST_F(SchedulerTest, SynchronousCompositorDoubleCommitWithoutDraw) {
2543 scheduler_settings_.using_synchronous_renderer_compositor = true;
2544 scheduler_settings_.use_external_begin_frame_source = true;
2545 scheduler_settings_.impl_side_painting = true;
2546 SetUpScheduler(true);
2548 scheduler_->SetNeedsCommit();
2549 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2550 client_->Reset();
2552 // Next vsync.
2553 AdvanceFrame();
2554 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2555 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2556 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2557 client_->Reset();
2559 scheduler_->NotifyBeginMainFrameStarted();
2560 EXPECT_NO_ACTION(client_);
2562 scheduler_->NotifyReadyToCommit();
2563 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2564 client_->Reset();
2566 scheduler_->NotifyReadyToActivate();
2567 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2568 client_->Reset();
2570 // Ask for another commit.
2571 scheduler_->SetNeedsCommit();
2573 AdvanceFrame();
2574 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4);
2575 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4);
2576 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4);
2577 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 3, 4);
2578 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2579 client_->Reset();
2581 scheduler_->NotifyBeginMainFrameStarted();
2582 EXPECT_NO_ACTION(client_);
2584 // Allow new commit even though previous commit hasn't been drawn.
2585 scheduler_->NotifyReadyToCommit();
2586 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2587 client_->Reset();
2590 TEST_F(SchedulerTest, AuthoritativeVSyncInterval) {
2591 SetUpScheduler(true);
2593 base::TimeDelta initial_interval =
2594 scheduler_->begin_impl_frame_args().interval;
2595 base::TimeDelta authoritative_interval =
2596 base::TimeDelta::FromMilliseconds(33);
2598 scheduler_->SetNeedsCommit();
2599 EXPECT_SCOPED(AdvanceFrame());
2601 EXPECT_EQ(initial_interval, scheduler_->begin_impl_frame_args().interval);
2603 scheduler_->NotifyBeginMainFrameStarted();
2604 scheduler_->NotifyReadyToCommit();
2605 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2607 scheduler_->SetAuthoritativeVSyncInterval(authoritative_interval);
2609 EXPECT_SCOPED(AdvanceFrame());
2611 // At the next BeginFrame, authoritative interval is used instead of previous
2612 // interval.
2613 EXPECT_NE(initial_interval, scheduler_->begin_impl_frame_args().interval);
2614 EXPECT_EQ(authoritative_interval,
2615 scheduler_->begin_impl_frame_args().interval);
2618 } // namespace
2619 } // namespace cc