Infobar material design refresh: bg color
[chromium-blink-merge.git] / cc / scheduler / scheduler_unittest.cc
blobdfb76bd38d11b23b389e1ce0779e7a8c67971af5
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/message_loop/message_loop.h"
12 #include "base/numerics/safe_conversions.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 scheduler_(nullptr) {
53 Reset();
56 void Reset() {
57 actions_.clear();
58 states_.clear();
59 draw_will_happen_ = true;
60 swap_will_happen_if_draw_happens_ = true;
61 num_draws_ = 0;
62 begin_frame_args_sent_to_children_ = BeginFrameArgs();
65 void set_scheduler(TestScheduler* scheduler) { scheduler_ = scheduler; }
67 bool needs_begin_frames() {
68 return scheduler_->frame_source().NeedsBeginFrames();
70 int num_draws() const { return num_draws_; }
71 int num_actions_() const { return static_cast<int>(actions_.size()); }
72 const char* Action(int i) const { return actions_[i]; }
73 std::string StateForAction(int i) const { return states_[i]->ToString(); }
74 base::TimeTicks posted_begin_impl_frame_deadline() const {
75 return posted_begin_impl_frame_deadline_;
78 int ActionIndex(const char* action) const {
79 for (size_t i = 0; i < actions_.size(); i++)
80 if (!strcmp(actions_[i], action))
81 return base::checked_cast<int>(i);
82 return -1;
85 bool HasAction(const char* action) const {
86 return ActionIndex(action) >= 0;
89 void SetDrawWillHappen(bool draw_will_happen) {
90 draw_will_happen_ = draw_will_happen;
92 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
93 swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
95 void SetAutomaticSwapAck(bool automatic_swap_ack) {
96 automatic_swap_ack_ = automatic_swap_ack;
98 // SchedulerClient implementation.
99 void WillBeginImplFrame(const BeginFrameArgs& args) override {
100 PushAction("WillBeginImplFrame");
102 void DidFinishImplFrame() override {}
104 void ScheduledActionSendBeginMainFrame() override {
105 PushAction("ScheduledActionSendBeginMainFrame");
107 void ScheduledActionAnimate() override {
108 PushAction("ScheduledActionAnimate");
110 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
111 PushAction("ScheduledActionDrawAndSwapIfPossible");
112 num_draws_++;
113 DrawResult result =
114 draw_will_happen_ ? DRAW_SUCCESS : DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
115 bool swap_will_happen =
116 draw_will_happen_ && swap_will_happen_if_draw_happens_;
117 if (swap_will_happen) {
118 scheduler_->DidSwapBuffers();
120 if (automatic_swap_ack_)
121 scheduler_->DidSwapBuffersComplete();
123 return result;
125 DrawResult ScheduledActionDrawAndSwapForced() override {
126 PushAction("ScheduledActionDrawAndSwapForced");
127 return DRAW_SUCCESS;
129 void ScheduledActionCommit() override {
130 PushAction("ScheduledActionCommit");
131 scheduler_->DidCommit();
133 void ScheduledActionActivateSyncTree() override {
134 PushAction("ScheduledActionActivateSyncTree");
136 void ScheduledActionBeginOutputSurfaceCreation() override {
137 PushAction("ScheduledActionBeginOutputSurfaceCreation");
139 void ScheduledActionPrepareTiles() override {
140 PushAction("ScheduledActionPrepareTiles");
141 scheduler_->WillPrepareTiles();
142 scheduler_->DidPrepareTiles();
144 void ScheduledActionInvalidateOutputSurface() override {
145 actions_.push_back("ScheduledActionInvalidateOutputSurface");
146 states_.push_back(scheduler_->AsValue());
149 void SendBeginFramesToChildren(const BeginFrameArgs& args) override {
150 begin_frame_args_sent_to_children_ = args;
153 void SendBeginMainFrameNotExpectedSoon() override {
154 PushAction("SendBeginMainFrameNotExpectedSoon");
157 base::Callback<bool(void)> ImplFrameDeadlinePending(bool state) {
158 return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback,
159 base::Unretained(this),
160 state);
163 bool begin_frame_is_sent_to_children() const {
164 return begin_frame_args_sent_to_children_.IsValid();
167 const BeginFrameArgs& begin_frame_args_sent_to_children() const {
168 return begin_frame_args_sent_to_children_;
171 void PushAction(const char* description) {
172 actions_.push_back(description);
173 states_.push_back(scheduler_->AsValue());
176 protected:
177 bool ImplFrameDeadlinePendingCallback(bool state) {
178 return scheduler_->BeginImplFrameDeadlinePending() == state;
181 bool draw_will_happen_;
182 bool swap_will_happen_if_draw_happens_;
183 bool automatic_swap_ack_;
184 int num_draws_;
185 BeginFrameArgs begin_frame_args_sent_to_children_;
186 base::TimeTicks posted_begin_impl_frame_deadline_;
187 std::vector<const char*> actions_;
188 std::vector<scoped_refptr<base::trace_event::ConvertableToTraceFormat>>
189 states_;
190 TestScheduler* scheduler_;
193 class FakeExternalBeginFrameSource : public BeginFrameSourceBase {
194 public:
195 explicit FakeExternalBeginFrameSource(FakeSchedulerClient* client)
196 : client_(client) {}
197 ~FakeExternalBeginFrameSource() override {}
199 void OnNeedsBeginFramesChange(bool needs_begin_frames) override {
200 if (needs_begin_frames) {
201 client_->PushAction("SetNeedsBeginFrames(true)");
202 } else {
203 client_->PushAction("SetNeedsBeginFrames(false)");
207 void TestOnBeginFrame(const BeginFrameArgs& args) {
208 return CallOnBeginFrame(args);
211 private:
212 FakeSchedulerClient* client_;
215 class SchedulerTest : public testing::Test {
216 public:
217 SchedulerTest()
218 : now_src_(new base::SimpleTestTickClock()),
219 task_runner_(new OrderedSimpleTaskRunner(now_src_.get(), true)),
220 fake_external_begin_frame_source_(nullptr) {
221 now_src_->Advance(base::TimeDelta::FromMicroseconds(10000));
222 // A bunch of tests require NowTicks()
223 // to be > BeginFrameArgs::DefaultInterval()
224 now_src_->Advance(base::TimeDelta::FromMilliseconds(100));
225 // Fail if we need to run 100 tasks in a row.
226 task_runner_->SetRunTaskLimit(100);
229 ~SchedulerTest() override {}
231 protected:
232 TestScheduler* CreateScheduler() {
233 if (scheduler_settings_.use_external_begin_frame_source) {
234 fake_external_begin_frame_source_.reset(
235 new FakeExternalBeginFrameSource(client_.get()));
238 scoped_ptr<FakeCompositorTimingHistory> fake_compositor_timing_history =
239 FakeCompositorTimingHistory::Create();
240 fake_compositor_timing_history_ = fake_compositor_timing_history.get();
242 scheduler_ = TestScheduler::Create(
243 now_src_.get(), client_.get(), scheduler_settings_, 0,
244 task_runner_.get(), fake_external_begin_frame_source_.get(),
245 fake_compositor_timing_history.Pass());
246 DCHECK(scheduler_);
247 client_->set_scheduler(scheduler_.get());
249 // Use large estimates by default to avoid latency recovery
250 // in most tests.
251 base::TimeDelta slow_duration = base::TimeDelta::FromSeconds(1);
252 fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration);
254 return scheduler_.get();
257 void CreateSchedulerAndInitSurface() {
258 CreateScheduler();
259 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit());
262 void SetUpScheduler(bool initSurface) {
263 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient), initSurface);
266 void SetUpScheduler(scoped_ptr<FakeSchedulerClient> client,
267 bool initSurface) {
268 client_ = client.Pass();
269 if (initSurface)
270 CreateSchedulerAndInitSurface();
271 else
272 CreateScheduler();
275 OrderedSimpleTaskRunner& task_runner() { return *task_runner_; }
276 base::SimpleTestTickClock* now_src() { return now_src_.get(); }
278 // As this function contains EXPECT macros, to allow debugging it should be
279 // called inside EXPECT_SCOPED like so;
280 // EXPECT_SCOPED(client.InitializeOutputSurfaceAndFirstCommit(scheduler));
281 void InitializeOutputSurfaceAndFirstCommit() {
282 TRACE_EVENT0("cc",
283 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit");
284 DCHECK(scheduler_);
286 // Check the client doesn't have any actions queued when calling this
287 // function.
288 EXPECT_NO_ACTION(client_);
289 EXPECT_FALSE(client_->needs_begin_frames());
291 // Start the initial output surface creation.
292 EXPECT_FALSE(scheduler_->CanStart());
293 scheduler_->SetCanStart();
294 scheduler_->SetVisible(true);
295 scheduler_->SetCanDraw(true);
296 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
298 client_->Reset();
300 // We don't see anything happening until the first impl frame.
301 scheduler_->DidCreateAndInitializeOutputSurface();
302 scheduler_->SetNeedsBeginMainFrame();
303 EXPECT_TRUE(client_->needs_begin_frames());
304 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
305 client_->Reset();
308 SCOPED_TRACE("Do first frame to commit after initialize.");
309 AdvanceFrame();
311 scheduler_->NotifyBeginMainFrameStarted();
312 scheduler_->NotifyReadyToCommit();
313 scheduler_->NotifyReadyToActivate();
314 scheduler_->NotifyReadyToDraw();
316 EXPECT_FALSE(scheduler_->CommitPending());
318 if (scheduler_settings_.using_synchronous_renderer_compositor) {
319 scheduler_->SetNeedsRedraw();
320 scheduler_->OnDrawForOutputSurface();
321 } else {
322 // Run the posted deadline task.
323 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
324 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
327 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
330 client_->Reset();
333 SCOPED_TRACE(
334 "Run second frame so Scheduler calls SetNeedsBeginFrame(false).");
335 AdvanceFrame();
337 if (!scheduler_settings_.using_synchronous_renderer_compositor) {
338 // Run the posted deadline task.
339 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
340 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
343 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
346 EXPECT_FALSE(client_->needs_begin_frames());
347 client_->Reset();
350 // As this function contains EXPECT macros, to allow debugging it should be
351 // called inside EXPECT_SCOPED like so;
352 // EXPECT_SCOPED(client.AdvanceFrame());
353 void AdvanceFrame() {
354 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
355 "FakeSchedulerClient::AdvanceFrame");
356 // Consume any previous deadline first, if no deadline is currently
357 // pending, ImplFrameDeadlinePending will return false straight away and we
358 // will run no tasks.
359 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
360 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
362 // Send the next BeginFrame message if using an external source, otherwise
363 // it will be already in the task queue.
364 if (scheduler_->settings().use_external_begin_frame_source &&
365 scheduler_->FrameProductionThrottled()) {
366 EXPECT_TRUE(client_->needs_begin_frames());
367 SendNextBeginFrame();
370 if (!scheduler_->settings().using_synchronous_renderer_compositor) {
371 // Then run tasks until new deadline is scheduled.
372 EXPECT_TRUE(task_runner_->RunTasksWhile(
373 client_->ImplFrameDeadlinePending(false)));
374 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
378 BeginFrameArgs SendNextBeginFrame() {
379 DCHECK(scheduler_->settings().use_external_begin_frame_source);
380 // Creep the time forward so that any BeginFrameArgs is not equal to the
381 // last one otherwise we violate the BeginFrameSource contract.
382 now_src_->Advance(BeginFrameArgs::DefaultInterval());
383 BeginFrameArgs args =
384 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
385 fake_external_begin_frame_source_->TestOnBeginFrame(args);
386 return args;
389 FakeExternalBeginFrameSource* fake_external_begin_frame_source() const {
390 return fake_external_begin_frame_source_.get();
393 void CheckMainFrameSkippedAfterLateCommit(bool expect_send_begin_main_frame);
394 void ImplFrameSkippedAfterLateSwapAck(bool swap_ack_before_deadline);
395 void ImplFrameIsNotSkippedAfterLateSwapAck();
396 void BeginFramesNotFromClient(bool use_external_begin_frame_source,
397 bool throttle_frame_production);
398 void BeginFramesNotFromClient_SwapThrottled(
399 bool use_external_begin_frame_source,
400 bool throttle_frame_production);
402 scoped_ptr<base::SimpleTestTickClock> now_src_;
403 scoped_refptr<OrderedSimpleTaskRunner> task_runner_;
404 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source_;
405 SchedulerSettings scheduler_settings_;
406 scoped_ptr<FakeSchedulerClient> client_;
407 scoped_ptr<TestScheduler> scheduler_;
408 FakeCompositorTimingHistory* fake_compositor_timing_history_;
411 TEST_F(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) {
412 scheduler_settings_.use_external_begin_frame_source = true;
413 SetUpScheduler(false);
414 scheduler_->SetCanStart();
415 scheduler_->SetVisible(true);
416 scheduler_->SetCanDraw(true);
418 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
419 client_->Reset();
420 scheduler_->DidCreateAndInitializeOutputSurface();
421 EXPECT_NO_ACTION(client_);
424 TEST_F(SchedulerTest, SendBeginFramesToChildren) {
425 scheduler_settings_.use_external_begin_frame_source = true;
426 SetUpScheduler(true);
428 EXPECT_FALSE(client_->begin_frame_is_sent_to_children());
429 scheduler_->SetNeedsBeginMainFrame();
430 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
431 EXPECT_TRUE(client_->needs_begin_frames());
433 scheduler_->SetChildrenNeedBeginFrames(true);
435 client_->Reset();
436 EXPECT_SCOPED(AdvanceFrame());
437 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
438 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
439 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
440 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
441 EXPECT_TRUE(client_->needs_begin_frames());
444 TEST_F(SchedulerTest, SendBeginFramesToChildrenWithoutCommit) {
445 scheduler_settings_.use_external_begin_frame_source = true;
446 SetUpScheduler(true);
448 EXPECT_FALSE(client_->needs_begin_frames());
449 scheduler_->SetChildrenNeedBeginFrames(true);
450 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
451 EXPECT_TRUE(client_->needs_begin_frames());
453 client_->Reset();
454 EXPECT_SCOPED(AdvanceFrame());
455 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
458 TEST_F(SchedulerTest, SendBeginFramesToChildrenDeadlineNotAdjusted) {
459 // Set up client with specified estimates.
460 scheduler_settings_.use_external_begin_frame_source = true;
461 SetUpScheduler(true);
463 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate(
464 base::TimeDelta::FromMilliseconds(2));
465 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate(
466 base::TimeDelta::FromMilliseconds(4));
467 fake_compositor_timing_history_->SetDrawDurationEstimate(
468 base::TimeDelta::FromMilliseconds(1));
470 EXPECT_FALSE(client_->needs_begin_frames());
471 scheduler_->SetChildrenNeedBeginFrames(true);
472 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
473 EXPECT_TRUE(client_->needs_begin_frames());
475 client_->Reset();
477 BeginFrameArgs frame_args =
478 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
479 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args);
481 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
482 EXPECT_EQ(client_->begin_frame_args_sent_to_children().deadline,
483 frame_args.deadline);
486 TEST_F(SchedulerTest, VideoNeedsBeginFrames) {
487 scheduler_settings_.use_external_begin_frame_source = true;
488 SetUpScheduler(true);
490 scheduler_->SetVideoNeedsBeginFrames(true);
491 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
492 EXPECT_TRUE(client_->needs_begin_frames());
494 client_->Reset();
495 EXPECT_SCOPED(AdvanceFrame());
496 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
497 // WillBeginImplFrame is responsible for sending BeginFrames to video.
498 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
500 client_->Reset();
501 EXPECT_SCOPED(AdvanceFrame());
502 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
503 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
505 client_->Reset();
506 scheduler_->SetVideoNeedsBeginFrames(false);
507 EXPECT_NO_ACTION(client_);
509 client_->Reset();
510 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
511 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
512 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
513 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
514 EXPECT_FALSE(client_->needs_begin_frames());
517 TEST_F(SchedulerTest, RequestCommit) {
518 scheduler_settings_.use_external_begin_frame_source = true;
519 SetUpScheduler(true);
521 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
522 scheduler_->SetNeedsBeginMainFrame();
523 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
524 client_->Reset();
526 EXPECT_SCOPED(AdvanceFrame());
527 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
528 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
529 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
530 EXPECT_TRUE(client_->needs_begin_frames());
531 client_->Reset();
533 // If we don't swap on the deadline, we wait for the next BeginFrame.
534 task_runner().RunPendingTasks(); // Run posted deadline.
535 EXPECT_NO_ACTION(client_);
536 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
537 EXPECT_TRUE(client_->needs_begin_frames());
538 client_->Reset();
540 // NotifyReadyToCommit should trigger the commit.
541 scheduler_->NotifyBeginMainFrameStarted();
542 scheduler_->NotifyReadyToCommit();
543 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
544 EXPECT_TRUE(client_->needs_begin_frames());
545 client_->Reset();
547 // NotifyReadyToActivate should trigger the activation.
548 scheduler_->NotifyReadyToActivate();
549 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
550 EXPECT_TRUE(client_->needs_begin_frames());
551 client_->Reset();
553 // BeginImplFrame should prepare the draw.
554 EXPECT_SCOPED(AdvanceFrame());
555 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
556 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
557 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
558 EXPECT_TRUE(client_->needs_begin_frames());
559 client_->Reset();
561 // BeginImplFrame deadline should draw.
562 task_runner().RunPendingTasks(); // Run posted deadline.
563 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
564 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
565 EXPECT_TRUE(client_->needs_begin_frames());
566 client_->Reset();
568 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
569 // to avoid excessive toggles.
570 EXPECT_SCOPED(AdvanceFrame());
571 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
572 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
573 client_->Reset();
575 task_runner().RunPendingTasks(); // Run posted deadline.
576 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
577 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
578 client_->Reset();
581 TEST_F(SchedulerTest, RequestCommitAfterSetDeferCommit) {
582 scheduler_settings_.use_external_begin_frame_source = true;
583 SetUpScheduler(true);
585 scheduler_->SetDeferCommits(true);
587 scheduler_->SetNeedsBeginMainFrame();
588 EXPECT_NO_ACTION(client_);
590 client_->Reset();
591 task_runner().RunPendingTasks();
592 // There are no pending tasks or actions.
593 EXPECT_NO_ACTION(client_);
594 EXPECT_FALSE(client_->needs_begin_frames());
596 client_->Reset();
597 scheduler_->SetDeferCommits(false);
598 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
600 // Start new BeginMainFrame after defer commit is off.
601 client_->Reset();
602 EXPECT_SCOPED(AdvanceFrame());
603 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
604 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
605 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
608 TEST_F(SchedulerTest, DeferCommitWithRedraw) {
609 scheduler_settings_.use_external_begin_frame_source = true;
610 SetUpScheduler(true);
612 scheduler_->SetDeferCommits(true);
614 scheduler_->SetNeedsBeginMainFrame();
615 EXPECT_NO_ACTION(client_);
617 // The SetNeedsRedraw will override the SetDeferCommits(true), to allow a
618 // begin frame to be needed.
619 client_->Reset();
620 scheduler_->SetNeedsRedraw();
621 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
623 client_->Reset();
624 AdvanceFrame();
625 // BeginMainFrame is not sent during the defer commit is on.
626 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
627 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
629 client_->Reset();
630 task_runner().RunPendingTasks(); // Run posted deadline.
631 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
632 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
633 EXPECT_TRUE(client_->needs_begin_frames());
635 client_->Reset();
636 AdvanceFrame();
637 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
640 TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
641 scheduler_settings_.use_external_begin_frame_source = true;
642 SetUpScheduler(true);
644 // SetNeedsBeginMainFrame should begin the frame.
645 scheduler_->SetNeedsBeginMainFrame();
646 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
648 client_->Reset();
649 EXPECT_SCOPED(AdvanceFrame());
650 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
651 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
652 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
654 EXPECT_TRUE(client_->needs_begin_frames());
655 client_->Reset();
657 // Now SetNeedsBeginMainFrame again. Calling here means we need a second
658 // commit.
659 scheduler_->SetNeedsBeginMainFrame();
660 EXPECT_EQ(client_->num_actions_(), 0);
661 client_->Reset();
663 // Finish the first commit.
664 scheduler_->NotifyBeginMainFrameStarted();
665 scheduler_->NotifyReadyToCommit();
666 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
667 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
668 client_->Reset();
670 // Activate it.
671 scheduler_->NotifyReadyToActivate();
672 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
673 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
674 client_->Reset();
676 task_runner().RunPendingTasks(); // Run posted deadline.
677 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
678 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
679 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
681 // Because we just swapped, the Scheduler should also request the next
682 // BeginImplFrame from the OutputSurface.
683 EXPECT_TRUE(client_->needs_begin_frames());
684 client_->Reset();
685 // Since another commit is needed, the next BeginImplFrame should initiate
686 // the second commit.
687 EXPECT_SCOPED(AdvanceFrame());
688 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
689 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
690 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
691 client_->Reset();
693 // Finishing the commit before the deadline should post a new deadline task
694 // to trigger the deadline early.
695 scheduler_->NotifyBeginMainFrameStarted();
696 scheduler_->NotifyReadyToCommit();
697 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
698 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
699 client_->Reset();
700 scheduler_->NotifyReadyToActivate();
701 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
702 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
703 client_->Reset();
704 task_runner().RunPendingTasks(); // Run posted deadline.
705 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
706 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
707 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
708 EXPECT_TRUE(client_->needs_begin_frames());
709 client_->Reset();
711 // On the next BeginImplFrame, verify we go back to a quiescent state and
712 // no longer request BeginImplFrames.
713 EXPECT_SCOPED(AdvanceFrame());
714 task_runner().RunPendingTasks(); // Run posted deadline.
715 EXPECT_FALSE(client_->needs_begin_frames());
716 client_->Reset();
719 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
720 public:
721 SchedulerClientThatsetNeedsDrawInsideDraw()
722 : FakeSchedulerClient(), request_redraws_(false) {}
724 void SetRequestRedrawsInsideDraw(bool enable) { request_redraws_ = enable; }
726 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
727 // Only SetNeedsRedraw the first time this is called
728 if (request_redraws_) {
729 scheduler_->SetNeedsRedraw();
731 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
734 DrawResult ScheduledActionDrawAndSwapForced() override {
735 NOTREACHED();
736 return DRAW_SUCCESS;
739 private:
740 bool request_redraws_;
743 // Tests for two different situations:
744 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
745 // a ScheduledActionDrawAndSwap
746 // 2. the scheduler drawing twice inside a single tick
747 TEST_F(SchedulerTest, RequestRedrawInsideDraw) {
748 SchedulerClientThatsetNeedsDrawInsideDraw* client =
749 new SchedulerClientThatsetNeedsDrawInsideDraw;
750 scheduler_settings_.use_external_begin_frame_source = true;
751 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
752 client->SetRequestRedrawsInsideDraw(true);
754 scheduler_->SetNeedsRedraw();
755 EXPECT_TRUE(scheduler_->RedrawPending());
756 EXPECT_TRUE(client->needs_begin_frames());
757 EXPECT_EQ(0, client->num_draws());
759 EXPECT_SCOPED(AdvanceFrame());
760 task_runner().RunPendingTasks(); // Run posted deadline.
761 EXPECT_EQ(1, client->num_draws());
762 EXPECT_TRUE(scheduler_->RedrawPending());
763 EXPECT_TRUE(client->needs_begin_frames());
765 client->SetRequestRedrawsInsideDraw(false);
767 EXPECT_SCOPED(AdvanceFrame());
768 task_runner().RunPendingTasks(); // Run posted deadline.
769 EXPECT_EQ(2, client_->num_draws());
770 EXPECT_FALSE(scheduler_->RedrawPending());
771 EXPECT_TRUE(client->needs_begin_frames());
773 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
774 // swap.
775 EXPECT_SCOPED(AdvanceFrame());
776 task_runner().RunPendingTasks(); // Run posted deadline.
777 EXPECT_EQ(2, client->num_draws());
778 EXPECT_FALSE(scheduler_->RedrawPending());
779 EXPECT_FALSE(client->needs_begin_frames());
782 // Test that requesting redraw inside a failed draw doesn't lose the request.
783 TEST_F(SchedulerTest, RequestRedrawInsideFailedDraw) {
784 SchedulerClientThatsetNeedsDrawInsideDraw* client =
785 new SchedulerClientThatsetNeedsDrawInsideDraw;
786 scheduler_settings_.use_external_begin_frame_source = true;
787 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
789 client->SetRequestRedrawsInsideDraw(true);
790 client->SetDrawWillHappen(false);
792 scheduler_->SetNeedsRedraw();
793 EXPECT_TRUE(scheduler_->RedrawPending());
794 EXPECT_TRUE(client->needs_begin_frames());
795 EXPECT_EQ(0, client->num_draws());
797 // Fail the draw.
798 EXPECT_SCOPED(AdvanceFrame());
799 task_runner().RunPendingTasks(); // Run posted deadline.
800 EXPECT_EQ(1, client->num_draws());
802 // We have a commit pending and the draw failed, and we didn't lose the redraw
803 // request.
804 EXPECT_TRUE(scheduler_->CommitPending());
805 EXPECT_TRUE(scheduler_->RedrawPending());
806 EXPECT_TRUE(client->needs_begin_frames());
808 client->SetRequestRedrawsInsideDraw(false);
810 // Fail the draw again.
811 EXPECT_SCOPED(AdvanceFrame());
812 task_runner().RunPendingTasks(); // Run posted deadline.
813 EXPECT_EQ(2, client->num_draws());
814 EXPECT_TRUE(scheduler_->CommitPending());
815 EXPECT_TRUE(scheduler_->RedrawPending());
816 EXPECT_TRUE(client->needs_begin_frames());
818 // Draw successfully.
819 client->SetDrawWillHappen(true);
820 EXPECT_SCOPED(AdvanceFrame());
821 task_runner().RunPendingTasks(); // Run posted deadline.
822 EXPECT_EQ(3, client->num_draws());
823 EXPECT_TRUE(scheduler_->CommitPending());
824 EXPECT_FALSE(scheduler_->RedrawPending());
825 EXPECT_TRUE(client->needs_begin_frames());
828 class SchedulerClientThatSetNeedsBeginMainFrameInsideDraw
829 : public FakeSchedulerClient {
830 public:
831 SchedulerClientThatSetNeedsBeginMainFrameInsideDraw()
832 : set_needs_commit_on_next_draw_(false) {}
834 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
835 // Only SetNeedsBeginMainFrame the first time this is called
836 if (set_needs_commit_on_next_draw_) {
837 scheduler_->SetNeedsBeginMainFrame();
838 set_needs_commit_on_next_draw_ = false;
840 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
843 DrawResult ScheduledActionDrawAndSwapForced() override {
844 NOTREACHED();
845 return DRAW_SUCCESS;
848 void SetNeedsBeginMainFrameOnNextDraw() {
849 set_needs_commit_on_next_draw_ = true;
852 private:
853 bool set_needs_commit_on_next_draw_;
856 // Tests for the scheduler infinite-looping on SetNeedsBeginMainFrame requests
857 // that happen inside a ScheduledActionDrawAndSwap
858 TEST_F(SchedulerTest, RequestCommitInsideDraw) {
859 SchedulerClientThatSetNeedsBeginMainFrameInsideDraw* client =
860 new SchedulerClientThatSetNeedsBeginMainFrameInsideDraw;
862 scheduler_settings_.use_external_begin_frame_source = true;
863 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
865 EXPECT_FALSE(client->needs_begin_frames());
866 scheduler_->SetNeedsRedraw();
867 EXPECT_TRUE(scheduler_->RedrawPending());
868 EXPECT_EQ(0, client->num_draws());
869 EXPECT_TRUE(client->needs_begin_frames());
871 client->SetNeedsBeginMainFrameOnNextDraw();
872 EXPECT_SCOPED(AdvanceFrame());
873 client->SetNeedsBeginMainFrameOnNextDraw();
874 task_runner().RunPendingTasks(); // Run posted deadline.
875 EXPECT_EQ(1, client->num_draws());
876 EXPECT_TRUE(scheduler_->CommitPending());
877 EXPECT_TRUE(client->needs_begin_frames());
878 scheduler_->NotifyBeginMainFrameStarted();
879 scheduler_->NotifyReadyToCommit();
880 scheduler_->NotifyReadyToActivate();
882 EXPECT_SCOPED(AdvanceFrame());
883 task_runner().RunPendingTasks(); // Run posted deadline.
884 EXPECT_EQ(2, client->num_draws());
886 EXPECT_FALSE(scheduler_->RedrawPending());
887 EXPECT_FALSE(scheduler_->CommitPending());
888 EXPECT_TRUE(client->needs_begin_frames());
890 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
891 // swap.
892 EXPECT_SCOPED(AdvanceFrame());
893 task_runner().RunPendingTasks(); // Run posted deadline.
894 EXPECT_EQ(2, client->num_draws());
895 EXPECT_FALSE(scheduler_->RedrawPending());
896 EXPECT_FALSE(scheduler_->CommitPending());
897 EXPECT_FALSE(client->needs_begin_frames());
900 // Tests that when a draw fails then the pending commit should not be dropped.
901 TEST_F(SchedulerTest, RequestCommitInsideFailedDraw) {
902 SchedulerClientThatsetNeedsDrawInsideDraw* client =
903 new SchedulerClientThatsetNeedsDrawInsideDraw;
904 scheduler_settings_.use_external_begin_frame_source = true;
905 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
907 client->SetDrawWillHappen(false);
909 scheduler_->SetNeedsRedraw();
910 EXPECT_TRUE(scheduler_->RedrawPending());
911 EXPECT_TRUE(client->needs_begin_frames());
912 EXPECT_EQ(0, client->num_draws());
914 // Fail the draw.
915 EXPECT_SCOPED(AdvanceFrame());
916 task_runner().RunPendingTasks(); // Run posted deadline.
917 EXPECT_EQ(1, client->num_draws());
919 // We have a commit pending and the draw failed, and we didn't lose the commit
920 // request.
921 EXPECT_TRUE(scheduler_->CommitPending());
922 EXPECT_TRUE(scheduler_->RedrawPending());
923 EXPECT_TRUE(client->needs_begin_frames());
925 // Fail the draw again.
926 EXPECT_SCOPED(AdvanceFrame());
928 task_runner().RunPendingTasks(); // Run posted deadline.
929 EXPECT_EQ(2, client->num_draws());
930 EXPECT_TRUE(scheduler_->CommitPending());
931 EXPECT_TRUE(scheduler_->RedrawPending());
932 EXPECT_TRUE(client->needs_begin_frames());
934 // Draw successfully.
935 client->SetDrawWillHappen(true);
936 EXPECT_SCOPED(AdvanceFrame());
937 task_runner().RunPendingTasks(); // Run posted deadline.
938 EXPECT_EQ(3, client->num_draws());
939 EXPECT_TRUE(scheduler_->CommitPending());
940 EXPECT_FALSE(scheduler_->RedrawPending());
941 EXPECT_TRUE(client->needs_begin_frames());
944 TEST_F(SchedulerTest, NoSwapWhenDrawFails) {
945 SchedulerClientThatSetNeedsBeginMainFrameInsideDraw* client =
946 new SchedulerClientThatSetNeedsBeginMainFrameInsideDraw;
947 scheduler_settings_.use_external_begin_frame_source = true;
948 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
950 scheduler_->SetNeedsRedraw();
951 EXPECT_TRUE(scheduler_->RedrawPending());
952 EXPECT_TRUE(client->needs_begin_frames());
953 EXPECT_EQ(0, client->num_draws());
955 // Draw successfully, this starts a new frame.
956 client->SetNeedsBeginMainFrameOnNextDraw();
957 EXPECT_SCOPED(AdvanceFrame());
958 task_runner().RunPendingTasks(); // Run posted deadline.
959 EXPECT_EQ(1, client->num_draws());
961 scheduler_->SetNeedsRedraw();
962 EXPECT_TRUE(scheduler_->RedrawPending());
963 EXPECT_TRUE(client->needs_begin_frames());
965 // Fail to draw, this should not start a frame.
966 client->SetDrawWillHappen(false);
967 client->SetNeedsBeginMainFrameOnNextDraw();
968 EXPECT_SCOPED(AdvanceFrame());
969 task_runner().RunPendingTasks(); // Run posted deadline.
970 EXPECT_EQ(2, client->num_draws());
973 class SchedulerClientNeedsPrepareTilesInDraw : public FakeSchedulerClient {
974 public:
975 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
976 scheduler_->SetNeedsPrepareTiles();
977 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
981 // Test prepare tiles is independant of draws.
982 TEST_F(SchedulerTest, PrepareTiles) {
983 SchedulerClientNeedsPrepareTilesInDraw* client =
984 new SchedulerClientNeedsPrepareTilesInDraw;
985 scheduler_settings_.use_external_begin_frame_source = true;
986 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
988 // Request both draw and prepare tiles. PrepareTiles shouldn't
989 // be trigged until BeginImplFrame.
990 client->Reset();
991 scheduler_->SetNeedsPrepareTiles();
992 scheduler_->SetNeedsRedraw();
993 EXPECT_TRUE(scheduler_->RedrawPending());
994 EXPECT_TRUE(scheduler_->PrepareTilesPending());
995 EXPECT_TRUE(client->needs_begin_frames());
996 EXPECT_EQ(0, client->num_draws());
997 EXPECT_FALSE(client->HasAction("ScheduledActionPrepareTiles"));
998 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1000 // We have no immediate actions to perform, so the BeginImplFrame should post
1001 // the deadline task.
1002 client->Reset();
1003 EXPECT_SCOPED(AdvanceFrame());
1004 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1005 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1006 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1008 // On the deadline, he actions should have occured in the right order.
1009 client->Reset();
1010 task_runner().RunPendingTasks(); // Run posted deadline.
1011 EXPECT_EQ(1, client->num_draws());
1012 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1013 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1014 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1015 client->ActionIndex("ScheduledActionPrepareTiles"));
1016 EXPECT_FALSE(scheduler_->RedrawPending());
1017 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1018 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1020 // Request a draw. We don't need a PrepareTiles yet.
1021 client->Reset();
1022 scheduler_->SetNeedsRedraw();
1023 EXPECT_TRUE(scheduler_->RedrawPending());
1024 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1025 EXPECT_TRUE(client->needs_begin_frames());
1026 EXPECT_EQ(0, client->num_draws());
1028 // We have no immediate actions to perform, so the BeginImplFrame should post
1029 // the deadline task.
1030 client->Reset();
1031 EXPECT_SCOPED(AdvanceFrame());
1032 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1033 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1034 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1036 // Draw. The draw will trigger SetNeedsPrepareTiles, and
1037 // then the PrepareTiles action will be triggered after the Draw.
1038 // Afterwards, neither a draw nor PrepareTiles are pending.
1039 client->Reset();
1040 task_runner().RunPendingTasks(); // Run posted deadline.
1041 EXPECT_EQ(1, client->num_draws());
1042 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1043 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1044 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1045 client->ActionIndex("ScheduledActionPrepareTiles"));
1046 EXPECT_FALSE(scheduler_->RedrawPending());
1047 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1048 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1050 // We need a BeginImplFrame where we don't swap to go idle.
1051 client->Reset();
1052 EXPECT_SCOPED(AdvanceFrame());
1053 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1054 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1055 client->Reset();
1056 task_runner().RunPendingTasks(); // Run posted deadline.
1057 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1058 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1059 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1060 EXPECT_EQ(0, client->num_draws());
1062 // Now trigger a PrepareTiles outside of a draw. We will then need
1063 // a begin-frame for the PrepareTiles, but we don't need a draw.
1064 client->Reset();
1065 EXPECT_FALSE(client->needs_begin_frames());
1066 scheduler_->SetNeedsPrepareTiles();
1067 EXPECT_TRUE(client->needs_begin_frames());
1068 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1069 EXPECT_FALSE(scheduler_->RedrawPending());
1071 // BeginImplFrame. There will be no draw, only PrepareTiles.
1072 client->Reset();
1073 EXPECT_SCOPED(AdvanceFrame());
1074 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1075 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1076 client->Reset();
1077 task_runner().RunPendingTasks(); // Run posted deadline.
1078 EXPECT_EQ(0, client->num_draws());
1079 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1080 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1081 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1084 // Test that PrepareTiles only happens once per frame. If an external caller
1085 // initiates it, then the state machine should not PrepareTiles on that frame.
1086 TEST_F(SchedulerTest, PrepareTilesOncePerFrame) {
1087 scheduler_settings_.use_external_begin_frame_source = true;
1088 SetUpScheduler(true);
1090 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
1091 // again.
1092 scheduler_->SetNeedsPrepareTiles();
1093 scheduler_->SetNeedsRedraw();
1094 client_->Reset();
1095 EXPECT_SCOPED(AdvanceFrame());
1096 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1097 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1098 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1100 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1101 scheduler_->WillPrepareTiles();
1102 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1103 EXPECT_FALSE(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_->PrepareTilesPending());
1112 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1114 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1115 scheduler_->SetNeedsPrepareTiles();
1116 scheduler_->SetNeedsRedraw();
1117 client_->Reset();
1118 EXPECT_SCOPED(AdvanceFrame());
1119 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1120 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1121 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1123 client_->Reset();
1124 task_runner().RunPendingTasks(); // Run posted deadline.
1125 EXPECT_EQ(1, client_->num_draws());
1126 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1127 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1128 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1129 client_->ActionIndex("ScheduledActionPrepareTiles"));
1130 EXPECT_FALSE(scheduler_->RedrawPending());
1131 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1132 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1134 // If we get another DidPrepareTiles within the same frame, we should
1135 // not PrepareTiles on the next frame.
1136 scheduler_->WillPrepareTiles();
1137 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
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 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1148 client_->Reset();
1149 task_runner().RunPendingTasks(); // Run posted deadline.
1150 EXPECT_EQ(1, client_->num_draws());
1151 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1152 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1153 EXPECT_FALSE(scheduler_->RedrawPending());
1154 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1156 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1157 // frame. This verifies we don't alternate calling PrepareTiles once and
1158 // twice.
1159 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1160 scheduler_->WillPrepareTiles();
1161 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1162 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1163 scheduler_->SetNeedsPrepareTiles();
1164 scheduler_->SetNeedsRedraw();
1165 client_->Reset();
1166 EXPECT_SCOPED(AdvanceFrame());
1167 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1168 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1169 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1171 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1173 client_->Reset();
1174 task_runner().RunPendingTasks(); // Run posted deadline.
1175 EXPECT_EQ(1, client_->num_draws());
1176 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1177 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1178 EXPECT_FALSE(scheduler_->RedrawPending());
1179 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1181 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1182 scheduler_->SetNeedsPrepareTiles();
1183 scheduler_->SetNeedsRedraw();
1184 client_->Reset();
1185 EXPECT_SCOPED(AdvanceFrame());
1186 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1187 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1188 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1190 client_->Reset();
1191 task_runner().RunPendingTasks(); // Run posted deadline.
1192 EXPECT_EQ(1, client_->num_draws());
1193 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1194 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1195 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1196 client_->ActionIndex("ScheduledActionPrepareTiles"));
1197 EXPECT_FALSE(scheduler_->RedrawPending());
1198 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1199 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1202 TEST_F(SchedulerTest, PrepareTilesFunnelResetOnVisibilityChange) {
1203 scoped_ptr<SchedulerClientNeedsPrepareTilesInDraw> client =
1204 make_scoped_ptr(new SchedulerClientNeedsPrepareTilesInDraw);
1205 scheduler_settings_.use_external_begin_frame_source = true;
1206 SetUpScheduler(client.Pass(), true);
1208 // Simulate a few visibility changes and associated PrepareTiles.
1209 for (int i = 0; i < 10; i++) {
1210 scheduler_->SetVisible(false);
1211 scheduler_->WillPrepareTiles();
1212 scheduler_->DidPrepareTiles();
1214 scheduler_->SetVisible(true);
1215 scheduler_->WillPrepareTiles();
1216 scheduler_->DidPrepareTiles();
1219 client_->Reset();
1220 scheduler_->SetNeedsRedraw();
1221 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1223 client_->Reset();
1224 AdvanceFrame();
1225 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1226 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1227 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1229 client_->Reset();
1230 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1231 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1232 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
1233 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 1, 2);
1236 TEST_F(SchedulerTest, TriggerBeginFrameDeadlineEarly) {
1237 SchedulerClientNeedsPrepareTilesInDraw* client =
1238 new SchedulerClientNeedsPrepareTilesInDraw;
1239 scheduler_settings_.use_external_begin_frame_source = true;
1240 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1242 scheduler_->SetNeedsRedraw();
1243 EXPECT_SCOPED(AdvanceFrame());
1245 // The deadline should be zero since there is no work other than drawing
1246 // pending.
1247 EXPECT_EQ(base::TimeTicks(), client->posted_begin_impl_frame_deadline());
1250 TEST_F(SchedulerTest, WaitForReadyToDrawDoNotPostDeadline) {
1251 SchedulerClientNeedsPrepareTilesInDraw* client =
1252 new SchedulerClientNeedsPrepareTilesInDraw;
1253 scheduler_settings_.use_external_begin_frame_source = true;
1254 scheduler_settings_.commit_to_active_tree = true;
1255 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1257 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
1258 scheduler_->SetNeedsBeginMainFrame();
1259 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1260 client_->Reset();
1262 // Begin new frame.
1263 EXPECT_SCOPED(AdvanceFrame());
1264 scheduler_->NotifyBeginMainFrameStarted();
1265 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1266 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1268 client_->Reset();
1269 scheduler_->NotifyReadyToCommit();
1270 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1272 client_->Reset();
1273 scheduler_->NotifyReadyToActivate();
1274 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
1276 // Scheduler won't post deadline in the mode.
1277 client_->Reset();
1278 task_runner().RunPendingTasks(); // Try to run posted deadline.
1279 // There is no posted deadline.
1280 EXPECT_NO_ACTION(client_);
1282 // Scheduler received ready to draw signal, and posted deadline.
1283 scheduler_->NotifyReadyToDraw();
1284 client_->Reset();
1285 task_runner().RunPendingTasks(); // Run posted deadline.
1286 EXPECT_EQ(1, client_->num_draws());
1287 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1290 TEST_F(SchedulerTest, WaitForReadyToDrawCancelledWhenLostOutputSurface) {
1291 SchedulerClientNeedsPrepareTilesInDraw* client =
1292 new SchedulerClientNeedsPrepareTilesInDraw;
1293 scheduler_settings_.use_external_begin_frame_source = true;
1294 scheduler_settings_.commit_to_active_tree = true;
1295 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1297 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
1298 scheduler_->SetNeedsBeginMainFrame();
1299 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1300 client_->Reset();
1302 // Begin new frame.
1303 EXPECT_SCOPED(AdvanceFrame());
1304 scheduler_->NotifyBeginMainFrameStarted();
1305 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1306 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1308 client_->Reset();
1309 scheduler_->NotifyReadyToCommit();
1310 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1312 client_->Reset();
1313 scheduler_->NotifyReadyToActivate();
1314 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
1316 // Scheduler won't post deadline in the mode.
1317 client_->Reset();
1318 task_runner().RunPendingTasks(); // Try to run posted deadline.
1319 // There is no posted deadline.
1320 EXPECT_NO_ACTION(client_);
1322 // Scheduler loses output surface, and stops waiting for ready to draw signal.
1323 client_->Reset();
1324 scheduler_->DidLoseOutputSurface();
1325 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1326 task_runner().RunPendingTasks(); // Run posted deadline.
1327 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
1328 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
1329 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
1332 void SchedulerTest::CheckMainFrameSkippedAfterLateCommit(
1333 bool expect_send_begin_main_frame) {
1334 // Impl thread hits deadline before commit finishes.
1335 scheduler_->SetNeedsBeginMainFrame();
1336 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1337 EXPECT_SCOPED(AdvanceFrame());
1338 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1339 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1340 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1341 scheduler_->NotifyBeginMainFrameStarted();
1342 scheduler_->NotifyReadyToCommit();
1343 scheduler_->NotifyReadyToActivate();
1344 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5);
1345 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5);
1346 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5);
1347 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5);
1348 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 4, 5);
1349 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1351 client_->Reset();
1352 scheduler_->SetNeedsBeginMainFrame();
1353 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1354 EXPECT_SCOPED(AdvanceFrame());
1355 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1356 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1357 EXPECT_EQ(expect_send_begin_main_frame,
1358 scheduler_->MainThreadMissedLastDeadline());
1359 EXPECT_EQ(expect_send_begin_main_frame,
1360 client_->HasAction("ScheduledActionSendBeginMainFrame"));
1363 TEST_F(SchedulerTest, MainFrameSkippedAfterLateCommit) {
1364 scheduler_settings_.use_external_begin_frame_source = true;
1365 SetUpScheduler(true);
1367 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1368 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1370 bool expect_send_begin_main_frame = false;
1371 EXPECT_SCOPED(
1372 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1375 TEST_F(SchedulerTest,
1376 MainFrameNotSkippedAfterLateCommitInPreferImplLatencyMode) {
1377 scheduler_settings_.use_external_begin_frame_source = true;
1378 SetUpScheduler(true);
1379 scheduler_->SetImplLatencyTakesPriority(true);
1381 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1382 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1384 bool expect_send_begin_main_frame = true;
1385 EXPECT_SCOPED(
1386 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1389 TEST_F(SchedulerTest,
1390 MainFrameNotSkippedAfterLateCommit_CommitEstimateTooLong) {
1391 scheduler_settings_.use_external_begin_frame_source = true;
1392 SetUpScheduler(true);
1393 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1394 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1395 auto slow_duration = base::TimeDelta::FromSeconds(1);
1396 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate(
1397 slow_duration);
1399 bool expect_send_begin_main_frame = true;
1400 EXPECT_SCOPED(
1401 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1404 TEST_F(SchedulerTest,
1405 MainFrameNotSkippedAfterLateCommit_ReadyToActivateEstimateTooLong) {
1406 scheduler_settings_.use_external_begin_frame_source = true;
1407 SetUpScheduler(true);
1408 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1409 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1410 auto slow_duration = base::TimeDelta::FromSeconds(1);
1411 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate(
1412 slow_duration);
1414 bool expect_send_begin_main_frame = true;
1415 EXPECT_SCOPED(
1416 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1419 TEST_F(SchedulerTest,
1420 MainFrameNotSkippedAfterLateCommit_ActivateEstimateTooLong) {
1421 scheduler_settings_.use_external_begin_frame_source = true;
1422 SetUpScheduler(true);
1423 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1424 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1425 auto slow_duration = base::TimeDelta::FromSeconds(1);
1426 fake_compositor_timing_history_->SetActivateDurationEstimate(slow_duration);
1428 bool expect_send_begin_main_frame = true;
1429 EXPECT_SCOPED(
1430 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1433 TEST_F(SchedulerTest, MainFrameNotSkippedAfterLateCommit_DrawEstimateTooLong) {
1434 scheduler_settings_.use_external_begin_frame_source = true;
1435 SetUpScheduler(true);
1436 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1437 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1438 auto slow_duration = base::TimeDelta::FromSeconds(1);
1439 fake_compositor_timing_history_->SetDrawDurationEstimate(slow_duration);
1441 bool expect_send_begin_main_frame = true;
1442 EXPECT_SCOPED(
1443 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1446 void SchedulerTest::ImplFrameSkippedAfterLateSwapAck(
1447 bool swap_ack_before_deadline) {
1448 // To get into a high latency state, this test disables automatic swap acks.
1449 scheduler_->SetMaxSwapsPending(1);
1450 client_->SetAutomaticSwapAck(false);
1452 // Draw and swap for first BeginFrame
1453 client_->Reset();
1454 scheduler_->SetNeedsBeginMainFrame();
1455 scheduler_->SetNeedsRedraw();
1456 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1457 SendNextBeginFrame();
1458 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 4);
1459 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 4);
1460 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4);
1461 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 4);
1463 client_->Reset();
1464 scheduler_->NotifyBeginMainFrameStarted();
1465 scheduler_->NotifyReadyToCommit();
1466 scheduler_->NotifyReadyToActivate();
1467 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1468 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1469 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4);
1470 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4);
1471 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4);
1472 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1474 // Verify we skip every other frame if the swap ack consistently
1475 // comes back late.
1476 for (int i = 0; i < 10; i++) {
1477 // Not calling scheduler_->DidSwapBuffersComplete() until after next
1478 // BeginImplFrame puts the impl thread in high latency mode.
1479 client_->Reset();
1480 scheduler_->SetNeedsBeginMainFrame();
1481 scheduler_->SetNeedsRedraw();
1482 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1483 SendNextBeginFrame();
1484 // Verify that we skip the BeginImplFrame
1485 EXPECT_NO_ACTION(client_);
1486 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1487 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1489 // Verify that we do not perform any actions after we are no longer
1490 // swap throttled.
1491 client_->Reset();
1492 if (swap_ack_before_deadline) {
1493 // It shouldn't matter if the swap ack comes back before the deadline...
1494 scheduler_->DidSwapBuffersComplete();
1495 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1496 } else {
1497 // ... or after the deadline.
1498 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1499 scheduler_->DidSwapBuffersComplete();
1501 EXPECT_NO_ACTION(client_);
1503 // Verify that we start the next BeginImplFrame and continue normally
1504 // after having just skipped a BeginImplFrame.
1505 client_->Reset();
1506 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1507 SendNextBeginFrame();
1508 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
1509 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
1510 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3);
1512 client_->Reset();
1513 scheduler_->NotifyBeginMainFrameStarted();
1514 scheduler_->NotifyReadyToCommit();
1515 scheduler_->NotifyReadyToActivate();
1516 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1517 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4);
1518 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4);
1519 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4);
1520 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1524 TEST_F(SchedulerTest,
1525 ImplFrameSkippedAfterLateSwapAck_FastEstimates_SwapAckThenDeadline) {
1526 scheduler_settings_.use_external_begin_frame_source = true;
1527 SetUpScheduler(true);
1529 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1530 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1532 bool swap_ack_before_deadline = true;
1533 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline));
1536 TEST_F(SchedulerTest,
1537 ImplFrameSkippedAfterLateSwapAck_FastEstimates_DeadlineThenSwapAck) {
1538 scheduler_settings_.use_external_begin_frame_source = true;
1539 SetUpScheduler(true);
1541 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1542 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1544 bool swap_ack_before_deadline = false;
1545 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline));
1548 TEST_F(SchedulerTest,
1549 ImplFrameSkippedAfterLateSwapAck_ImplLatencyTakesPriority) {
1550 scheduler_settings_.use_external_begin_frame_source = true;
1551 SetUpScheduler(true);
1553 // Even if every estimate related to the main thread is slow, we should
1554 // still expect to recover impl thread latency if the draw is fast and we
1555 // are in impl latency takes priority.
1556 scheduler_->SetImplLatencyTakesPriority(true);
1557 auto slow_duration = base::TimeDelta::FromSeconds(1);
1558 fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration);
1559 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1560 fake_compositor_timing_history_->SetDrawDurationEstimate(fast_duration);
1562 bool swap_ack_before_deadline = false;
1563 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline));
1566 TEST_F(SchedulerTest,
1567 ImplFrameSkippedAfterLateSwapAck_OnlyImplSideUpdatesExpected) {
1568 // This tests that we recover impl thread latency when there are no commits.
1569 scheduler_settings_.use_external_begin_frame_source = true;
1570 SetUpScheduler(true);
1572 // To get into a high latency state, this test disables automatic swap acks.
1573 scheduler_->SetMaxSwapsPending(1);
1574 client_->SetAutomaticSwapAck(false);
1576 // Even if every estimate related to the main thread is slow, we should
1577 // still expect to recover impl thread latency if there are no commits from
1578 // the main thread.
1579 auto slow_duration = base::TimeDelta::FromSeconds(1);
1580 fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration);
1581 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1582 fake_compositor_timing_history_->SetDrawDurationEstimate(fast_duration);
1584 // Draw and swap for first BeginFrame
1585 client_->Reset();
1586 scheduler_->SetNeedsRedraw();
1587 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1588 SendNextBeginFrame();
1589 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3);
1590 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3);
1591 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 3);
1593 client_->Reset();
1594 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1595 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1596 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
1598 // Verify we skip every other frame if the swap ack consistently
1599 // comes back late.
1600 for (int i = 0; i < 10; i++) {
1601 // Not calling scheduler_->DidSwapBuffersComplete() until after next
1602 // BeginImplFrame puts the impl thread in high latency mode.
1603 client_->Reset();
1604 scheduler_->SetNeedsRedraw();
1605 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1606 SendNextBeginFrame();
1607 // Verify that we skip the BeginImplFrame
1608 EXPECT_NO_ACTION(client_);
1609 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1610 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1612 // Verify that we do not perform any actions after we are no longer
1613 // swap throttled.
1614 client_->Reset();
1615 scheduler_->DidSwapBuffersComplete();
1616 EXPECT_NO_ACTION(client_);
1618 // Verify that we start the next BeginImplFrame and continue normally
1619 // after having just skipped a BeginImplFrame.
1620 client_->Reset();
1621 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1622 SendNextBeginFrame();
1623 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1624 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1626 client_->Reset();
1627 // Deadline should be immediate.
1628 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1629 task_runner().RunUntilTime(now_src_->NowTicks());
1630 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1631 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
1635 void SchedulerTest::ImplFrameIsNotSkippedAfterLateSwapAck() {
1636 // To get into a high latency state, this test disables automatic swap acks.
1637 scheduler_->SetMaxSwapsPending(1);
1638 client_->SetAutomaticSwapAck(false);
1640 // Draw and swap for first BeginFrame
1641 client_->Reset();
1642 scheduler_->SetNeedsBeginMainFrame();
1643 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1644 SendNextBeginFrame();
1645 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3);
1646 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3);
1647 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3);
1649 client_->Reset();
1650 scheduler_->NotifyBeginMainFrameStarted();
1651 scheduler_->NotifyReadyToCommit();
1652 scheduler_->NotifyReadyToActivate();
1653 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1654 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1655 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4);
1656 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4);
1657 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4);
1658 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1660 // Verify impl thread consistently operates in high latency mode
1661 // without skipping any frames.
1662 for (int i = 0; i < 10; i++) {
1663 // Not calling scheduler_->DidSwapBuffersComplete() until after next frame
1664 // puts the impl thread in high latency mode.
1665 client_->Reset();
1666 scheduler_->SetNeedsBeginMainFrame();
1667 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1668 SendNextBeginFrame();
1669 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
1670 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1671 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1673 client_->Reset();
1674 scheduler_->DidSwapBuffersComplete();
1675 scheduler_->NotifyBeginMainFrameStarted();
1676 scheduler_->NotifyReadyToCommit();
1677 scheduler_->NotifyReadyToActivate();
1678 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1680 // Verify that we don't skip the actions of the BeginImplFrame
1681 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 0, 5);
1682 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 5);
1683 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 2, 5);
1684 EXPECT_ACTION("ScheduledActionAnimate", client_, 3, 5);
1685 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 5);
1689 TEST_F(SchedulerTest,
1690 ImplFrameIsNotSkippedAfterLateSwapAck_CommitEstimateTooLong) {
1691 scheduler_settings_.use_external_begin_frame_source = true;
1692 SetUpScheduler(true);
1693 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1694 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1695 auto slow_duration = base::TimeDelta::FromSeconds(1);
1696 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate(
1697 slow_duration);
1698 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck());
1701 TEST_F(SchedulerTest,
1702 ImplFrameIsNotSkippedAfterLateSwapAck_ReadyToActivateEstimateTooLong) {
1703 scheduler_settings_.use_external_begin_frame_source = true;
1704 SetUpScheduler(true);
1705 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1706 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1707 auto slow_duration = base::TimeDelta::FromSeconds(1);
1708 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate(
1709 slow_duration);
1710 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck());
1713 TEST_F(SchedulerTest,
1714 ImplFrameIsNotSkippedAfterLateSwapAck_ActivateEstimateTooLong) {
1715 scheduler_settings_.use_external_begin_frame_source = true;
1716 SetUpScheduler(true);
1717 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1718 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1719 auto slow_duration = base::TimeDelta::FromSeconds(1);
1720 fake_compositor_timing_history_->SetActivateDurationEstimate(slow_duration);
1721 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck());
1724 TEST_F(SchedulerTest,
1725 ImplFrameIsNotSkippedAfterLateSwapAck_DrawEstimateTooLong) {
1726 scheduler_settings_.use_external_begin_frame_source = true;
1727 SetUpScheduler(true);
1728 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1729 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1730 auto slow_duration = base::TimeDelta::FromSeconds(1);
1731 fake_compositor_timing_history_->SetDrawDurationEstimate(slow_duration);
1732 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck());
1735 TEST_F(SchedulerTest,
1736 MainFrameThenImplFrameSkippedAfterLateCommitAndLateSwapAck) {
1737 // Set up client with custom estimates.
1738 // This test starts off with expensive estimates to prevent latency recovery
1739 // initially, then lowers the estimates to enable it once both the main
1740 // and impl threads are in a high latency mode.
1741 scheduler_settings_.use_external_begin_frame_source = true;
1742 SetUpScheduler(true);
1744 auto slow_duration = base::TimeDelta::FromSeconds(1);
1745 fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration);
1747 // To get into a high latency state, this test disables automatic swap acks.
1748 scheduler_->SetMaxSwapsPending(1);
1749 client_->SetAutomaticSwapAck(false);
1751 // Impl thread hits deadline before commit finishes to make
1752 // MainThreadMissedLastDeadline true
1753 client_->Reset();
1754 scheduler_->SetNeedsBeginMainFrame();
1755 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1756 EXPECT_SCOPED(AdvanceFrame());
1757 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1758 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1759 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1760 scheduler_->NotifyBeginMainFrameStarted();
1761 scheduler_->NotifyReadyToCommit();
1762 scheduler_->NotifyReadyToActivate();
1763 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1765 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5);
1766 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5);
1767 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5);
1768 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5);
1769 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 4, 5);
1771 // Draw and swap for first commit, start second commit.
1772 client_->Reset();
1773 scheduler_->SetNeedsBeginMainFrame();
1774 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1775 EXPECT_SCOPED(AdvanceFrame());
1776 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1777 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1778 scheduler_->NotifyBeginMainFrameStarted();
1779 scheduler_->NotifyReadyToCommit();
1780 scheduler_->NotifyReadyToActivate();
1782 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6);
1783 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 6);
1784 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 6);
1785 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 6);
1786 EXPECT_ACTION("ScheduledActionCommit", client_, 4, 6);
1787 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 5, 6);
1789 // Don't call scheduler_->DidSwapBuffersComplete() until after next frame
1790 // to put the impl thread in a high latency mode.
1791 client_->Reset();
1792 scheduler_->SetNeedsBeginMainFrame();
1793 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1794 EXPECT_SCOPED(AdvanceFrame());
1795 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1796 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1798 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1799 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1800 // Note: BeginMainFrame and swap are skipped here because of
1801 // swap ack backpressure, not because of latency recovery.
1802 EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame"));
1803 EXPECT_FALSE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1804 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1806 // Lower estimates so that the scheduler will attempt latency recovery.
1807 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1808 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1810 // Now that both threads are in a high latency mode, make sure we
1811 // skip the BeginMainFrame, then the BeginImplFrame, but not both
1812 // at the same time.
1814 // Verify we skip BeginMainFrame first.
1815 client_->Reset();
1816 // Previous commit request is still outstanding.
1817 EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
1818 EXPECT_TRUE(scheduler_->SwapThrottled());
1819 SendNextBeginFrame();
1820 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1821 scheduler_->DidSwapBuffersComplete();
1822 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1824 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1825 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
1826 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
1827 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3);
1829 // Verify we skip the BeginImplFrame second.
1830 client_->Reset();
1831 // Previous commit request is still outstanding.
1832 EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
1833 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1834 SendNextBeginFrame();
1835 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1836 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1837 scheduler_->DidSwapBuffersComplete();
1838 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1840 EXPECT_NO_ACTION(client_);
1842 // Then verify we operate in a low latency mode.
1843 client_->Reset();
1844 // Previous commit request is still outstanding.
1845 EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
1846 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1847 SendNextBeginFrame();
1848 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1849 scheduler_->NotifyBeginMainFrameStarted();
1850 scheduler_->NotifyReadyToCommit();
1851 scheduler_->NotifyReadyToActivate();
1852 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1853 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1854 scheduler_->DidSwapBuffersComplete();
1855 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1857 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6);
1858 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 6);
1859 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 6);
1860 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 3, 6);
1861 EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 6);
1862 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 5, 6);
1865 TEST_F(
1866 SchedulerTest,
1867 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) {
1868 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1869 // thread. This prevents the scheduler from receiving any pending swap acks.
1871 scheduler_settings_.use_external_begin_frame_source = true;
1872 scheduler_settings_.main_frame_while_swap_throttled_enabled = true;
1873 SetUpScheduler(true);
1875 // Disables automatic swap acks so this test can force swap ack throttling
1876 // to simulate a blocked Browser ui thread.
1877 scheduler_->SetMaxSwapsPending(1);
1878 client_->SetAutomaticSwapAck(false);
1880 // Get a new active tree in main-thread high latency mode and put us
1881 // in a swap throttled state.
1882 client_->Reset();
1883 EXPECT_FALSE(scheduler_->CommitPending());
1884 scheduler_->SetNeedsBeginMainFrame();
1885 scheduler_->SetNeedsRedraw();
1886 EXPECT_SCOPED(AdvanceFrame());
1887 EXPECT_TRUE(scheduler_->CommitPending());
1888 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1889 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1890 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1891 scheduler_->NotifyBeginMainFrameStarted();
1892 scheduler_->NotifyReadyToCommit();
1893 scheduler_->NotifyReadyToActivate();
1894 EXPECT_FALSE(scheduler_->CommitPending());
1895 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 7);
1896 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 7);
1897 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 7);
1898 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 7);
1899 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 7);
1900 EXPECT_ACTION("ScheduledActionCommit", client_, 5, 7);
1901 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 6, 7);
1903 // Make sure that we can finish the next commit even while swap throttled.
1904 client_->Reset();
1905 EXPECT_FALSE(scheduler_->CommitPending());
1906 scheduler_->SetNeedsBeginMainFrame();
1907 EXPECT_SCOPED(AdvanceFrame());
1908 scheduler_->NotifyBeginMainFrameStarted();
1909 scheduler_->NotifyReadyToCommit();
1910 scheduler_->NotifyReadyToActivate();
1911 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1912 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1913 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1914 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 5);
1915 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 5);
1916 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5);
1917 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5);
1918 EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 5);
1920 // Make sure we do not send a BeginMainFrame while swap throttled and
1921 // we have both a pending tree and an active tree.
1922 client_->Reset();
1923 EXPECT_FALSE(scheduler_->CommitPending());
1924 scheduler_->SetNeedsBeginMainFrame();
1925 EXPECT_SCOPED(AdvanceFrame());
1926 EXPECT_FALSE(scheduler_->CommitPending());
1927 task_runner().RunPendingTasks(); // Run posted deadline.
1928 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1929 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1932 TEST_F(SchedulerTest,
1933 Deadlock_NoBeginMainFrameWhileSwapTrottledAndPipelineFull) {
1934 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1935 // thread. This prevents the scheduler from receiving any pending swap acks.
1937 // This particular test makes sure we do not send a BeginMainFrame while
1938 // swap trottled and we have a pending tree and active tree that
1939 // still needs to be drawn for the first time.
1941 scheduler_settings_.use_external_begin_frame_source = true;
1942 scheduler_settings_.main_frame_while_swap_throttled_enabled = true;
1943 scheduler_settings_.main_frame_before_activation_enabled = true;
1944 SetUpScheduler(true);
1946 // Disables automatic swap acks so this test can force swap ack throttling
1947 // to simulate a blocked Browser ui thread.
1948 scheduler_->SetMaxSwapsPending(1);
1949 client_->SetAutomaticSwapAck(false);
1951 // Start a new commit in main-thread high latency mode and hold off on
1952 // activation.
1953 client_->Reset();
1954 EXPECT_FALSE(scheduler_->CommitPending());
1955 scheduler_->SetNeedsBeginMainFrame();
1956 scheduler_->SetNeedsRedraw();
1957 EXPECT_SCOPED(AdvanceFrame());
1958 EXPECT_TRUE(scheduler_->CommitPending());
1959 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1960 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1961 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1962 scheduler_->DidSwapBuffersComplete();
1963 scheduler_->NotifyBeginMainFrameStarted();
1964 scheduler_->NotifyReadyToCommit();
1965 EXPECT_FALSE(scheduler_->CommitPending());
1966 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 6);
1967 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 6);
1968 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 6);
1969 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 6);
1970 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 6);
1971 EXPECT_ACTION("ScheduledActionCommit", client_, 5, 6);
1973 // Start another commit while we still have aa pending tree.
1974 // Enter a swap throttled state.
1975 client_->Reset();
1976 EXPECT_FALSE(scheduler_->CommitPending());
1977 scheduler_->SetNeedsBeginMainFrame();
1978 scheduler_->SetNeedsRedraw();
1979 EXPECT_SCOPED(AdvanceFrame());
1980 EXPECT_TRUE(scheduler_->CommitPending());
1981 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1982 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1983 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1984 scheduler_->NotifyBeginMainFrameStarted();
1985 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4);
1986 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4);
1987 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4);
1988 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1990 // Can't commit yet because there's still a pending tree.
1991 client_->Reset();
1992 scheduler_->NotifyReadyToCommit();
1993 EXPECT_NO_ACTION(client_);
1995 // Activate the pending tree, which also unblocks the commit immediately.
1996 client_->Reset();
1997 scheduler_->NotifyReadyToActivate();
1998 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 2);
1999 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 2);
2001 // Make sure we do not send a BeginMainFrame while swap throttled and
2002 // we have both a pending tree and an active tree that still needs
2003 // it's first draw.
2004 client_->Reset();
2005 EXPECT_FALSE(scheduler_->CommitPending());
2006 scheduler_->SetNeedsBeginMainFrame();
2007 EXPECT_SCOPED(AdvanceFrame());
2008 EXPECT_FALSE(scheduler_->CommitPending());
2009 task_runner().RunPendingTasks(); // Run posted deadline.
2010 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2011 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2014 TEST_F(
2015 SchedulerTest,
2016 CommitMakesProgressWhenIdleAndHasPendingTreeAndActiveTreeNeedsFirstDraw) {
2017 // This verifies we don't block commits longer than we need to
2018 // for performance reasons - not deadlock reasons.
2020 // Since we are simulating a long commit, set up a client with draw duration
2021 // estimates that prevent skipping main frames to get to low latency mode.
2022 scheduler_settings_.use_external_begin_frame_source = true;
2023 scheduler_settings_.main_frame_while_swap_throttled_enabled = true;
2024 scheduler_settings_.main_frame_before_activation_enabled = true;
2025 SetUpScheduler(true);
2027 // Disables automatic swap acks so this test can force swap ack throttling
2028 // to simulate a blocked Browser ui thread.
2029 scheduler_->SetMaxSwapsPending(1);
2030 client_->SetAutomaticSwapAck(false);
2032 // Start a new commit in main-thread high latency mode and hold off on
2033 // activation.
2034 client_->Reset();
2035 EXPECT_FALSE(scheduler_->CommitPending());
2036 scheduler_->SetNeedsBeginMainFrame();
2037 scheduler_->SetNeedsRedraw();
2038 EXPECT_SCOPED(AdvanceFrame());
2039 EXPECT_TRUE(scheduler_->CommitPending());
2040 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2041 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2042 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2043 scheduler_->DidSwapBuffersComplete();
2044 scheduler_->NotifyBeginMainFrameStarted();
2045 scheduler_->NotifyReadyToCommit();
2046 EXPECT_FALSE(scheduler_->CommitPending());
2047 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 6);
2048 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 6);
2049 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 6);
2050 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 6);
2051 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 6);
2052 EXPECT_ACTION("ScheduledActionCommit", client_, 5, 6);
2054 // Start another commit while we still have an active tree.
2055 client_->Reset();
2056 EXPECT_FALSE(scheduler_->CommitPending());
2057 scheduler_->SetNeedsBeginMainFrame();
2058 scheduler_->SetNeedsRedraw();
2059 EXPECT_SCOPED(AdvanceFrame());
2060 EXPECT_TRUE(scheduler_->CommitPending());
2061 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2062 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2063 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2064 scheduler_->DidSwapBuffersComplete();
2065 scheduler_->NotifyBeginMainFrameStarted();
2066 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4);
2067 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4);
2068 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4);
2069 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
2071 // Can't commit yet because there's still a pending tree.
2072 client_->Reset();
2073 scheduler_->NotifyReadyToCommit();
2074 EXPECT_NO_ACTION(client_);
2076 // Activate the pending tree, which also unblocks the commit immediately
2077 // while we are in an idle state.
2078 client_->Reset();
2079 scheduler_->NotifyReadyToActivate();
2080 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 2);
2081 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 2);
2084 TEST_F(SchedulerTest, BeginRetroFrame) {
2085 scheduler_settings_.use_external_begin_frame_source = true;
2086 SetUpScheduler(true);
2088 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2089 scheduler_->SetNeedsBeginMainFrame();
2090 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2091 client_->Reset();
2093 // Create a BeginFrame with a long deadline to avoid race conditions.
2094 // This is the first BeginFrame, which will be handled immediately.
2095 BeginFrameArgs args =
2096 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2097 args.deadline += base::TimeDelta::FromHours(1);
2098 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2099 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2100 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2101 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2102 EXPECT_TRUE(client_->needs_begin_frames());
2103 client_->Reset();
2105 // Queue BeginFrames while we are still handling the previous BeginFrame.
2106 args.frame_time += base::TimeDelta::FromSeconds(1);
2107 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2108 args.frame_time += base::TimeDelta::FromSeconds(1);
2109 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2111 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2112 task_runner().RunPendingTasks(); // Run posted deadline.
2113 EXPECT_NO_ACTION(client_);
2114 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2115 EXPECT_TRUE(client_->needs_begin_frames());
2116 client_->Reset();
2118 // NotifyReadyToCommit should trigger the commit.
2119 scheduler_->NotifyBeginMainFrameStarted();
2120 scheduler_->NotifyReadyToCommit();
2121 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2122 EXPECT_TRUE(client_->needs_begin_frames());
2123 client_->Reset();
2125 // NotifyReadyToActivate should trigger the activation.
2126 scheduler_->NotifyReadyToActivate();
2127 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2128 EXPECT_TRUE(client_->needs_begin_frames());
2129 client_->Reset();
2131 // BeginImplFrame should prepare the draw.
2132 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2133 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2134 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2135 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2136 EXPECT_TRUE(client_->needs_begin_frames());
2137 client_->Reset();
2139 // BeginImplFrame deadline should draw.
2140 task_runner().RunPendingTasks(); // Run posted deadline.
2141 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2142 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2143 EXPECT_TRUE(client_->needs_begin_frames());
2144 client_->Reset();
2146 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2147 // to avoid excessive toggles.
2148 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2149 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
2150 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2151 client_->Reset();
2153 task_runner().RunPendingTasks(); // Run posted deadline.
2154 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
2155 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2156 client_->Reset();
2159 TEST_F(SchedulerTest, BeginRetroFrame_SwapThrottled) {
2160 scheduler_settings_.use_external_begin_frame_source = true;
2161 SetUpScheduler(true);
2163 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
2165 // To test swap ack throttling, this test disables automatic swap acks.
2166 scheduler_->SetMaxSwapsPending(1);
2167 client_->SetAutomaticSwapAck(false);
2169 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2170 client_->Reset();
2171 scheduler_->SetNeedsBeginMainFrame();
2172 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2173 client_->Reset();
2175 EXPECT_SCOPED(AdvanceFrame());
2176 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2177 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2178 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2179 EXPECT_TRUE(client_->needs_begin_frames());
2180 client_->Reset();
2182 // Queue BeginFrame while we are still handling the previous BeginFrame.
2183 SendNextBeginFrame();
2184 EXPECT_NO_ACTION(client_);
2185 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2186 EXPECT_TRUE(client_->needs_begin_frames());
2187 client_->Reset();
2189 // NotifyReadyToCommit should trigger the pending commit.
2190 scheduler_->NotifyBeginMainFrameStarted();
2191 scheduler_->NotifyReadyToCommit();
2192 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2193 EXPECT_TRUE(client_->needs_begin_frames());
2194 client_->Reset();
2196 // NotifyReadyToActivate should trigger the activation and draw.
2197 scheduler_->NotifyReadyToActivate();
2198 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2199 EXPECT_TRUE(client_->needs_begin_frames());
2200 client_->Reset();
2202 // Swapping will put us into a swap throttled state.
2203 // Run posted deadline.
2204 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2205 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2206 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2207 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2208 EXPECT_TRUE(client_->needs_begin_frames());
2209 client_->Reset();
2211 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
2212 // but not a BeginMainFrame or draw.
2213 scheduler_->SetNeedsBeginMainFrame();
2214 scheduler_->SetNeedsRedraw();
2215 // Run posted BeginRetroFrame.
2216 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
2217 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2218 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2219 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2220 EXPECT_TRUE(client_->needs_begin_frames());
2221 client_->Reset();
2223 // Let time pass sufficiently beyond the regular deadline but not beyond the
2224 // late deadline.
2225 now_src()->Advance(BeginFrameArgs::DefaultInterval() -
2226 base::TimeDelta::FromMicroseconds(1));
2227 task_runner().RunUntilTime(now_src()->NowTicks());
2228 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2230 // Take us out of a swap throttled state.
2231 scheduler_->DidSwapBuffersComplete();
2232 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
2233 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2234 EXPECT_TRUE(client_->needs_begin_frames());
2235 client_->Reset();
2237 // Verify that the deadline was rescheduled.
2238 task_runner().RunUntilTime(now_src()->NowTicks());
2239 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
2240 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2241 EXPECT_TRUE(client_->needs_begin_frames());
2242 client_->Reset();
2245 TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooEarly) {
2246 scheduler_settings_.use_external_begin_frame_source = true;
2247 SetUpScheduler(true);
2249 scheduler_->SetNeedsBeginMainFrame();
2250 EXPECT_TRUE(client_->needs_begin_frames());
2251 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2253 client_->Reset();
2254 EXPECT_SCOPED(AdvanceFrame());
2255 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2256 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2257 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2259 client_->Reset();
2260 scheduler_->NotifyBeginMainFrameStarted();
2262 client_->Reset();
2263 BeginFrameArgs retro_frame_args = SendNextBeginFrame();
2264 // This BeginFrame is queued up as a retro frame.
2265 EXPECT_NO_ACTION(client_);
2266 // The previous deadline is still pending.
2267 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2269 client_->Reset();
2270 // This main frame activating should schedule the (previous) deadline to
2271 // trigger immediately.
2272 scheduler_->NotifyReadyToCommit();
2273 scheduler_->NotifyReadyToActivate();
2274 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2);
2275 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2);
2277 client_->Reset();
2278 // The deadline task should trigger causing a draw.
2279 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2280 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2281 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2282 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2284 // Keep animating.
2285 client_->Reset();
2286 scheduler_->SetNeedsAnimate();
2287 scheduler_->SetNeedsRedraw();
2288 EXPECT_NO_ACTION(client_);
2290 // Let's advance to the retro frame's deadline.
2291 now_src()->Advance(retro_frame_args.deadline - now_src()->NowTicks());
2293 // The retro frame hasn't expired yet.
2294 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
2295 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2296 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2297 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2299 // This is an immediate deadline case.
2300 client_->Reset();
2301 task_runner().RunPendingTasks();
2302 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2303 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
2306 TEST_F(SchedulerTest, RetroFrameExpiresOnTime) {
2307 scheduler_settings_.use_external_begin_frame_source = true;
2308 SetUpScheduler(true);
2310 scheduler_->SetNeedsBeginMainFrame();
2311 EXPECT_TRUE(client_->needs_begin_frames());
2312 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2314 client_->Reset();
2315 EXPECT_SCOPED(AdvanceFrame());
2316 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2317 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2318 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2320 client_->Reset();
2321 scheduler_->NotifyBeginMainFrameStarted();
2323 client_->Reset();
2324 BeginFrameArgs retro_frame_args = SendNextBeginFrame();
2325 // This BeginFrame is queued up as a retro frame.
2326 EXPECT_NO_ACTION(client_);
2327 // The previous deadline is still pending.
2328 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2330 client_->Reset();
2331 // This main frame activating should schedule the (previous) deadline to
2332 // trigger immediately.
2333 scheduler_->NotifyReadyToCommit();
2334 scheduler_->NotifyReadyToActivate();
2335 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2);
2336 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2);
2338 client_->Reset();
2339 // The deadline task should trigger causing a draw.
2340 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2341 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2342 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2343 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2345 // Keep animating.
2346 client_->Reset();
2347 scheduler_->SetNeedsAnimate();
2348 scheduler_->SetNeedsRedraw();
2349 EXPECT_NO_ACTION(client_);
2351 // Let's advance sufficiently past the retro frame's deadline.
2352 now_src()->Advance(retro_frame_args.deadline - now_src()->NowTicks() +
2353 base::TimeDelta::FromMicroseconds(1));
2355 // The retro frame should've expired.
2356 EXPECT_NO_ACTION(client_);
2359 TEST_F(SchedulerTest, MissedFrameDoesNotExpireTooEarly) {
2360 scheduler_settings_.use_external_begin_frame_source = true;
2361 SetUpScheduler(true);
2363 scheduler_->SetNeedsBeginMainFrame();
2364 EXPECT_TRUE(client_->needs_begin_frames());
2365 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2367 BeginFrameArgs missed_frame_args =
2368 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2369 missed_frame_args.type = BeginFrameArgs::MISSED;
2371 // Advance to the deadline.
2372 now_src()->Advance(missed_frame_args.deadline - now_src()->NowTicks());
2374 // Missed frame is handled because it's on time.
2375 client_->Reset();
2376 fake_external_begin_frame_source_->TestOnBeginFrame(missed_frame_args);
2377 EXPECT_TRUE(
2378 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false)));
2379 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2380 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2381 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2384 TEST_F(SchedulerTest, MissedFrameExpiresOnTime) {
2385 scheduler_settings_.use_external_begin_frame_source = true;
2386 SetUpScheduler(true);
2388 scheduler_->SetNeedsBeginMainFrame();
2389 EXPECT_TRUE(client_->needs_begin_frames());
2390 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2392 BeginFrameArgs missed_frame_args =
2393 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2394 missed_frame_args.type = BeginFrameArgs::MISSED;
2396 // Advance sufficiently past the deadline.
2397 now_src()->Advance(missed_frame_args.deadline - now_src()->NowTicks() +
2398 base::TimeDelta::FromMicroseconds(1));
2400 // Missed frame is dropped because it's too late.
2401 client_->Reset();
2402 fake_external_begin_frame_source_->TestOnBeginFrame(missed_frame_args);
2403 EXPECT_FALSE(
2404 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false)));
2405 EXPECT_NO_ACTION(client_);
2406 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2409 void SchedulerTest::BeginFramesNotFromClient(
2410 bool use_external_begin_frame_source,
2411 bool throttle_frame_production) {
2412 scheduler_settings_.use_external_begin_frame_source =
2413 use_external_begin_frame_source;
2414 scheduler_settings_.throttle_frame_production = throttle_frame_production;
2415 SetUpScheduler(true);
2417 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame
2418 // without calling SetNeedsBeginFrame.
2419 scheduler_->SetNeedsBeginMainFrame();
2420 EXPECT_NO_ACTION(client_);
2421 client_->Reset();
2423 // When the client-driven BeginFrame are disabled, the scheduler posts it's
2424 // own BeginFrame tasks.
2425 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2426 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2427 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2428 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2429 client_->Reset();
2431 // If we don't swap on the deadline, we wait for the next BeginFrame.
2432 task_runner().RunPendingTasks(); // Run posted deadline.
2433 EXPECT_NO_ACTION(client_);
2434 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2435 client_->Reset();
2437 // NotifyReadyToCommit should trigger the commit.
2438 scheduler_->NotifyBeginMainFrameStarted();
2439 scheduler_->NotifyReadyToCommit();
2440 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2441 client_->Reset();
2443 // NotifyReadyToActivate should trigger the activation.
2444 scheduler_->NotifyReadyToActivate();
2445 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2446 client_->Reset();
2448 // BeginImplFrame should prepare the draw.
2449 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2450 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2451 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2452 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2453 client_->Reset();
2455 // BeginImplFrame deadline should draw.
2456 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2457 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2458 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2459 client_->Reset();
2461 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2462 // to avoid excessive toggles.
2463 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2464 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
2465 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2466 client_->Reset();
2468 // Make sure SetNeedsBeginFrame isn't called on the client
2469 // when the BeginFrame is no longer needed.
2470 task_runner().RunPendingTasks(); // Run posted deadline.
2471 EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_);
2472 client_->Reset();
2475 TEST_F(SchedulerTest, SyntheticBeginFrames) {
2476 bool use_external_begin_frame_source = false;
2477 bool throttle_frame_production = true;
2478 BeginFramesNotFromClient(use_external_begin_frame_source,
2479 throttle_frame_production);
2482 TEST_F(SchedulerTest, VSyncThrottlingDisabled) {
2483 bool use_external_begin_frame_source = true;
2484 bool throttle_frame_production = false;
2485 BeginFramesNotFromClient(use_external_begin_frame_source,
2486 throttle_frame_production);
2489 TEST_F(SchedulerTest, SyntheticBeginFrames_And_VSyncThrottlingDisabled) {
2490 bool use_external_begin_frame_source = false;
2491 bool throttle_frame_production = false;
2492 BeginFramesNotFromClient(use_external_begin_frame_source,
2493 throttle_frame_production);
2496 void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
2497 bool use_external_begin_frame_source,
2498 bool throttle_frame_production) {
2499 scheduler_settings_.use_external_begin_frame_source =
2500 use_external_begin_frame_source;
2501 scheduler_settings_.throttle_frame_production = throttle_frame_production;
2502 SetUpScheduler(true);
2504 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
2506 // To test swap ack throttling, this test disables automatic swap acks.
2507 scheduler_->SetMaxSwapsPending(1);
2508 client_->SetAutomaticSwapAck(false);
2510 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2511 client_->Reset();
2512 scheduler_->SetNeedsBeginMainFrame();
2513 EXPECT_NO_ACTION(client_);
2514 client_->Reset();
2516 // Trigger the first BeginImplFrame and BeginMainFrame
2517 EXPECT_SCOPED(AdvanceFrame());
2518 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2519 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2520 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2521 client_->Reset();
2523 // NotifyReadyToCommit should trigger the pending commit.
2524 scheduler_->NotifyBeginMainFrameStarted();
2525 scheduler_->NotifyReadyToCommit();
2526 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2527 client_->Reset();
2529 // NotifyReadyToActivate should trigger the activation and draw.
2530 scheduler_->NotifyReadyToActivate();
2531 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2532 client_->Reset();
2534 // Swapping will put us into a swap throttled state.
2535 // Run posted deadline.
2536 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2537 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2538 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2539 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2540 client_->Reset();
2542 // While swap throttled, BeginFrames should trigger BeginImplFrames,
2543 // but not a BeginMainFrame or draw.
2544 scheduler_->SetNeedsBeginMainFrame();
2545 scheduler_->SetNeedsRedraw();
2546 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
2547 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2548 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2549 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2550 client_->Reset();
2552 // Let time pass sufficiently beyond the regular deadline but not beyond the
2553 // late deadline.
2554 now_src()->Advance(BeginFrameArgs::DefaultInterval() -
2555 base::TimeDelta::FromMicroseconds(1));
2556 task_runner().RunUntilTime(now_src()->NowTicks());
2557 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2559 // Take us out of a swap throttled state.
2560 scheduler_->DidSwapBuffersComplete();
2561 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
2562 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2563 client_->Reset();
2565 // Verify that the deadline was rescheduled.
2566 // We can't use RunUntilTime(now) here because the next frame is also
2567 // scheduled if throttle_frame_production = false.
2568 base::TimeTicks before_deadline = now_src()->NowTicks();
2569 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2570 base::TimeTicks after_deadline = now_src()->NowTicks();
2571 EXPECT_EQ(after_deadline, before_deadline);
2572 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2573 client_->Reset();
2576 TEST_F(SchedulerTest, SyntheticBeginFrames_SwapThrottled) {
2577 bool use_external_begin_frame_source = false;
2578 bool throttle_frame_production = true;
2579 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
2580 throttle_frame_production);
2583 TEST_F(SchedulerTest, VSyncThrottlingDisabled_SwapThrottled) {
2584 bool use_external_begin_frame_source = true;
2585 bool throttle_frame_production = false;
2586 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
2587 throttle_frame_production);
2590 TEST_F(SchedulerTest,
2591 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled) {
2592 bool use_external_begin_frame_source = false;
2593 bool throttle_frame_production = false;
2594 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
2595 throttle_frame_production);
2598 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized) {
2599 scheduler_settings_.use_external_begin_frame_source = true;
2600 SetUpScheduler(false);
2602 scheduler_->SetCanStart();
2603 scheduler_->SetVisible(true);
2604 scheduler_->SetCanDraw(true);
2606 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
2607 client_->Reset();
2608 scheduler_->DidCreateAndInitializeOutputSurface();
2609 EXPECT_NO_ACTION(client_);
2611 scheduler_->DidLoseOutputSurface();
2612 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
2615 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) {
2616 scheduler_settings_.use_external_begin_frame_source = true;
2617 SetUpScheduler(true);
2619 // SetNeedsBeginMainFrame should begin the frame.
2620 scheduler_->SetNeedsBeginMainFrame();
2621 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2623 client_->Reset();
2624 EXPECT_SCOPED(AdvanceFrame());
2625 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2626 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2627 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2629 client_->Reset();
2630 scheduler_->DidLoseOutputSurface();
2631 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2632 EXPECT_NO_ACTION(client_);
2634 client_->Reset();
2635 scheduler_->NotifyBeginMainFrameStarted();
2636 scheduler_->NotifyReadyToCommit();
2637 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2);
2638 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2);
2640 client_->Reset();
2641 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2642 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2643 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2644 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2647 TEST_F(SchedulerTest,
2648 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) {
2649 scheduler_settings_.use_external_begin_frame_source = true;
2650 SetUpScheduler(true);
2652 // SetNeedsBeginMainFrame should begin the frame.
2653 scheduler_->SetNeedsBeginMainFrame();
2654 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2656 client_->Reset();
2657 EXPECT_SCOPED(AdvanceFrame());
2658 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2659 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2660 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2662 client_->Reset();
2663 scheduler_->DidLoseOutputSurface();
2664 // Do nothing when impl frame is in deadine pending state.
2665 EXPECT_NO_ACTION(client_);
2667 client_->Reset();
2668 // Run posted deadline.
2669 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2670 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2671 // OnBeginImplFrameDeadline didn't schedule output surface creation because
2672 // main frame is not yet completed.
2673 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
2674 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2675 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2677 // BeginImplFrame is not started.
2678 client_->Reset();
2679 task_runner().RunUntilTime(now_src()->NowTicks() +
2680 base::TimeDelta::FromMilliseconds(10));
2681 EXPECT_NO_ACTION(client_);
2682 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2684 client_->Reset();
2685 scheduler_->NotifyBeginMainFrameStarted();
2686 scheduler_->NotifyReadyToCommit();
2687 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 3);
2688 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 3);
2689 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 2, 3);
2692 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) {
2693 scheduler_settings_.use_external_begin_frame_source = true;
2694 SetUpScheduler(true);
2696 // SetNeedsBeginMainFrame should begin the frame.
2697 scheduler_->SetNeedsBeginMainFrame();
2698 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2700 client_->Reset();
2701 EXPECT_SCOPED(AdvanceFrame());
2702 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2703 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2704 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2706 client_->Reset();
2707 scheduler_->NotifyBeginMainFrameStarted();
2708 scheduler_->NotifyReadyToCommit();
2709 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2711 client_->Reset();
2712 scheduler_->DidLoseOutputSurface();
2713 // Sync tree should be forced to activate.
2714 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2716 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2717 client_->Reset();
2718 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2719 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2720 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2721 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2724 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles) {
2725 scheduler_settings_.use_external_begin_frame_source = true;
2726 SetUpScheduler(true);
2728 scheduler_->SetNeedsPrepareTiles();
2729 scheduler_->SetNeedsRedraw();
2730 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2732 client_->Reset();
2733 EXPECT_SCOPED(AdvanceFrame());
2734 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2735 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2736 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2738 client_->Reset();
2739 scheduler_->DidLoseOutputSurface();
2740 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2741 EXPECT_NO_ACTION(client_);
2743 client_->Reset();
2744 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2745 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 0, 4);
2746 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 4);
2747 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 2, 4);
2748 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 3, 4);
2751 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) {
2752 scheduler_settings_.use_external_begin_frame_source = true;
2753 SetUpScheduler(true);
2755 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2756 scheduler_->SetNeedsBeginMainFrame();
2757 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2759 // Create a BeginFrame with a long deadline to avoid race conditions.
2760 // This is the first BeginFrame, which will be handled immediately.
2761 client_->Reset();
2762 BeginFrameArgs args =
2763 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2764 args.deadline += base::TimeDelta::FromHours(1);
2765 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2766 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2767 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2768 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2769 EXPECT_TRUE(client_->needs_begin_frames());
2771 // Queue BeginFrames while we are still handling the previous BeginFrame.
2772 args.frame_time += base::TimeDelta::FromSeconds(1);
2773 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2774 args.frame_time += base::TimeDelta::FromSeconds(1);
2775 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2777 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2778 client_->Reset();
2779 task_runner().RunPendingTasks(); // Run posted deadline.
2780 EXPECT_NO_ACTION(client_);
2781 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2782 EXPECT_TRUE(client_->needs_begin_frames());
2784 // NotifyReadyToCommit should trigger the commit.
2785 client_->Reset();
2786 scheduler_->NotifyBeginMainFrameStarted();
2787 scheduler_->NotifyReadyToCommit();
2788 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2789 EXPECT_TRUE(client_->needs_begin_frames());
2791 // NotifyReadyToActivate should trigger the activation.
2792 client_->Reset();
2793 scheduler_->NotifyReadyToActivate();
2794 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2795 EXPECT_TRUE(client_->needs_begin_frames());
2797 client_->Reset();
2798 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty());
2799 scheduler_->DidLoseOutputSurface();
2800 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2801 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2802 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2803 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty());
2805 // Posted BeginRetroFrame is aborted.
2806 client_->Reset();
2807 task_runner().RunPendingTasks();
2808 EXPECT_NO_ACTION(client_);
2811 TEST_F(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) {
2812 scheduler_settings_.use_external_begin_frame_source = true;
2813 SetUpScheduler(true);
2815 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2816 scheduler_->SetNeedsBeginMainFrame();
2817 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2819 // Create a BeginFrame with a long deadline to avoid race conditions.
2820 // This is the first BeginFrame, which will be handled immediately.
2821 client_->Reset();
2822 BeginFrameArgs args =
2823 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2824 args.deadline += base::TimeDelta::FromHours(1);
2825 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2826 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2827 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2828 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2829 EXPECT_TRUE(client_->needs_begin_frames());
2831 // Queue BeginFrames while we are still handling the previous BeginFrame.
2832 args.frame_time += base::TimeDelta::FromSeconds(1);
2833 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2834 args.frame_time += base::TimeDelta::FromSeconds(1);
2835 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2837 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2838 client_->Reset();
2839 task_runner().RunPendingTasks(); // Run posted deadline.
2840 EXPECT_NO_ACTION(client_);
2841 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2842 EXPECT_TRUE(client_->needs_begin_frames());
2844 // NotifyReadyToCommit should trigger the commit.
2845 client_->Reset();
2846 scheduler_->NotifyBeginMainFrameStarted();
2847 scheduler_->NotifyReadyToCommit();
2848 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2849 EXPECT_TRUE(client_->needs_begin_frames());
2851 // NotifyReadyToActivate should trigger the activation.
2852 client_->Reset();
2853 scheduler_->NotifyReadyToActivate();
2854 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2855 EXPECT_TRUE(client_->needs_begin_frames());
2857 // BeginImplFrame should prepare the draw.
2858 client_->Reset();
2859 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2860 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2861 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2862 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2863 EXPECT_TRUE(client_->needs_begin_frames());
2865 client_->Reset();
2866 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty());
2867 scheduler_->DidLoseOutputSurface();
2868 EXPECT_NO_ACTION(client_);
2869 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty());
2871 // BeginImplFrame deadline should abort drawing.
2872 client_->Reset();
2873 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2874 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2875 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2876 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2877 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2878 EXPECT_FALSE(client_->needs_begin_frames());
2880 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
2881 client_->Reset();
2882 task_runner().RunPendingTasks();
2883 EXPECT_NO_ACTION(client_);
2886 TEST_F(SchedulerTest, DidLoseOutputSurfaceWithSyntheticBeginFrameSource) {
2887 SetUpScheduler(true);
2889 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2890 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2891 scheduler_->SetNeedsBeginMainFrame();
2892 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2894 client_->Reset();
2895 AdvanceFrame();
2896 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2897 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2898 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2899 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2901 // NotifyReadyToCommit should trigger the commit.
2902 client_->Reset();
2903 scheduler_->NotifyBeginMainFrameStarted();
2904 scheduler_->NotifyReadyToCommit();
2905 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2906 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2908 // NotifyReadyToActivate should trigger the activation.
2909 client_->Reset();
2910 scheduler_->NotifyReadyToActivate();
2911 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2912 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2914 client_->Reset();
2915 scheduler_->DidLoseOutputSurface();
2916 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2917 EXPECT_NO_ACTION(client_);
2918 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2920 client_->Reset();
2921 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2922 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 2);
2923 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2924 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2927 TEST_F(SchedulerTest, DidLoseOutputSurfaceWhenIdle) {
2928 scheduler_settings_.use_external_begin_frame_source = true;
2929 SetUpScheduler(true);
2931 // SetNeedsBeginMainFrame should begin the frame.
2932 scheduler_->SetNeedsBeginMainFrame();
2933 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2935 client_->Reset();
2936 EXPECT_SCOPED(AdvanceFrame());
2937 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2938 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2939 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2941 client_->Reset();
2942 scheduler_->NotifyBeginMainFrameStarted();
2943 scheduler_->NotifyReadyToCommit();
2944 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2946 client_->Reset();
2947 scheduler_->NotifyReadyToActivate();
2948 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2950 client_->Reset();
2951 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2952 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2953 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2955 // Idle time between BeginFrames.
2956 client_->Reset();
2957 scheduler_->DidLoseOutputSurface();
2958 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2959 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2960 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2963 TEST_F(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) {
2964 scheduler_settings_.use_external_begin_frame_source = true;
2965 SetUpScheduler(true);
2967 // SetNeedsBeginMainFrame should begin the frame.
2968 scheduler_->SetNeedsBeginMainFrame();
2969 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2971 client_->Reset();
2972 EXPECT_SCOPED(AdvanceFrame());
2973 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2974 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2975 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2977 client_->Reset();
2978 scheduler_->NotifyBeginMainFrameStarted();
2979 scheduler_->NotifyReadyToCommit();
2980 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2981 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2983 client_->Reset();
2984 scheduler_->SetVisible(false);
2985 task_runner().RunPendingTasks(); // Run posted deadline.
2987 // Sync tree should be forced to activate.
2988 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 3);
2989 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2990 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2993 // Tests to ensure frame sources can be successfully changed while drawing.
2994 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottled) {
2995 scheduler_settings_.use_external_begin_frame_source = true;
2996 SetUpScheduler(true);
2998 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2999 scheduler_->SetNeedsRedraw();
3000 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3001 client_->Reset();
3003 EXPECT_SCOPED(AdvanceFrame());
3004 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3005 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
3006 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3007 EXPECT_TRUE(client_->needs_begin_frames());
3008 client_->Reset();
3009 task_runner().RunPendingTasks(); // Run posted deadline.
3010 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
3011 scheduler_->SetNeedsRedraw();
3013 // Switch to an unthrottled frame source.
3014 scheduler_->SetThrottleFrameProduction(false);
3015 client_->Reset();
3017 // Unthrottled frame source will immediately begin a new frame.
3018 task_runner().RunPendingTasks(); // Run posted BeginFrame.
3019 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3020 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
3021 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3022 client_->Reset();
3024 // If we don't swap on the deadline, we wait for the next BeginFrame.
3025 task_runner().RunPendingTasks(); // Run posted deadline.
3026 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
3027 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3028 client_->Reset();
3031 // Tests to ensure frame sources can be successfully changed while a frame
3032 // deadline is pending.
3033 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottledBeforeDeadline) {
3034 scheduler_settings_.use_external_begin_frame_source = true;
3035 SetUpScheduler(true);
3037 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
3038 scheduler_->SetNeedsRedraw();
3039 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3040 client_->Reset();
3042 EXPECT_SCOPED(AdvanceFrame());
3043 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3044 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
3046 // Switch to an unthrottled frame source before the frame deadline is hit.
3047 scheduler_->SetThrottleFrameProduction(false);
3048 client_->Reset();
3050 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3051 EXPECT_TRUE(client_->needs_begin_frames());
3052 client_->Reset();
3054 task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame.
3055 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
3056 // Unthrottled frame source will immediately begin a new frame.
3057 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 2);
3058 scheduler_->SetNeedsRedraw();
3059 client_->Reset();
3061 task_runner().RunPendingTasks(); // Run posted deadline.
3062 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
3063 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
3064 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3065 client_->Reset();
3068 // Tests to ensure that the active frame source can successfully be changed from
3069 // unthrottled to throttled.
3070 TEST_F(SchedulerTest, SwitchFrameSourceToThrottled) {
3071 scheduler_settings_.throttle_frame_production = false;
3072 scheduler_settings_.use_external_begin_frame_source = true;
3073 SetUpScheduler(true);
3075 scheduler_->SetNeedsRedraw();
3076 EXPECT_NO_ACTION(client_);
3077 client_->Reset();
3079 task_runner().RunPendingTasks(); // Run posted BeginFrame.
3080 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3081 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
3082 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3083 client_->Reset();
3085 task_runner().RunPendingTasks(); // Run posted deadline.
3086 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
3087 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3088 client_->Reset();
3090 // Switch to a throttled frame source.
3091 scheduler_->SetThrottleFrameProduction(true);
3092 client_->Reset();
3094 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
3095 scheduler_->SetNeedsRedraw();
3096 task_runner().RunPendingTasks();
3097 EXPECT_NO_ACTION(client_);
3098 client_->Reset();
3100 EXPECT_SCOPED(AdvanceFrame());
3101 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3102 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
3103 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3104 EXPECT_TRUE(client_->needs_begin_frames());
3105 client_->Reset();
3106 task_runner().RunPendingTasks(); // Run posted deadline.
3107 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
3110 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
3111 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon) {
3112 scheduler_settings_.use_external_begin_frame_source = true;
3113 SetUpScheduler(true);
3115 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
3116 scheduler_->SetNeedsBeginMainFrame();
3117 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3118 client_->Reset();
3120 // Trigger a frame draw.
3121 EXPECT_SCOPED(AdvanceFrame());
3122 scheduler_->NotifyBeginMainFrameStarted();
3123 scheduler_->NotifyReadyToCommit();
3124 scheduler_->NotifyReadyToActivate();
3125 task_runner().RunPendingTasks();
3126 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6);
3127 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 6);
3128 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 6);
3129 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 3, 6);
3130 EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 6);
3131 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 5, 6);
3132 client_->Reset();
3134 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
3135 // and send a SendBeginMainFrameNotExpectedSoon.
3136 EXPECT_SCOPED(AdvanceFrame());
3137 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
3138 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3139 client_->Reset();
3141 task_runner().RunPendingTasks(); // Run posted deadline.
3142 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
3143 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
3144 client_->Reset();
3147 TEST_F(SchedulerTest, SynchronousCompositorAnimation) {
3148 scheduler_settings_.using_synchronous_renderer_compositor = true;
3149 scheduler_settings_.use_external_begin_frame_source = true;
3150 SetUpScheduler(true);
3152 scheduler_->SetNeedsAnimate();
3153 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3154 client_->Reset();
3156 // Next vsync.
3157 AdvanceFrame();
3158 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3159 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3160 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3161 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3162 client_->Reset();
3164 // Continue with animation.
3165 scheduler_->SetNeedsAnimate();
3166 EXPECT_NO_ACTION(client_);
3168 // Android onDraw.
3169 scheduler_->SetNeedsRedraw();
3170 scheduler_->OnDrawForOutputSurface();
3171 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
3172 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3173 client_->Reset();
3175 // Next vsync.
3176 AdvanceFrame();
3177 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3178 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3179 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3180 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3181 client_->Reset();
3183 // Android onDraw.
3184 scheduler_->SetNeedsRedraw();
3185 scheduler_->OnDrawForOutputSurface();
3186 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
3187 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3188 client_->Reset();
3190 // Idle on next vsync.
3191 AdvanceFrame();
3192 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3193 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
3194 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
3195 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3196 client_->Reset();
3199 TEST_F(SchedulerTest, SynchronousCompositorOnDrawDuringIdle) {
3200 scheduler_settings_.using_synchronous_renderer_compositor = true;
3201 scheduler_settings_.use_external_begin_frame_source = true;
3202 SetUpScheduler(true);
3204 scheduler_->SetNeedsRedraw();
3205 scheduler_->OnDrawForOutputSurface();
3206 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3);
3207 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3208 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3);
3209 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3210 client_->Reset();
3212 // Idle on next vsync.
3213 AdvanceFrame();
3214 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3215 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
3216 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
3217 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3218 client_->Reset();
3221 TEST_F(SchedulerTest, SynchronousCompositorCommit) {
3222 scheduler_settings_.using_synchronous_renderer_compositor = true;
3223 scheduler_settings_.use_external_begin_frame_source = true;
3224 SetUpScheduler(true);
3226 scheduler_->SetNeedsBeginMainFrame();
3227 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3228 client_->Reset();
3230 // Next vsync.
3231 AdvanceFrame();
3232 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3233 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
3234 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3235 client_->Reset();
3237 scheduler_->NotifyBeginMainFrameStarted();
3238 EXPECT_NO_ACTION(client_);
3240 // Next vsync.
3241 AdvanceFrame();
3242 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
3243 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3244 client_->Reset();
3246 scheduler_->NotifyReadyToCommit();
3247 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
3248 client_->Reset();
3250 scheduler_->NotifyReadyToActivate();
3251 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
3252 client_->Reset();
3254 // Next vsync.
3255 AdvanceFrame();
3256 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3257 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3258 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3259 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3260 client_->Reset();
3262 // Android onDraw.
3263 scheduler_->SetNeedsRedraw();
3264 scheduler_->OnDrawForOutputSurface();
3265 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
3266 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3267 client_->Reset();
3269 // Idle on next vsync.
3270 AdvanceFrame();
3271 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3272 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
3273 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
3274 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3275 client_->Reset();
3278 TEST_F(SchedulerTest, SynchronousCompositorDoubleCommitWithoutDraw) {
3279 scheduler_settings_.using_synchronous_renderer_compositor = true;
3280 scheduler_settings_.use_external_begin_frame_source = true;
3281 SetUpScheduler(true);
3283 scheduler_->SetNeedsBeginMainFrame();
3284 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3285 client_->Reset();
3287 // Next vsync.
3288 AdvanceFrame();
3289 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3290 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
3291 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3292 client_->Reset();
3294 scheduler_->NotifyBeginMainFrameStarted();
3295 EXPECT_NO_ACTION(client_);
3297 scheduler_->NotifyReadyToCommit();
3298 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
3299 client_->Reset();
3301 scheduler_->NotifyReadyToActivate();
3302 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
3303 client_->Reset();
3305 // Ask for another commit.
3306 scheduler_->SetNeedsBeginMainFrame();
3308 AdvanceFrame();
3309 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4);
3310 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4);
3311 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4);
3312 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 3, 4);
3313 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3314 client_->Reset();
3316 scheduler_->NotifyBeginMainFrameStarted();
3317 EXPECT_NO_ACTION(client_);
3319 // Allow new commit even though previous commit hasn't been drawn.
3320 scheduler_->NotifyReadyToCommit();
3321 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
3322 client_->Reset();
3325 class SchedulerClientSetNeedsPrepareTilesOnDraw : public FakeSchedulerClient {
3326 public:
3327 SchedulerClientSetNeedsPrepareTilesOnDraw() : FakeSchedulerClient() {}
3329 protected:
3330 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
3331 scheduler_->SetNeedsPrepareTiles();
3332 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
3336 TEST_F(SchedulerTest, SynchronousCompositorPrepareTilesOnDraw) {
3337 scheduler_settings_.using_synchronous_renderer_compositor = true;
3338 scheduler_settings_.use_external_begin_frame_source = true;
3340 scoped_ptr<FakeSchedulerClient> client =
3341 make_scoped_ptr(new SchedulerClientSetNeedsPrepareTilesOnDraw);
3342 SetUpScheduler(client.Pass(), true);
3344 scheduler_->SetNeedsRedraw();
3345 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3346 client_->Reset();
3348 // Next vsync.
3349 EXPECT_SCOPED(AdvanceFrame());
3350 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3351 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3352 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3353 client_->Reset();
3355 // Android onDraw.
3356 scheduler_->SetNeedsRedraw();
3357 scheduler_->OnDrawForOutputSurface();
3358 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
3359 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 1, 2);
3360 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3361 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3362 client_->Reset();
3364 // Android onDraw.
3365 scheduler_->SetNeedsRedraw();
3366 scheduler_->OnDrawForOutputSurface();
3367 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
3368 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 1, 2);
3369 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3370 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3371 client_->Reset();
3373 // Next vsync.
3374 EXPECT_SCOPED(AdvanceFrame());
3375 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3376 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3377 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
3378 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
3379 EXPECT_FALSE(client_->needs_begin_frames());
3380 client_->Reset();
3383 TEST_F(SchedulerTest, SynchronousCompositorSendBeginMainFrameWhileIdle) {
3384 scheduler_settings_.using_synchronous_renderer_compositor = true;
3385 scheduler_settings_.use_external_begin_frame_source = true;
3387 SetUpScheduler(true);
3389 scheduler_->SetNeedsRedraw();
3390 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3391 client_->Reset();
3393 // Next vsync.
3394 EXPECT_SCOPED(AdvanceFrame());
3395 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3396 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3397 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3398 client_->Reset();
3400 // Android onDraw.
3401 scheduler_->SetNeedsRedraw();
3402 scheduler_->OnDrawForOutputSurface();
3403 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
3404 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3405 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3406 client_->Reset();
3408 // Simulate SetNeedsBeginMainFrame due to input event.
3409 scheduler_->SetNeedsBeginMainFrame();
3410 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
3411 client_->Reset();
3413 scheduler_->NotifyBeginMainFrameStarted();
3414 scheduler_->NotifyReadyToCommit();
3415 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
3416 client_->Reset();
3418 scheduler_->NotifyReadyToActivate();
3419 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
3420 client_->Reset();
3422 // Next vsync.
3423 EXPECT_SCOPED(AdvanceFrame());
3424 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3425 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3426 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3427 client_->Reset();
3429 // Android onDraw.
3430 scheduler_->SetNeedsRedraw();
3431 scheduler_->OnDrawForOutputSurface();
3432 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
3433 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3434 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3435 client_->Reset();
3437 // Simulate SetNeedsBeginMainFrame due to input event.
3438 scheduler_->SetNeedsBeginMainFrame();
3439 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
3440 client_->Reset();
3443 TEST_F(SchedulerTest, AuthoritativeVSyncInterval) {
3444 SetUpScheduler(true);
3445 base::TimeDelta initial_interval = scheduler_->BeginImplFrameInterval();
3446 base::TimeDelta authoritative_interval =
3447 base::TimeDelta::FromMilliseconds(33);
3449 scheduler_->SetNeedsBeginMainFrame();
3450 EXPECT_SCOPED(AdvanceFrame());
3452 EXPECT_EQ(initial_interval, scheduler_->BeginImplFrameInterval());
3454 scheduler_->NotifyBeginMainFrameStarted();
3455 scheduler_->NotifyReadyToCommit();
3456 scheduler_->NotifyReadyToActivate();
3457 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
3459 scheduler_->SetAuthoritativeVSyncInterval(authoritative_interval);
3461 EXPECT_SCOPED(AdvanceFrame());
3463 // At the next BeginFrame, authoritative interval is used instead of previous
3464 // interval.
3465 EXPECT_NE(initial_interval, scheduler_->BeginImplFrameInterval());
3466 EXPECT_EQ(authoritative_interval, scheduler_->BeginImplFrameInterval());
3469 TEST_F(SchedulerTest, ImplLatencyTakesPriority) {
3470 SetUpScheduler(true);
3471 scheduler_->SetImplLatencyTakesPriority(true);
3472 EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority());
3474 scheduler_->SetImplLatencyTakesPriority(false);
3475 EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority());
3478 TEST_F(SchedulerTest, BeginFrameArgs_OnCriticalPath) {
3479 scheduler_settings_.use_external_begin_frame_source = true;
3480 SetUpScheduler(true);
3482 scheduler_->SetImplLatencyTakesPriority(false);
3483 scheduler_->SetChildrenNeedBeginFrames(true);
3485 EXPECT_SCOPED(AdvanceFrame());
3486 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
3487 EXPECT_TRUE(client_->begin_frame_args_sent_to_children().on_critical_path);
3490 TEST_F(SchedulerTest, BeginFrameArgs_NotOnCriticalPath) {
3491 scheduler_settings_.use_external_begin_frame_source = true;
3492 SetUpScheduler(true);
3494 scheduler_->SetImplLatencyTakesPriority(true);
3495 scheduler_->SetChildrenNeedBeginFrames(true);
3497 EXPECT_SCOPED(AdvanceFrame());
3498 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
3499 EXPECT_FALSE(client_->begin_frame_args_sent_to_children().on_critical_path);
3502 } // namespace
3503 } // namespace cc