[Media,Android] Moved OnSuspend and OnResume out of #if defined(VIDEO_HOLE)
[chromium-blink-merge.git] / cc / scheduler / scheduler_unittest.cc
blob42a23d423e630893a9718b4704b54774010db24f
1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/scheduler/scheduler.h"
7 #include <string>
8 #include <vector>
10 #include "base/logging.h"
11 #include "base/memory/scoped_vector.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/numerics/safe_conversions.h"
14 #include "base/run_loop.h"
15 #include "base/time/time.h"
16 #include "base/trace_event/trace_event.h"
17 #include "cc/test/begin_frame_args_test.h"
18 #include "cc/test/ordered_simple_task_runner.h"
19 #include "cc/test/scheduler_test_common.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
24 do { \
25 EXPECT_EQ(expected_num_actions, client->num_actions_()); \
26 if (action_index >= 0) { \
27 ASSERT_LT(action_index, client->num_actions_()) << scheduler_.get(); \
28 EXPECT_STREQ(action, client->Action(action_index)); \
29 } \
30 for (int i = expected_num_actions; i < client->num_actions_(); ++i) \
31 ADD_FAILURE() << "Unexpected action: " << client->Action(i) \
32 << " with state:\n" << client->StateForAction(i); \
33 } while (false)
35 #define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0)
37 #define EXPECT_SINGLE_ACTION(action, client) \
38 EXPECT_ACTION(action, client, 0, 1)
40 #define EXPECT_SCOPED(statements) \
41 { \
42 SCOPED_TRACE(""); \
43 statements; \
46 namespace cc {
47 namespace {
49 class FakeSchedulerClient : public SchedulerClient {
50 public:
51 FakeSchedulerClient()
52 : automatic_swap_ack_(true),
53 scheduler_(nullptr) {
54 Reset();
57 void Reset() {
58 actions_.clear();
59 states_.clear();
60 draw_will_happen_ = true;
61 swap_will_happen_if_draw_happens_ = true;
62 num_draws_ = 0;
63 begin_frame_args_sent_to_children_ = BeginFrameArgs();
66 void set_scheduler(TestScheduler* scheduler) { scheduler_ = scheduler; }
68 bool needs_begin_frames() {
69 return scheduler_->frame_source().NeedsBeginFrames();
71 int num_draws() const { return num_draws_; }
72 int num_actions_() const { return static_cast<int>(actions_.size()); }
73 const char* Action(int i) const { return actions_[i]; }
74 std::string StateForAction(int i) const { return states_[i]->ToString(); }
75 base::TimeTicks posted_begin_impl_frame_deadline() const {
76 return posted_begin_impl_frame_deadline_;
79 int ActionIndex(const char* action) const {
80 for (size_t i = 0; i < actions_.size(); i++)
81 if (!strcmp(actions_[i], action))
82 return base::checked_cast<int>(i);
83 return -1;
86 bool HasAction(const char* action) const {
87 return ActionIndex(action) >= 0;
90 void SetDrawWillHappen(bool draw_will_happen) {
91 draw_will_happen_ = draw_will_happen;
93 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
94 swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
96 void SetAutomaticSwapAck(bool automatic_swap_ack) {
97 automatic_swap_ack_ = automatic_swap_ack;
99 // SchedulerClient implementation.
100 void WillBeginImplFrame(const BeginFrameArgs& args) override {
101 PushAction("WillBeginImplFrame");
103 void DidFinishImplFrame() override {}
105 void ScheduledActionSendBeginMainFrame() override {
106 PushAction("ScheduledActionSendBeginMainFrame");
108 void ScheduledActionAnimate() override {
109 PushAction("ScheduledActionAnimate");
111 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
112 PushAction("ScheduledActionDrawAndSwapIfPossible");
113 num_draws_++;
114 DrawResult result =
115 draw_will_happen_ ? DRAW_SUCCESS : DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
116 bool swap_will_happen =
117 draw_will_happen_ && swap_will_happen_if_draw_happens_;
118 if (swap_will_happen) {
119 scheduler_->DidSwapBuffers();
121 if (automatic_swap_ack_)
122 scheduler_->DidSwapBuffersComplete();
124 return result;
126 DrawResult ScheduledActionDrawAndSwapForced() override {
127 PushAction("ScheduledActionDrawAndSwapForced");
128 return DRAW_SUCCESS;
130 void ScheduledActionCommit() override {
131 PushAction("ScheduledActionCommit");
132 scheduler_->DidCommit();
134 void ScheduledActionActivateSyncTree() override {
135 PushAction("ScheduledActionActivateSyncTree");
137 void ScheduledActionBeginOutputSurfaceCreation() override {
138 PushAction("ScheduledActionBeginOutputSurfaceCreation");
140 void ScheduledActionPrepareTiles() override {
141 PushAction("ScheduledActionPrepareTiles");
142 scheduler_->WillPrepareTiles();
143 scheduler_->DidPrepareTiles();
145 void ScheduledActionInvalidateOutputSurface() override {
146 actions_.push_back("ScheduledActionInvalidateOutputSurface");
147 states_.push_back(scheduler_->AsValue());
150 void SendBeginFramesToChildren(const BeginFrameArgs& args) override {
151 begin_frame_args_sent_to_children_ = args;
154 void SendBeginMainFrameNotExpectedSoon() override {
155 PushAction("SendBeginMainFrameNotExpectedSoon");
158 base::Callback<bool(void)> ImplFrameDeadlinePending(bool state) {
159 return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback,
160 base::Unretained(this),
161 state);
164 bool begin_frame_is_sent_to_children() const {
165 return begin_frame_args_sent_to_children_.IsValid();
168 const BeginFrameArgs& begin_frame_args_sent_to_children() const {
169 return begin_frame_args_sent_to_children_;
172 void PushAction(const char* description) {
173 actions_.push_back(description);
174 states_.push_back(scheduler_->AsValue());
177 protected:
178 bool ImplFrameDeadlinePendingCallback(bool state) {
179 return scheduler_->BeginImplFrameDeadlinePending() == state;
182 bool draw_will_happen_;
183 bool swap_will_happen_if_draw_happens_;
184 bool automatic_swap_ack_;
185 int num_draws_;
186 BeginFrameArgs begin_frame_args_sent_to_children_;
187 base::TimeTicks posted_begin_impl_frame_deadline_;
188 std::vector<const char*> actions_;
189 std::vector<scoped_refptr<base::trace_event::ConvertableToTraceFormat>>
190 states_;
191 TestScheduler* scheduler_;
194 class FakeExternalBeginFrameSource : public BeginFrameSourceBase {
195 public:
196 explicit FakeExternalBeginFrameSource(FakeSchedulerClient* client)
197 : client_(client) {}
198 ~FakeExternalBeginFrameSource() override {}
200 void OnNeedsBeginFramesChange(bool needs_begin_frames) override {
201 if (needs_begin_frames) {
202 client_->PushAction("SetNeedsBeginFrames(true)");
203 } else {
204 client_->PushAction("SetNeedsBeginFrames(false)");
208 void TestOnBeginFrame(const BeginFrameArgs& args) {
209 return CallOnBeginFrame(args);
212 private:
213 FakeSchedulerClient* client_;
216 class SchedulerTest : public testing::Test {
217 public:
218 SchedulerTest()
219 : now_src_(new base::SimpleTestTickClock()),
220 task_runner_(new OrderedSimpleTaskRunner(now_src_.get(), true)),
221 fake_external_begin_frame_source_(nullptr) {
222 now_src_->Advance(base::TimeDelta::FromMicroseconds(10000));
223 // A bunch of tests require NowTicks()
224 // to be > BeginFrameArgs::DefaultInterval()
225 now_src_->Advance(base::TimeDelta::FromMilliseconds(100));
226 // Fail if we need to run 100 tasks in a row.
227 task_runner_->SetRunTaskLimit(100);
230 ~SchedulerTest() override {}
232 protected:
233 TestScheduler* CreateScheduler() {
234 if (scheduler_settings_.use_external_begin_frame_source) {
235 fake_external_begin_frame_source_.reset(
236 new FakeExternalBeginFrameSource(client_.get()));
239 scoped_ptr<FakeCompositorTimingHistory> fake_compositor_timing_history =
240 FakeCompositorTimingHistory::Create();
241 fake_compositor_timing_history_ = fake_compositor_timing_history.get();
243 scheduler_ = TestScheduler::Create(
244 now_src_.get(), client_.get(), scheduler_settings_, 0,
245 task_runner_.get(), fake_external_begin_frame_source_.get(),
246 fake_compositor_timing_history.Pass());
247 DCHECK(scheduler_);
248 client_->set_scheduler(scheduler_.get());
250 // Use large estimates by default to avoid latency recovery
251 // in most tests.
252 base::TimeDelta slow_duration = base::TimeDelta::FromSeconds(1);
253 fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration);
255 return scheduler_.get();
258 void CreateSchedulerAndInitSurface() {
259 CreateScheduler();
260 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit());
263 void SetUpScheduler(bool initSurface) {
264 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient), initSurface);
267 void SetUpScheduler(scoped_ptr<FakeSchedulerClient> client,
268 bool initSurface) {
269 client_ = client.Pass();
270 if (initSurface)
271 CreateSchedulerAndInitSurface();
272 else
273 CreateScheduler();
276 OrderedSimpleTaskRunner& task_runner() { return *task_runner_; }
277 base::SimpleTestTickClock* now_src() { return now_src_.get(); }
279 // As this function contains EXPECT macros, to allow debugging it should be
280 // called inside EXPECT_SCOPED like so;
281 // EXPECT_SCOPED(client.InitializeOutputSurfaceAndFirstCommit(scheduler));
282 void InitializeOutputSurfaceAndFirstCommit() {
283 TRACE_EVENT0("cc",
284 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit");
285 DCHECK(scheduler_);
287 // Check the client doesn't have any actions queued when calling this
288 // function.
289 EXPECT_NO_ACTION(client_);
290 EXPECT_FALSE(client_->needs_begin_frames());
292 // Start the initial output surface creation.
293 EXPECT_FALSE(scheduler_->CanStart());
294 scheduler_->SetCanStart();
295 scheduler_->SetVisible(true);
296 scheduler_->SetCanDraw(true);
297 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
299 client_->Reset();
301 // We don't see anything happening until the first impl frame.
302 scheduler_->DidCreateAndInitializeOutputSurface();
303 scheduler_->SetNeedsCommit();
304 EXPECT_TRUE(client_->needs_begin_frames());
305 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
306 client_->Reset();
309 SCOPED_TRACE("Do first frame to commit after initialize.");
310 AdvanceFrame();
312 scheduler_->NotifyBeginMainFrameStarted();
313 scheduler_->NotifyReadyToCommit();
314 scheduler_->NotifyReadyToActivate();
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_->SetNeedsCommit();
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 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
522 scheduler_->SetNeedsCommit();
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_->SetNeedsCommit();
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_->SetNeedsCommit();
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 // SetNeedsCommit should begin the frame.
645 scheduler_->SetNeedsCommit();
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 SetNeedsCommit again. Calling here means we need a second commit.
658 scheduler_->SetNeedsCommit();
659 EXPECT_EQ(client_->num_actions_(), 0);
660 client_->Reset();
662 // Finish the first commit.
663 scheduler_->NotifyBeginMainFrameStarted();
664 scheduler_->NotifyReadyToCommit();
665 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
666 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
667 client_->Reset();
669 // Activate it.
670 scheduler_->NotifyReadyToActivate();
671 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
672 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
673 client_->Reset();
675 task_runner().RunPendingTasks(); // Run posted deadline.
676 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
677 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
678 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
680 // Because we just swapped, the Scheduler should also request the next
681 // BeginImplFrame from the OutputSurface.
682 EXPECT_TRUE(client_->needs_begin_frames());
683 client_->Reset();
684 // Since another commit is needed, the next BeginImplFrame should initiate
685 // the second commit.
686 EXPECT_SCOPED(AdvanceFrame());
687 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
688 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
689 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
690 client_->Reset();
692 // Finishing the commit before the deadline should post a new deadline task
693 // to trigger the deadline early.
694 scheduler_->NotifyBeginMainFrameStarted();
695 scheduler_->NotifyReadyToCommit();
696 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
697 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
698 client_->Reset();
699 scheduler_->NotifyReadyToActivate();
700 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
701 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
702 client_->Reset();
703 task_runner().RunPendingTasks(); // Run posted deadline.
704 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
705 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
706 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
707 EXPECT_TRUE(client_->needs_begin_frames());
708 client_->Reset();
710 // On the next BeginImplFrame, verify we go back to a quiescent state and
711 // no longer request BeginImplFrames.
712 EXPECT_SCOPED(AdvanceFrame());
713 task_runner().RunPendingTasks(); // Run posted deadline.
714 EXPECT_FALSE(client_->needs_begin_frames());
715 client_->Reset();
718 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
719 public:
720 SchedulerClientThatsetNeedsDrawInsideDraw()
721 : FakeSchedulerClient(), request_redraws_(false) {}
723 void SetRequestRedrawsInsideDraw(bool enable) { request_redraws_ = enable; }
725 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
726 // Only SetNeedsRedraw the first time this is called
727 if (request_redraws_) {
728 scheduler_->SetNeedsRedraw();
730 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
733 DrawResult ScheduledActionDrawAndSwapForced() override {
734 NOTREACHED();
735 return DRAW_SUCCESS;
738 private:
739 bool request_redraws_;
742 // Tests for two different situations:
743 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
744 // a ScheduledActionDrawAndSwap
745 // 2. the scheduler drawing twice inside a single tick
746 TEST_F(SchedulerTest, RequestRedrawInsideDraw) {
747 SchedulerClientThatsetNeedsDrawInsideDraw* client =
748 new SchedulerClientThatsetNeedsDrawInsideDraw;
749 scheduler_settings_.use_external_begin_frame_source = true;
750 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
751 client->SetRequestRedrawsInsideDraw(true);
753 scheduler_->SetNeedsRedraw();
754 EXPECT_TRUE(scheduler_->RedrawPending());
755 EXPECT_TRUE(client->needs_begin_frames());
756 EXPECT_EQ(0, client->num_draws());
758 EXPECT_SCOPED(AdvanceFrame());
759 task_runner().RunPendingTasks(); // Run posted deadline.
760 EXPECT_EQ(1, client->num_draws());
761 EXPECT_TRUE(scheduler_->RedrawPending());
762 EXPECT_TRUE(client->needs_begin_frames());
764 client->SetRequestRedrawsInsideDraw(false);
766 EXPECT_SCOPED(AdvanceFrame());
767 task_runner().RunPendingTasks(); // Run posted deadline.
768 EXPECT_EQ(2, client_->num_draws());
769 EXPECT_FALSE(scheduler_->RedrawPending());
770 EXPECT_TRUE(client->needs_begin_frames());
772 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
773 // swap.
774 EXPECT_SCOPED(AdvanceFrame());
775 task_runner().RunPendingTasks(); // Run posted deadline.
776 EXPECT_EQ(2, client->num_draws());
777 EXPECT_FALSE(scheduler_->RedrawPending());
778 EXPECT_FALSE(client->needs_begin_frames());
781 // Test that requesting redraw inside a failed draw doesn't lose the request.
782 TEST_F(SchedulerTest, RequestRedrawInsideFailedDraw) {
783 SchedulerClientThatsetNeedsDrawInsideDraw* client =
784 new SchedulerClientThatsetNeedsDrawInsideDraw;
785 scheduler_settings_.use_external_begin_frame_source = true;
786 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
788 client->SetRequestRedrawsInsideDraw(true);
789 client->SetDrawWillHappen(false);
791 scheduler_->SetNeedsRedraw();
792 EXPECT_TRUE(scheduler_->RedrawPending());
793 EXPECT_TRUE(client->needs_begin_frames());
794 EXPECT_EQ(0, client->num_draws());
796 // Fail the draw.
797 EXPECT_SCOPED(AdvanceFrame());
798 task_runner().RunPendingTasks(); // Run posted deadline.
799 EXPECT_EQ(1, client->num_draws());
801 // We have a commit pending and the draw failed, and we didn't lose the redraw
802 // request.
803 EXPECT_TRUE(scheduler_->CommitPending());
804 EXPECT_TRUE(scheduler_->RedrawPending());
805 EXPECT_TRUE(client->needs_begin_frames());
807 client->SetRequestRedrawsInsideDraw(false);
809 // Fail the draw again.
810 EXPECT_SCOPED(AdvanceFrame());
811 task_runner().RunPendingTasks(); // Run posted deadline.
812 EXPECT_EQ(2, client->num_draws());
813 EXPECT_TRUE(scheduler_->CommitPending());
814 EXPECT_TRUE(scheduler_->RedrawPending());
815 EXPECT_TRUE(client->needs_begin_frames());
817 // Draw successfully.
818 client->SetDrawWillHappen(true);
819 EXPECT_SCOPED(AdvanceFrame());
820 task_runner().RunPendingTasks(); // Run posted deadline.
821 EXPECT_EQ(3, client->num_draws());
822 EXPECT_TRUE(scheduler_->CommitPending());
823 EXPECT_FALSE(scheduler_->RedrawPending());
824 EXPECT_TRUE(client->needs_begin_frames());
827 class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
828 public:
829 SchedulerClientThatSetNeedsCommitInsideDraw()
830 : set_needs_commit_on_next_draw_(false) {}
832 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
833 // Only SetNeedsCommit the first time this is called
834 if (set_needs_commit_on_next_draw_) {
835 scheduler_->SetNeedsCommit();
836 set_needs_commit_on_next_draw_ = false;
838 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
841 DrawResult ScheduledActionDrawAndSwapForced() override {
842 NOTREACHED();
843 return DRAW_SUCCESS;
846 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; }
848 private:
849 bool set_needs_commit_on_next_draw_;
852 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
853 // happen inside a ScheduledActionDrawAndSwap
854 TEST_F(SchedulerTest, RequestCommitInsideDraw) {
855 SchedulerClientThatSetNeedsCommitInsideDraw* client =
856 new SchedulerClientThatSetNeedsCommitInsideDraw;
858 scheduler_settings_.use_external_begin_frame_source = true;
859 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
861 EXPECT_FALSE(client->needs_begin_frames());
862 scheduler_->SetNeedsRedraw();
863 EXPECT_TRUE(scheduler_->RedrawPending());
864 EXPECT_EQ(0, client->num_draws());
865 EXPECT_TRUE(client->needs_begin_frames());
867 client->SetNeedsCommitOnNextDraw();
868 EXPECT_SCOPED(AdvanceFrame());
869 client->SetNeedsCommitOnNextDraw();
870 task_runner().RunPendingTasks(); // Run posted deadline.
871 EXPECT_EQ(1, client->num_draws());
872 EXPECT_TRUE(scheduler_->CommitPending());
873 EXPECT_TRUE(client->needs_begin_frames());
874 scheduler_->NotifyBeginMainFrameStarted();
875 scheduler_->NotifyReadyToCommit();
876 scheduler_->NotifyReadyToActivate();
878 EXPECT_SCOPED(AdvanceFrame());
879 task_runner().RunPendingTasks(); // Run posted deadline.
880 EXPECT_EQ(2, client->num_draws());
882 EXPECT_FALSE(scheduler_->RedrawPending());
883 EXPECT_FALSE(scheduler_->CommitPending());
884 EXPECT_TRUE(client->needs_begin_frames());
886 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
887 // swap.
888 EXPECT_SCOPED(AdvanceFrame());
889 task_runner().RunPendingTasks(); // Run posted deadline.
890 EXPECT_EQ(2, client->num_draws());
891 EXPECT_FALSE(scheduler_->RedrawPending());
892 EXPECT_FALSE(scheduler_->CommitPending());
893 EXPECT_FALSE(client->needs_begin_frames());
896 // Tests that when a draw fails then the pending commit should not be dropped.
897 TEST_F(SchedulerTest, RequestCommitInsideFailedDraw) {
898 SchedulerClientThatsetNeedsDrawInsideDraw* client =
899 new SchedulerClientThatsetNeedsDrawInsideDraw;
900 scheduler_settings_.use_external_begin_frame_source = true;
901 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
903 client->SetDrawWillHappen(false);
905 scheduler_->SetNeedsRedraw();
906 EXPECT_TRUE(scheduler_->RedrawPending());
907 EXPECT_TRUE(client->needs_begin_frames());
908 EXPECT_EQ(0, client->num_draws());
910 // Fail the draw.
911 EXPECT_SCOPED(AdvanceFrame());
912 task_runner().RunPendingTasks(); // Run posted deadline.
913 EXPECT_EQ(1, client->num_draws());
915 // We have a commit pending and the draw failed, and we didn't lose the commit
916 // request.
917 EXPECT_TRUE(scheduler_->CommitPending());
918 EXPECT_TRUE(scheduler_->RedrawPending());
919 EXPECT_TRUE(client->needs_begin_frames());
921 // Fail the draw again.
922 EXPECT_SCOPED(AdvanceFrame());
924 task_runner().RunPendingTasks(); // Run posted deadline.
925 EXPECT_EQ(2, client->num_draws());
926 EXPECT_TRUE(scheduler_->CommitPending());
927 EXPECT_TRUE(scheduler_->RedrawPending());
928 EXPECT_TRUE(client->needs_begin_frames());
930 // Draw successfully.
931 client->SetDrawWillHappen(true);
932 EXPECT_SCOPED(AdvanceFrame());
933 task_runner().RunPendingTasks(); // Run posted deadline.
934 EXPECT_EQ(3, client->num_draws());
935 EXPECT_TRUE(scheduler_->CommitPending());
936 EXPECT_FALSE(scheduler_->RedrawPending());
937 EXPECT_TRUE(client->needs_begin_frames());
940 TEST_F(SchedulerTest, NoSwapWhenDrawFails) {
941 SchedulerClientThatSetNeedsCommitInsideDraw* client =
942 new SchedulerClientThatSetNeedsCommitInsideDraw;
943 scheduler_settings_.use_external_begin_frame_source = true;
944 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
946 scheduler_->SetNeedsRedraw();
947 EXPECT_TRUE(scheduler_->RedrawPending());
948 EXPECT_TRUE(client->needs_begin_frames());
949 EXPECT_EQ(0, client->num_draws());
951 // Draw successfully, this starts a new frame.
952 client->SetNeedsCommitOnNextDraw();
953 EXPECT_SCOPED(AdvanceFrame());
954 task_runner().RunPendingTasks(); // Run posted deadline.
955 EXPECT_EQ(1, client->num_draws());
957 scheduler_->SetNeedsRedraw();
958 EXPECT_TRUE(scheduler_->RedrawPending());
959 EXPECT_TRUE(client->needs_begin_frames());
961 // Fail to draw, this should not start a frame.
962 client->SetDrawWillHappen(false);
963 client->SetNeedsCommitOnNextDraw();
964 EXPECT_SCOPED(AdvanceFrame());
965 task_runner().RunPendingTasks(); // Run posted deadline.
966 EXPECT_EQ(2, client->num_draws());
969 class SchedulerClientNeedsPrepareTilesInDraw : public FakeSchedulerClient {
970 public:
971 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
972 scheduler_->SetNeedsPrepareTiles();
973 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
977 // Test prepare tiles is independant of draws.
978 TEST_F(SchedulerTest, PrepareTiles) {
979 SchedulerClientNeedsPrepareTilesInDraw* client =
980 new SchedulerClientNeedsPrepareTilesInDraw;
981 scheduler_settings_.use_external_begin_frame_source = true;
982 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
984 // Request both draw and prepare tiles. PrepareTiles shouldn't
985 // be trigged until BeginImplFrame.
986 client->Reset();
987 scheduler_->SetNeedsPrepareTiles();
988 scheduler_->SetNeedsRedraw();
989 EXPECT_TRUE(scheduler_->RedrawPending());
990 EXPECT_TRUE(scheduler_->PrepareTilesPending());
991 EXPECT_TRUE(client->needs_begin_frames());
992 EXPECT_EQ(0, client->num_draws());
993 EXPECT_FALSE(client->HasAction("ScheduledActionPrepareTiles"));
994 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
996 // We have no immediate actions to perform, so the BeginImplFrame should post
997 // the deadline task.
998 client->Reset();
999 EXPECT_SCOPED(AdvanceFrame());
1000 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1001 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1002 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1004 // On the deadline, he actions should have occured in the right order.
1005 client->Reset();
1006 task_runner().RunPendingTasks(); // Run posted deadline.
1007 EXPECT_EQ(1, client->num_draws());
1008 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1009 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1010 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1011 client->ActionIndex("ScheduledActionPrepareTiles"));
1012 EXPECT_FALSE(scheduler_->RedrawPending());
1013 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1014 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1016 // Request a draw. We don't need a PrepareTiles yet.
1017 client->Reset();
1018 scheduler_->SetNeedsRedraw();
1019 EXPECT_TRUE(scheduler_->RedrawPending());
1020 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1021 EXPECT_TRUE(client->needs_begin_frames());
1022 EXPECT_EQ(0, client->num_draws());
1024 // We have no immediate actions to perform, so the BeginImplFrame should post
1025 // the deadline task.
1026 client->Reset();
1027 EXPECT_SCOPED(AdvanceFrame());
1028 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1029 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1030 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1032 // Draw. The draw will trigger SetNeedsPrepareTiles, and
1033 // then the PrepareTiles action will be triggered after the Draw.
1034 // Afterwards, neither a draw nor PrepareTiles are pending.
1035 client->Reset();
1036 task_runner().RunPendingTasks(); // Run posted deadline.
1037 EXPECT_EQ(1, client->num_draws());
1038 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1039 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1040 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1041 client->ActionIndex("ScheduledActionPrepareTiles"));
1042 EXPECT_FALSE(scheduler_->RedrawPending());
1043 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1044 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1046 // We need a BeginImplFrame where we don't swap to go idle.
1047 client->Reset();
1048 EXPECT_SCOPED(AdvanceFrame());
1049 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1050 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1051 client->Reset();
1052 task_runner().RunPendingTasks(); // Run posted deadline.
1053 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1054 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1055 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1056 EXPECT_EQ(0, client->num_draws());
1058 // Now trigger a PrepareTiles outside of a draw. We will then need
1059 // a begin-frame for the PrepareTiles, but we don't need a draw.
1060 client->Reset();
1061 EXPECT_FALSE(client->needs_begin_frames());
1062 scheduler_->SetNeedsPrepareTiles();
1063 EXPECT_TRUE(client->needs_begin_frames());
1064 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1065 EXPECT_FALSE(scheduler_->RedrawPending());
1067 // BeginImplFrame. There will be no draw, only PrepareTiles.
1068 client->Reset();
1069 EXPECT_SCOPED(AdvanceFrame());
1070 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1071 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1072 client->Reset();
1073 task_runner().RunPendingTasks(); // Run posted deadline.
1074 EXPECT_EQ(0, client->num_draws());
1075 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1076 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1077 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1080 // Test that PrepareTiles only happens once per frame. If an external caller
1081 // initiates it, then the state machine should not PrepareTiles on that frame.
1082 TEST_F(SchedulerTest, PrepareTilesOncePerFrame) {
1083 scheduler_settings_.use_external_begin_frame_source = true;
1084 SetUpScheduler(true);
1086 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
1087 // again.
1088 scheduler_->SetNeedsPrepareTiles();
1089 scheduler_->SetNeedsRedraw();
1090 client_->Reset();
1091 EXPECT_SCOPED(AdvanceFrame());
1092 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1093 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1094 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1096 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1097 scheduler_->WillPrepareTiles();
1098 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1099 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1101 client_->Reset();
1102 task_runner().RunPendingTasks(); // Run posted deadline.
1103 EXPECT_EQ(1, client_->num_draws());
1104 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1105 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1106 EXPECT_FALSE(scheduler_->RedrawPending());
1107 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1108 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1110 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1111 scheduler_->SetNeedsPrepareTiles();
1112 scheduler_->SetNeedsRedraw();
1113 client_->Reset();
1114 EXPECT_SCOPED(AdvanceFrame());
1115 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1116 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1117 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1119 client_->Reset();
1120 task_runner().RunPendingTasks(); // Run posted deadline.
1121 EXPECT_EQ(1, client_->num_draws());
1122 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1123 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1124 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1125 client_->ActionIndex("ScheduledActionPrepareTiles"));
1126 EXPECT_FALSE(scheduler_->RedrawPending());
1127 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1128 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1130 // If we get another DidPrepareTiles within the same frame, we should
1131 // not PrepareTiles on the next frame.
1132 scheduler_->WillPrepareTiles();
1133 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1134 scheduler_->SetNeedsPrepareTiles();
1135 scheduler_->SetNeedsRedraw();
1136 client_->Reset();
1137 EXPECT_SCOPED(AdvanceFrame());
1138 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1139 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1140 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1142 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1144 client_->Reset();
1145 task_runner().RunPendingTasks(); // Run posted deadline.
1146 EXPECT_EQ(1, client_->num_draws());
1147 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1148 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1149 EXPECT_FALSE(scheduler_->RedrawPending());
1150 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1152 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1153 // frame. This verifies we don't alternate calling PrepareTiles once and
1154 // twice.
1155 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1156 scheduler_->WillPrepareTiles();
1157 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1158 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1159 scheduler_->SetNeedsPrepareTiles();
1160 scheduler_->SetNeedsRedraw();
1161 client_->Reset();
1162 EXPECT_SCOPED(AdvanceFrame());
1163 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1164 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1165 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1167 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1169 client_->Reset();
1170 task_runner().RunPendingTasks(); // Run posted deadline.
1171 EXPECT_EQ(1, client_->num_draws());
1172 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1173 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1174 EXPECT_FALSE(scheduler_->RedrawPending());
1175 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1177 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1178 scheduler_->SetNeedsPrepareTiles();
1179 scheduler_->SetNeedsRedraw();
1180 client_->Reset();
1181 EXPECT_SCOPED(AdvanceFrame());
1182 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1183 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1184 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1186 client_->Reset();
1187 task_runner().RunPendingTasks(); // Run posted deadline.
1188 EXPECT_EQ(1, client_->num_draws());
1189 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1190 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1191 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1192 client_->ActionIndex("ScheduledActionPrepareTiles"));
1193 EXPECT_FALSE(scheduler_->RedrawPending());
1194 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1195 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1198 TEST_F(SchedulerTest, PrepareTilesFunnelResetOnVisibilityChange) {
1199 scoped_ptr<SchedulerClientNeedsPrepareTilesInDraw> client =
1200 make_scoped_ptr(new SchedulerClientNeedsPrepareTilesInDraw);
1201 scheduler_settings_.use_external_begin_frame_source = true;
1202 SetUpScheduler(client.Pass(), true);
1204 // Simulate a few visibility changes and associated PrepareTiles.
1205 for (int i = 0; i < 10; i++) {
1206 scheduler_->SetVisible(false);
1207 scheduler_->WillPrepareTiles();
1208 scheduler_->DidPrepareTiles();
1210 scheduler_->SetVisible(true);
1211 scheduler_->WillPrepareTiles();
1212 scheduler_->DidPrepareTiles();
1215 client_->Reset();
1216 scheduler_->SetNeedsRedraw();
1217 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1219 client_->Reset();
1220 AdvanceFrame();
1221 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1222 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1223 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1225 client_->Reset();
1226 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1227 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1228 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
1229 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 1, 2);
1232 TEST_F(SchedulerTest, TriggerBeginFrameDeadlineEarly) {
1233 SchedulerClientNeedsPrepareTilesInDraw* client =
1234 new SchedulerClientNeedsPrepareTilesInDraw;
1235 scheduler_settings_.use_external_begin_frame_source = true;
1236 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1238 scheduler_->SetNeedsRedraw();
1239 EXPECT_SCOPED(AdvanceFrame());
1241 // The deadline should be zero since there is no work other than drawing
1242 // pending.
1243 EXPECT_EQ(base::TimeTicks(), client->posted_begin_impl_frame_deadline());
1246 TEST_F(SchedulerTest, WaitForReadyToDrawDoNotPostDeadline) {
1247 SchedulerClientNeedsPrepareTilesInDraw* client =
1248 new SchedulerClientNeedsPrepareTilesInDraw;
1249 scheduler_settings_.use_external_begin_frame_source = true;
1250 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1252 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1253 scheduler_->SetNeedsCommit();
1254 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1255 client_->Reset();
1257 // Begin new frame.
1258 EXPECT_SCOPED(AdvanceFrame());
1259 scheduler_->NotifyBeginMainFrameStarted();
1260 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1261 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1263 client_->Reset();
1264 scheduler_->NotifyReadyToCommit();
1265 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1267 client_->Reset();
1268 scheduler_->NotifyReadyToActivate();
1269 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
1271 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1272 // the mode.
1273 scheduler_->SetWaitForReadyToDraw();
1274 client_->Reset();
1275 task_runner().RunPendingTasks(); // Try to run posted deadline.
1276 // There is no posted deadline.
1277 EXPECT_NO_ACTION(client_);
1279 // Scheduler received ready to draw signal, and posted deadline.
1280 scheduler_->NotifyReadyToDraw();
1281 client_->Reset();
1282 task_runner().RunPendingTasks(); // Run posted deadline.
1283 EXPECT_EQ(1, client_->num_draws());
1284 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1287 TEST_F(SchedulerTest, WaitForReadyToDrawCancelledWhenLostOutputSurface) {
1288 SchedulerClientNeedsPrepareTilesInDraw* client =
1289 new SchedulerClientNeedsPrepareTilesInDraw;
1290 scheduler_settings_.use_external_begin_frame_source = true;
1291 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1293 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1294 scheduler_->SetNeedsCommit();
1295 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1296 client_->Reset();
1298 // Begin new frame.
1299 EXPECT_SCOPED(AdvanceFrame());
1300 scheduler_->NotifyBeginMainFrameStarted();
1301 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1302 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1304 client_->Reset();
1305 scheduler_->NotifyReadyToCommit();
1306 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1308 client_->Reset();
1309 scheduler_->NotifyReadyToActivate();
1310 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
1312 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1313 // the mode.
1314 scheduler_->SetWaitForReadyToDraw();
1315 client_->Reset();
1316 task_runner().RunPendingTasks(); // Try to run posted deadline.
1317 // There is no posted deadline.
1318 EXPECT_NO_ACTION(client_);
1320 // Scheduler loses output surface, and stops waiting for ready to draw signal.
1321 client_->Reset();
1322 scheduler_->DidLoseOutputSurface();
1323 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1324 task_runner().RunPendingTasks(); // Run posted deadline.
1325 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
1326 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
1327 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
1330 void SchedulerTest::CheckMainFrameSkippedAfterLateCommit(
1331 bool expect_send_begin_main_frame) {
1332 // Impl thread hits deadline before commit finishes.
1333 scheduler_->SetNeedsCommit();
1334 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1335 EXPECT_SCOPED(AdvanceFrame());
1336 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1337 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1338 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1339 scheduler_->NotifyBeginMainFrameStarted();
1340 scheduler_->NotifyReadyToCommit();
1341 scheduler_->NotifyReadyToActivate();
1342 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5);
1343 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5);
1344 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5);
1345 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5);
1346 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 4, 5);
1347 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1349 client_->Reset();
1350 scheduler_->SetNeedsCommit();
1351 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1352 EXPECT_SCOPED(AdvanceFrame());
1353 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1354 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1355 EXPECT_EQ(expect_send_begin_main_frame,
1356 scheduler_->MainThreadIsInHighLatencyMode());
1357 EXPECT_EQ(expect_send_begin_main_frame,
1358 client_->HasAction("ScheduledActionSendBeginMainFrame"));
1361 TEST_F(SchedulerTest, MainFrameSkippedAfterLateCommit) {
1362 scheduler_settings_.use_external_begin_frame_source = true;
1363 SetUpScheduler(true);
1365 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1366 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1368 bool expect_send_begin_main_frame = false;
1369 EXPECT_SCOPED(
1370 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1373 TEST_F(SchedulerTest,
1374 MainFrameNotSkippedAfterLateCommitInPreferImplLatencyMode) {
1375 scheduler_settings_.use_external_begin_frame_source = true;
1376 SetUpScheduler(true);
1377 scheduler_->SetImplLatencyTakesPriority(true);
1379 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1380 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1382 bool expect_send_begin_main_frame = true;
1383 EXPECT_SCOPED(
1384 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1387 TEST_F(SchedulerTest,
1388 MainFrameNotSkippedAfterLateCommit_CommitEstimateTooLong) {
1389 scheduler_settings_.use_external_begin_frame_source = true;
1390 SetUpScheduler(true);
1391 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1392 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1393 auto slow_duration = base::TimeDelta::FromSeconds(1);
1394 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate(
1395 slow_duration);
1397 bool expect_send_begin_main_frame = true;
1398 EXPECT_SCOPED(
1399 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1402 TEST_F(SchedulerTest,
1403 MainFrameNotSkippedAfterLateCommit_ReadyToActivateEstimateTooLong) {
1404 scheduler_settings_.use_external_begin_frame_source = true;
1405 SetUpScheduler(true);
1406 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1407 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1408 auto slow_duration = base::TimeDelta::FromSeconds(1);
1409 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate(
1410 slow_duration);
1412 bool expect_send_begin_main_frame = true;
1413 EXPECT_SCOPED(
1414 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1417 TEST_F(SchedulerTest,
1418 MainFrameNotSkippedAfterLateCommit_ActivateEstimateTooLong) {
1419 scheduler_settings_.use_external_begin_frame_source = true;
1420 SetUpScheduler(true);
1421 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1422 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1423 auto slow_duration = base::TimeDelta::FromSeconds(1);
1424 fake_compositor_timing_history_->SetActivateDurationEstimate(slow_duration);
1426 bool expect_send_begin_main_frame = true;
1427 EXPECT_SCOPED(
1428 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1431 TEST_F(SchedulerTest, MainFrameNotSkippedAfterLateCommit_DrawEstimateTooLong) {
1432 scheduler_settings_.use_external_begin_frame_source = true;
1433 SetUpScheduler(true);
1434 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1435 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1436 auto slow_duration = base::TimeDelta::FromSeconds(1);
1437 fake_compositor_timing_history_->SetDrawDurationEstimate(slow_duration);
1439 bool expect_send_begin_main_frame = true;
1440 EXPECT_SCOPED(
1441 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1444 void SchedulerTest::ImplFrameSkippedAfterLateSwapAck(
1445 bool swap_ack_before_deadline) {
1446 // To get into a high latency state, this test disables automatic swap acks.
1447 scheduler_->SetMaxSwapsPending(1);
1448 client_->SetAutomaticSwapAck(false);
1450 // Draw and swap for first BeginFrame
1451 client_->Reset();
1452 scheduler_->SetNeedsCommit();
1453 scheduler_->SetNeedsRedraw();
1454 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1455 SendNextBeginFrame();
1456 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 4);
1457 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 4);
1458 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4);
1459 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 4);
1461 client_->Reset();
1462 scheduler_->NotifyBeginMainFrameStarted();
1463 scheduler_->NotifyReadyToCommit();
1464 scheduler_->NotifyReadyToActivate();
1465 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1466 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1467 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4);
1468 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4);
1469 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4);
1470 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1472 // Verify we skip every other frame if the swap ack consistently
1473 // comes back late.
1474 for (int i = 0; i < 10; i++) {
1475 // Not calling scheduler_->DidSwapBuffersComplete() until after next
1476 // BeginImplFrame puts the impl thread in high latency mode.
1477 client_->Reset();
1478 scheduler_->SetNeedsCommit();
1479 scheduler_->SetNeedsRedraw();
1480 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1481 SendNextBeginFrame();
1482 // Verify that we skip the BeginImplFrame
1483 EXPECT_NO_ACTION(client_);
1484 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1485 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1487 // Verify that we do not perform any actions after we are no longer
1488 // swap throttled.
1489 client_->Reset();
1490 if (swap_ack_before_deadline) {
1491 // It shouldn't matter if the swap ack comes back before the deadline...
1492 scheduler_->DidSwapBuffersComplete();
1493 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1494 } else {
1495 // ... or after the deadline.
1496 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1497 scheduler_->DidSwapBuffersComplete();
1499 EXPECT_NO_ACTION(client_);
1501 // Verify that we start the next BeginImplFrame and continue normally
1502 // after having just skipped a BeginImplFrame.
1503 client_->Reset();
1504 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1505 SendNextBeginFrame();
1506 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
1507 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
1508 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3);
1510 client_->Reset();
1511 scheduler_->NotifyBeginMainFrameStarted();
1512 scheduler_->NotifyReadyToCommit();
1513 scheduler_->NotifyReadyToActivate();
1514 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1515 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4);
1516 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4);
1517 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4);
1518 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1522 TEST_F(SchedulerTest,
1523 ImplFrameSkippedAfterLateSwapAck_FastEstimates_SwapAckThenDeadline) {
1524 scheduler_settings_.use_external_begin_frame_source = true;
1525 SetUpScheduler(true);
1527 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1528 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1530 bool swap_ack_before_deadline = true;
1531 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline));
1534 TEST_F(SchedulerTest,
1535 ImplFrameSkippedAfterLateSwapAck_FastEstimates_DeadlineThenSwapAck) {
1536 scheduler_settings_.use_external_begin_frame_source = true;
1537 SetUpScheduler(true);
1539 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1540 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1542 bool swap_ack_before_deadline = false;
1543 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline));
1546 TEST_F(SchedulerTest,
1547 ImplFrameSkippedAfterLateSwapAck_ImplLatencyTakesPriority) {
1548 scheduler_settings_.use_external_begin_frame_source = true;
1549 SetUpScheduler(true);
1551 // Even if every estimate related to the main thread is slow, we should
1552 // still expect to recover impl thread latency if the draw is fast and we
1553 // are in impl latency takes priority.
1554 scheduler_->SetImplLatencyTakesPriority(true);
1555 auto slow_duration = base::TimeDelta::FromSeconds(1);
1556 fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration);
1557 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1558 fake_compositor_timing_history_->SetDrawDurationEstimate(fast_duration);
1560 bool swap_ack_before_deadline = false;
1561 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline));
1564 TEST_F(SchedulerTest,
1565 ImplFrameSkippedAfterLateSwapAck_OnlyImplSideUpdatesExpected) {
1566 // This tests that we recover impl thread latency when there are no commits.
1567 scheduler_settings_.use_external_begin_frame_source = true;
1568 SetUpScheduler(true);
1570 // To get into a high latency state, this test disables automatic swap acks.
1571 scheduler_->SetMaxSwapsPending(1);
1572 client_->SetAutomaticSwapAck(false);
1574 // Even if every estimate related to the main thread is slow, we should
1575 // still expect to recover impl thread latency if there are no commits from
1576 // the main thread.
1577 auto slow_duration = base::TimeDelta::FromSeconds(1);
1578 fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration);
1579 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1580 fake_compositor_timing_history_->SetDrawDurationEstimate(fast_duration);
1582 // Draw and swap for first BeginFrame
1583 client_->Reset();
1584 scheduler_->SetNeedsRedraw();
1585 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1586 SendNextBeginFrame();
1587 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3);
1588 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3);
1589 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 3);
1591 client_->Reset();
1592 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1593 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1594 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
1596 // Verify we skip every other frame if the swap ack consistently
1597 // comes back late.
1598 for (int i = 0; i < 10; i++) {
1599 // Not calling scheduler_->DidSwapBuffersComplete() until after next
1600 // BeginImplFrame puts the impl thread in high latency mode.
1601 client_->Reset();
1602 scheduler_->SetNeedsRedraw();
1603 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1604 SendNextBeginFrame();
1605 // Verify that we skip the BeginImplFrame
1606 EXPECT_NO_ACTION(client_);
1607 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1608 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1610 // Verify that we do not perform any actions after we are no longer
1611 // swap throttled.
1612 client_->Reset();
1613 scheduler_->DidSwapBuffersComplete();
1614 EXPECT_NO_ACTION(client_);
1616 // Verify that we start the next BeginImplFrame and continue normally
1617 // after having just skipped a BeginImplFrame.
1618 client_->Reset();
1619 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1620 SendNextBeginFrame();
1621 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1622 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1624 client_->Reset();
1625 // Deadline should be immediate.
1626 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1627 task_runner().RunUntilTime(now_src_->NowTicks());
1628 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1629 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
1633 void SchedulerTest::ImplFrameIsNotSkippedAfterLateSwapAck() {
1634 // To get into a high latency state, this test disables automatic swap acks.
1635 scheduler_->SetMaxSwapsPending(1);
1636 client_->SetAutomaticSwapAck(false);
1638 // Draw and swap for first BeginFrame
1639 client_->Reset();
1640 scheduler_->SetNeedsCommit();
1641 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1642 SendNextBeginFrame();
1643 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3);
1644 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3);
1645 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3);
1647 client_->Reset();
1648 scheduler_->NotifyBeginMainFrameStarted();
1649 scheduler_->NotifyReadyToCommit();
1650 scheduler_->NotifyReadyToActivate();
1651 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1652 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1653 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4);
1654 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4);
1655 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4);
1656 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1658 // Verify impl thread consistently operates in high latency mode
1659 // without skipping any frames.
1660 for (int i = 0; i < 10; i++) {
1661 // Not calling scheduler_->DidSwapBuffersComplete() until after next frame
1662 // puts the impl thread in high latency mode.
1663 client_->Reset();
1664 scheduler_->SetNeedsCommit();
1665 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1666 SendNextBeginFrame();
1667 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
1668 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1669 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1671 client_->Reset();
1672 scheduler_->DidSwapBuffersComplete();
1673 scheduler_->NotifyBeginMainFrameStarted();
1674 scheduler_->NotifyReadyToCommit();
1675 scheduler_->NotifyReadyToActivate();
1676 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1678 // Verify that we don't skip the actions of the BeginImplFrame
1679 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 0, 5);
1680 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 5);
1681 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 2, 5);
1682 EXPECT_ACTION("ScheduledActionAnimate", client_, 3, 5);
1683 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 5);
1687 TEST_F(SchedulerTest,
1688 ImplFrameIsNotSkippedAfterLateSwapAck_CommitEstimateTooLong) {
1689 scheduler_settings_.use_external_begin_frame_source = true;
1690 SetUpScheduler(true);
1691 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1692 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1693 auto slow_duration = base::TimeDelta::FromSeconds(1);
1694 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate(
1695 slow_duration);
1696 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck());
1699 TEST_F(SchedulerTest,
1700 ImplFrameIsNotSkippedAfterLateSwapAck_ReadyToActivateEstimateTooLong) {
1701 scheduler_settings_.use_external_begin_frame_source = true;
1702 SetUpScheduler(true);
1703 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1704 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1705 auto slow_duration = base::TimeDelta::FromSeconds(1);
1706 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate(
1707 slow_duration);
1708 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck());
1711 TEST_F(SchedulerTest,
1712 ImplFrameIsNotSkippedAfterLateSwapAck_ActivateEstimateTooLong) {
1713 scheduler_settings_.use_external_begin_frame_source = true;
1714 SetUpScheduler(true);
1715 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1716 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1717 auto slow_duration = base::TimeDelta::FromSeconds(1);
1718 fake_compositor_timing_history_->SetActivateDurationEstimate(slow_duration);
1719 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck());
1722 TEST_F(SchedulerTest,
1723 ImplFrameIsNotSkippedAfterLateSwapAck_DrawEstimateTooLong) {
1724 scheduler_settings_.use_external_begin_frame_source = true;
1725 SetUpScheduler(true);
1726 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1727 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1728 auto slow_duration = base::TimeDelta::FromSeconds(1);
1729 fake_compositor_timing_history_->SetDrawDurationEstimate(slow_duration);
1730 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck());
1733 TEST_F(SchedulerTest,
1734 MainFrameThenImplFrameSkippedAfterLateCommitAndLateSwapAck) {
1735 // Set up client with custom estimates.
1736 // This test starts off with expensive estimates to prevent latency recovery
1737 // initially, then lowers the estimates to enable it once both the main
1738 // and impl threads are in a high latency mode.
1739 scheduler_settings_.use_external_begin_frame_source = true;
1740 SetUpScheduler(true);
1742 auto slow_duration = base::TimeDelta::FromSeconds(1);
1743 fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration);
1745 // To get into a high latency state, this test disables automatic swap acks.
1746 scheduler_->SetMaxSwapsPending(1);
1747 client_->SetAutomaticSwapAck(false);
1749 // Impl thread hits deadline before commit finishes to make
1750 // MainThreadIsInHighLatencyMode true
1751 client_->Reset();
1752 scheduler_->SetNeedsCommit();
1753 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1754 EXPECT_SCOPED(AdvanceFrame());
1755 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1756 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1757 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1758 scheduler_->NotifyBeginMainFrameStarted();
1759 scheduler_->NotifyReadyToCommit();
1760 scheduler_->NotifyReadyToActivate();
1761 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1763 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5);
1764 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5);
1765 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5);
1766 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5);
1767 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 4, 5);
1769 // Draw and swap for first commit, start second commit.
1770 client_->Reset();
1771 scheduler_->SetNeedsCommit();
1772 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1773 EXPECT_SCOPED(AdvanceFrame());
1774 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1775 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1776 scheduler_->NotifyBeginMainFrameStarted();
1777 scheduler_->NotifyReadyToCommit();
1778 scheduler_->NotifyReadyToActivate();
1780 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6);
1781 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 6);
1782 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 6);
1783 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 6);
1784 EXPECT_ACTION("ScheduledActionCommit", client_, 4, 6);
1785 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 5, 6);
1787 // Don't call scheduler_->DidSwapBuffersComplete() until after next frame
1788 // to put the impl thread in a high latency mode.
1789 client_->Reset();
1790 scheduler_->SetNeedsCommit();
1791 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1792 EXPECT_TRUE(scheduler_->SwapThrottled());
1793 EXPECT_SCOPED(AdvanceFrame());
1794 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1795 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1797 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1798 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1799 // Note: BeginMainFrame and swap are skipped here because of
1800 // swap ack backpressure, not because of latency recovery.
1801 EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame"));
1802 EXPECT_FALSE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1803 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1805 // Lower estimates so that the scheduler will attempt latency recovery.
1806 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1807 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1809 // Now that both threads are in a high latency mode, make sure we
1810 // skip the BeginMainFrame, then the BeginImplFrame, but not both
1811 // at the same time.
1813 // Verify we skip BeginMainFrame first.
1814 client_->Reset();
1815 // Previous commit request is still outstanding.
1816 EXPECT_TRUE(scheduler_->NeedsCommit());
1817 EXPECT_TRUE(scheduler_->SwapThrottled());
1818 SendNextBeginFrame();
1819 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1820 scheduler_->DidSwapBuffersComplete();
1821 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1823 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1824 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
1825 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
1826 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3);
1828 // Verify we skip the BeginImplFrame second.
1829 client_->Reset();
1830 // Previous commit request is still outstanding.
1831 EXPECT_TRUE(scheduler_->NeedsCommit());
1832 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1833 SendNextBeginFrame();
1834 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1835 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1836 scheduler_->DidSwapBuffersComplete();
1837 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1839 EXPECT_NO_ACTION(client_);
1841 // Then verify we operate in a low latency mode.
1842 client_->Reset();
1843 // Previous commit request is still outstanding.
1844 EXPECT_TRUE(scheduler_->NeedsCommit());
1845 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1846 SendNextBeginFrame();
1847 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1848 scheduler_->NotifyBeginMainFrameStarted();
1849 scheduler_->NotifyReadyToCommit();
1850 scheduler_->NotifyReadyToActivate();
1851 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1852 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1853 scheduler_->DidSwapBuffersComplete();
1854 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1856 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6);
1857 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 6);
1858 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 6);
1859 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 3, 6);
1860 EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 6);
1861 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 5, 6);
1864 TEST_F(
1865 SchedulerTest,
1866 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) {
1867 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1868 // thread. This prevents the scheduler from receiving any pending swap acks.
1870 scheduler_settings_.use_external_begin_frame_source = true;
1871 scheduler_settings_.main_frame_while_swap_throttled_enabled = true;
1872 SetUpScheduler(true);
1874 // Disables automatic swap acks so this test can force swap ack throttling
1875 // to simulate a blocked Browser ui thread.
1876 scheduler_->SetMaxSwapsPending(1);
1877 client_->SetAutomaticSwapAck(false);
1879 // Get a new active tree in main-thread high latency mode and put us
1880 // in a swap throttled state.
1881 client_->Reset();
1882 EXPECT_FALSE(scheduler_->CommitPending());
1883 scheduler_->SetNeedsCommit();
1884 scheduler_->SetNeedsRedraw();
1885 EXPECT_SCOPED(AdvanceFrame());
1886 EXPECT_TRUE(scheduler_->CommitPending());
1887 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1888 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1889 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1890 scheduler_->NotifyBeginMainFrameStarted();
1891 scheduler_->NotifyReadyToCommit();
1892 scheduler_->NotifyReadyToActivate();
1893 EXPECT_FALSE(scheduler_->CommitPending());
1894 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 7);
1895 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 7);
1896 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 7);
1897 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 7);
1898 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 7);
1899 EXPECT_ACTION("ScheduledActionCommit", client_, 5, 7);
1900 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 6, 7);
1902 // Make sure that we can finish the next commit even while swap throttled.
1903 client_->Reset();
1904 EXPECT_FALSE(scheduler_->CommitPending());
1905 scheduler_->SetNeedsCommit();
1906 EXPECT_SCOPED(AdvanceFrame());
1907 scheduler_->NotifyBeginMainFrameStarted();
1908 scheduler_->NotifyReadyToCommit();
1909 scheduler_->NotifyReadyToActivate();
1910 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1911 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1912 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1913 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 5);
1914 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 5);
1915 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5);
1916 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5);
1917 EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 5);
1919 // Make sure we do not send a BeginMainFrame while swap throttled and
1920 // we have both a pending tree and an active tree.
1921 client_->Reset();
1922 EXPECT_FALSE(scheduler_->CommitPending());
1923 scheduler_->SetNeedsCommit();
1924 EXPECT_SCOPED(AdvanceFrame());
1925 EXPECT_FALSE(scheduler_->CommitPending());
1926 task_runner().RunPendingTasks(); // Run posted deadline.
1927 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1928 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1931 TEST_F(SchedulerTest,
1932 Deadlock_NoBeginMainFrameWhileSwapTrottledAndPipelineFull) {
1933 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1934 // thread. This prevents the scheduler from receiving any pending swap acks.
1936 // This particular test makes sure we do not send a BeginMainFrame while
1937 // swap trottled and we have a pending tree and active tree that
1938 // still needs to be drawn for the first time.
1940 scheduler_settings_.use_external_begin_frame_source = true;
1941 scheduler_settings_.main_frame_while_swap_throttled_enabled = true;
1942 scheduler_settings_.main_frame_before_activation_enabled = true;
1943 SetUpScheduler(true);
1945 // Disables automatic swap acks so this test can force swap ack throttling
1946 // to simulate a blocked Browser ui thread.
1947 scheduler_->SetMaxSwapsPending(1);
1948 client_->SetAutomaticSwapAck(false);
1950 // Start a new commit in main-thread high latency mode and hold off on
1951 // activation.
1952 client_->Reset();
1953 EXPECT_FALSE(scheduler_->CommitPending());
1954 scheduler_->SetNeedsCommit();
1955 scheduler_->SetNeedsRedraw();
1956 EXPECT_SCOPED(AdvanceFrame());
1957 EXPECT_TRUE(scheduler_->CommitPending());
1958 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1959 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1960 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1961 scheduler_->DidSwapBuffersComplete();
1962 scheduler_->NotifyBeginMainFrameStarted();
1963 scheduler_->NotifyReadyToCommit();
1964 EXPECT_FALSE(scheduler_->CommitPending());
1965 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 6);
1966 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 6);
1967 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 6);
1968 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 6);
1969 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 6);
1970 EXPECT_ACTION("ScheduledActionCommit", client_, 5, 6);
1972 // Start another commit while we still have aa pending tree.
1973 // Enter a swap throttled state.
1974 client_->Reset();
1975 EXPECT_FALSE(scheduler_->CommitPending());
1976 scheduler_->SetNeedsCommit();
1977 scheduler_->SetNeedsRedraw();
1978 EXPECT_SCOPED(AdvanceFrame());
1979 EXPECT_TRUE(scheduler_->CommitPending());
1980 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1981 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1982 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1983 scheduler_->NotifyBeginMainFrameStarted();
1984 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4);
1985 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4);
1986 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4);
1987 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1989 // Can't commit yet because there's still a pending tree.
1990 client_->Reset();
1991 scheduler_->NotifyReadyToCommit();
1992 EXPECT_NO_ACTION(client_);
1994 // Activate the pending tree, which also unblocks the commit immediately.
1995 client_->Reset();
1996 scheduler_->NotifyReadyToActivate();
1997 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 2);
1998 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 2);
2000 // Make sure we do not send a BeginMainFrame while swap throttled and
2001 // we have both a pending tree and an active tree that still needs
2002 // it's first draw.
2003 client_->Reset();
2004 EXPECT_FALSE(scheduler_->CommitPending());
2005 scheduler_->SetNeedsCommit();
2006 EXPECT_SCOPED(AdvanceFrame());
2007 EXPECT_FALSE(scheduler_->CommitPending());
2008 task_runner().RunPendingTasks(); // Run posted deadline.
2009 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2010 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2013 TEST_F(
2014 SchedulerTest,
2015 CommitMakesProgressWhenIdleAndHasPendingTreeAndActiveTreeNeedsFirstDraw) {
2016 // This verifies we don't block commits longer than we need to
2017 // for performance reasons - not deadlock reasons.
2019 // Since we are simulating a long commit, set up a client with draw duration
2020 // estimates that prevent skipping main frames to get to low latency mode.
2021 scheduler_settings_.use_external_begin_frame_source = true;
2022 scheduler_settings_.main_frame_while_swap_throttled_enabled = true;
2023 scheduler_settings_.main_frame_before_activation_enabled = true;
2024 SetUpScheduler(true);
2026 // Disables automatic swap acks so this test can force swap ack throttling
2027 // to simulate a blocked Browser ui thread.
2028 scheduler_->SetMaxSwapsPending(1);
2029 client_->SetAutomaticSwapAck(false);
2031 // Start a new commit in main-thread high latency mode and hold off on
2032 // activation.
2033 client_->Reset();
2034 EXPECT_FALSE(scheduler_->CommitPending());
2035 scheduler_->SetNeedsCommit();
2036 scheduler_->SetNeedsRedraw();
2037 EXPECT_SCOPED(AdvanceFrame());
2038 EXPECT_TRUE(scheduler_->CommitPending());
2039 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2040 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2041 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2042 scheduler_->DidSwapBuffersComplete();
2043 scheduler_->NotifyBeginMainFrameStarted();
2044 scheduler_->NotifyReadyToCommit();
2045 EXPECT_FALSE(scheduler_->CommitPending());
2046 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 6);
2047 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 6);
2048 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 6);
2049 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 6);
2050 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 6);
2051 EXPECT_ACTION("ScheduledActionCommit", client_, 5, 6);
2053 // Start another commit while we still have an active tree.
2054 client_->Reset();
2055 EXPECT_FALSE(scheduler_->CommitPending());
2056 scheduler_->SetNeedsCommit();
2057 scheduler_->SetNeedsRedraw();
2058 EXPECT_SCOPED(AdvanceFrame());
2059 EXPECT_TRUE(scheduler_->CommitPending());
2060 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2061 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2062 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2063 scheduler_->DidSwapBuffersComplete();
2064 scheduler_->NotifyBeginMainFrameStarted();
2065 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4);
2066 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4);
2067 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4);
2068 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
2070 // Can't commit yet because there's still a pending tree.
2071 client_->Reset();
2072 scheduler_->NotifyReadyToCommit();
2073 EXPECT_NO_ACTION(client_);
2075 // Activate the pending tree, which also unblocks the commit immediately
2076 // while we are in an idle state.
2077 client_->Reset();
2078 scheduler_->NotifyReadyToActivate();
2079 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 2);
2080 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 2);
2083 TEST_F(SchedulerTest, BeginRetroFrame) {
2084 scheduler_settings_.use_external_begin_frame_source = true;
2085 SetUpScheduler(true);
2087 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2088 scheduler_->SetNeedsCommit();
2089 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2090 client_->Reset();
2092 // Create a BeginFrame with a long deadline to avoid race conditions.
2093 // This is the first BeginFrame, which will be handled immediately.
2094 BeginFrameArgs args =
2095 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2096 args.deadline += base::TimeDelta::FromHours(1);
2097 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2098 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2099 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2100 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2101 EXPECT_TRUE(client_->needs_begin_frames());
2102 client_->Reset();
2104 // Queue BeginFrames while we are still handling the previous BeginFrame.
2105 args.frame_time += base::TimeDelta::FromSeconds(1);
2106 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2107 args.frame_time += base::TimeDelta::FromSeconds(1);
2108 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2110 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2111 task_runner().RunPendingTasks(); // Run posted deadline.
2112 EXPECT_NO_ACTION(client_);
2113 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2114 EXPECT_TRUE(client_->needs_begin_frames());
2115 client_->Reset();
2117 // NotifyReadyToCommit should trigger the commit.
2118 scheduler_->NotifyBeginMainFrameStarted();
2119 scheduler_->NotifyReadyToCommit();
2120 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2121 EXPECT_TRUE(client_->needs_begin_frames());
2122 client_->Reset();
2124 // NotifyReadyToActivate should trigger the activation.
2125 scheduler_->NotifyReadyToActivate();
2126 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2127 EXPECT_TRUE(client_->needs_begin_frames());
2128 client_->Reset();
2130 // BeginImplFrame should prepare the draw.
2131 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2132 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2133 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2134 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2135 EXPECT_TRUE(client_->needs_begin_frames());
2136 client_->Reset();
2138 // BeginImplFrame deadline should draw.
2139 task_runner().RunPendingTasks(); // Run posted deadline.
2140 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2141 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2142 EXPECT_TRUE(client_->needs_begin_frames());
2143 client_->Reset();
2145 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2146 // to avoid excessive toggles.
2147 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2148 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
2149 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2150 client_->Reset();
2152 task_runner().RunPendingTasks(); // Run posted deadline.
2153 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
2154 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2155 client_->Reset();
2158 TEST_F(SchedulerTest, BeginRetroFrame_SwapThrottled) {
2159 scheduler_settings_.use_external_begin_frame_source = true;
2160 SetUpScheduler(true);
2162 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
2164 // To test swap ack throttling, this test disables automatic swap acks.
2165 scheduler_->SetMaxSwapsPending(1);
2166 client_->SetAutomaticSwapAck(false);
2168 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2169 client_->Reset();
2170 scheduler_->SetNeedsCommit();
2171 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2172 client_->Reset();
2174 EXPECT_SCOPED(AdvanceFrame());
2175 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2176 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2177 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2178 EXPECT_TRUE(client_->needs_begin_frames());
2179 client_->Reset();
2181 // Queue BeginFrame while we are still handling the previous BeginFrame.
2182 SendNextBeginFrame();
2183 EXPECT_NO_ACTION(client_);
2184 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2185 EXPECT_TRUE(client_->needs_begin_frames());
2186 client_->Reset();
2188 // NotifyReadyToCommit should trigger the pending commit.
2189 scheduler_->NotifyBeginMainFrameStarted();
2190 scheduler_->NotifyReadyToCommit();
2191 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2192 EXPECT_TRUE(client_->needs_begin_frames());
2193 client_->Reset();
2195 // NotifyReadyToActivate should trigger the activation and draw.
2196 scheduler_->NotifyReadyToActivate();
2197 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2198 EXPECT_TRUE(client_->needs_begin_frames());
2199 client_->Reset();
2201 // Swapping will put us into a swap throttled state.
2202 // Run posted deadline.
2203 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2204 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2205 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2206 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2207 EXPECT_TRUE(client_->needs_begin_frames());
2208 client_->Reset();
2210 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
2211 // but not a BeginMainFrame or draw.
2212 scheduler_->SetNeedsCommit();
2213 scheduler_->SetNeedsRedraw();
2214 // Run posted BeginRetroFrame.
2215 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
2216 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2217 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2218 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2219 EXPECT_TRUE(client_->needs_begin_frames());
2220 client_->Reset();
2222 // Let time pass sufficiently beyond the regular deadline but not beyond the
2223 // late deadline.
2224 now_src()->Advance(BeginFrameArgs::DefaultInterval() -
2225 base::TimeDelta::FromMicroseconds(1));
2226 task_runner().RunUntilTime(now_src()->NowTicks());
2227 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2229 // Take us out of a swap throttled state.
2230 scheduler_->DidSwapBuffersComplete();
2231 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
2232 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2233 EXPECT_TRUE(client_->needs_begin_frames());
2234 client_->Reset();
2236 // Verify that the deadline was rescheduled.
2237 task_runner().RunUntilTime(now_src()->NowTicks());
2238 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
2239 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2240 EXPECT_TRUE(client_->needs_begin_frames());
2241 client_->Reset();
2244 TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooEarly) {
2245 scheduler_settings_.use_external_begin_frame_source = true;
2246 SetUpScheduler(true);
2248 scheduler_->SetNeedsCommit();
2249 EXPECT_TRUE(client_->needs_begin_frames());
2250 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2252 client_->Reset();
2253 EXPECT_SCOPED(AdvanceFrame());
2254 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2255 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2256 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2258 client_->Reset();
2259 scheduler_->NotifyBeginMainFrameStarted();
2261 client_->Reset();
2262 BeginFrameArgs retro_frame_args = SendNextBeginFrame();
2263 // This BeginFrame is queued up as a retro frame.
2264 EXPECT_NO_ACTION(client_);
2265 // The previous deadline is still pending.
2266 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2268 client_->Reset();
2269 // This main frame activating should schedule the (previous) deadline to
2270 // trigger immediately.
2271 scheduler_->NotifyReadyToCommit();
2272 scheduler_->NotifyReadyToActivate();
2273 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2);
2274 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2);
2276 client_->Reset();
2277 // The deadline task should trigger causing a draw.
2278 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2279 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2280 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2281 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2283 // Keep animating.
2284 client_->Reset();
2285 scheduler_->SetNeedsAnimate();
2286 scheduler_->SetNeedsRedraw();
2287 EXPECT_NO_ACTION(client_);
2289 // Let's advance to the retro frame's deadline.
2290 now_src()->Advance(retro_frame_args.deadline - now_src()->NowTicks());
2292 // The retro frame hasn't expired yet.
2293 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
2294 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2295 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2296 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2298 // This is an immediate deadline case.
2299 client_->Reset();
2300 task_runner().RunPendingTasks();
2301 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2302 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
2305 TEST_F(SchedulerTest, RetroFrameExpiresOnTime) {
2306 scheduler_settings_.use_external_begin_frame_source = true;
2307 SetUpScheduler(true);
2309 scheduler_->SetNeedsCommit();
2310 EXPECT_TRUE(client_->needs_begin_frames());
2311 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2313 client_->Reset();
2314 EXPECT_SCOPED(AdvanceFrame());
2315 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2316 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2317 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2319 client_->Reset();
2320 scheduler_->NotifyBeginMainFrameStarted();
2322 client_->Reset();
2323 BeginFrameArgs retro_frame_args = SendNextBeginFrame();
2324 // This BeginFrame is queued up as a retro frame.
2325 EXPECT_NO_ACTION(client_);
2326 // The previous deadline is still pending.
2327 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2329 client_->Reset();
2330 // This main frame activating should schedule the (previous) deadline to
2331 // trigger immediately.
2332 scheduler_->NotifyReadyToCommit();
2333 scheduler_->NotifyReadyToActivate();
2334 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2);
2335 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2);
2337 client_->Reset();
2338 // The deadline task should trigger causing a draw.
2339 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2340 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2341 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2342 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2344 // Keep animating.
2345 client_->Reset();
2346 scheduler_->SetNeedsAnimate();
2347 scheduler_->SetNeedsRedraw();
2348 EXPECT_NO_ACTION(client_);
2350 // Let's advance sufficiently past the retro frame's deadline.
2351 now_src()->Advance(retro_frame_args.deadline - now_src()->NowTicks() +
2352 base::TimeDelta::FromMicroseconds(1));
2354 // The retro frame should've expired.
2355 EXPECT_NO_ACTION(client_);
2358 TEST_F(SchedulerTest, MissedFrameDoesNotExpireTooEarly) {
2359 scheduler_settings_.use_external_begin_frame_source = true;
2360 SetUpScheduler(true);
2362 scheduler_->SetNeedsCommit();
2363 EXPECT_TRUE(client_->needs_begin_frames());
2364 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2366 BeginFrameArgs missed_frame_args =
2367 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2368 missed_frame_args.type = BeginFrameArgs::MISSED;
2370 // Advance to the deadline.
2371 now_src()->Advance(missed_frame_args.deadline - now_src()->NowTicks());
2373 // Missed frame is handled because it's on time.
2374 client_->Reset();
2375 fake_external_begin_frame_source_->TestOnBeginFrame(missed_frame_args);
2376 EXPECT_TRUE(
2377 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false)));
2378 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2379 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2380 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2383 TEST_F(SchedulerTest, MissedFrameExpiresOnTime) {
2384 scheduler_settings_.use_external_begin_frame_source = true;
2385 SetUpScheduler(true);
2387 scheduler_->SetNeedsCommit();
2388 EXPECT_TRUE(client_->needs_begin_frames());
2389 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2391 BeginFrameArgs missed_frame_args =
2392 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2393 missed_frame_args.type = BeginFrameArgs::MISSED;
2395 // Advance sufficiently past the deadline.
2396 now_src()->Advance(missed_frame_args.deadline - now_src()->NowTicks() +
2397 base::TimeDelta::FromMicroseconds(1));
2399 // Missed frame is dropped because it's too late.
2400 client_->Reset();
2401 fake_external_begin_frame_source_->TestOnBeginFrame(missed_frame_args);
2402 EXPECT_FALSE(
2403 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false)));
2404 EXPECT_NO_ACTION(client_);
2405 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2408 void SchedulerTest::BeginFramesNotFromClient(
2409 bool use_external_begin_frame_source,
2410 bool throttle_frame_production) {
2411 scheduler_settings_.use_external_begin_frame_source =
2412 use_external_begin_frame_source;
2413 scheduler_settings_.throttle_frame_production = throttle_frame_production;
2414 SetUpScheduler(true);
2416 // SetNeedsCommit should begin the frame on the next BeginImplFrame
2417 // without calling SetNeedsBeginFrame.
2418 scheduler_->SetNeedsCommit();
2419 EXPECT_NO_ACTION(client_);
2420 client_->Reset();
2422 // When the client-driven BeginFrame are disabled, the scheduler posts it's
2423 // own BeginFrame tasks.
2424 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2425 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2426 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2427 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2428 client_->Reset();
2430 // If we don't swap on the deadline, we wait for the next BeginFrame.
2431 task_runner().RunPendingTasks(); // Run posted deadline.
2432 EXPECT_NO_ACTION(client_);
2433 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2434 client_->Reset();
2436 // NotifyReadyToCommit should trigger the commit.
2437 scheduler_->NotifyBeginMainFrameStarted();
2438 scheduler_->NotifyReadyToCommit();
2439 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2440 client_->Reset();
2442 // NotifyReadyToActivate should trigger the activation.
2443 scheduler_->NotifyReadyToActivate();
2444 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2445 client_->Reset();
2447 // BeginImplFrame should prepare the draw.
2448 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2449 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2450 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2451 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2452 client_->Reset();
2454 // BeginImplFrame deadline should draw.
2455 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2456 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2457 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2458 client_->Reset();
2460 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2461 // to avoid excessive toggles.
2462 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2463 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
2464 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2465 client_->Reset();
2467 // Make sure SetNeedsBeginFrame isn't called on the client
2468 // when the BeginFrame is no longer needed.
2469 task_runner().RunPendingTasks(); // Run posted deadline.
2470 EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_);
2471 client_->Reset();
2474 TEST_F(SchedulerTest, SyntheticBeginFrames) {
2475 bool use_external_begin_frame_source = false;
2476 bool throttle_frame_production = true;
2477 BeginFramesNotFromClient(use_external_begin_frame_source,
2478 throttle_frame_production);
2481 TEST_F(SchedulerTest, VSyncThrottlingDisabled) {
2482 bool use_external_begin_frame_source = true;
2483 bool throttle_frame_production = false;
2484 BeginFramesNotFromClient(use_external_begin_frame_source,
2485 throttle_frame_production);
2488 TEST_F(SchedulerTest, SyntheticBeginFrames_And_VSyncThrottlingDisabled) {
2489 bool use_external_begin_frame_source = false;
2490 bool throttle_frame_production = false;
2491 BeginFramesNotFromClient(use_external_begin_frame_source,
2492 throttle_frame_production);
2495 void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
2496 bool use_external_begin_frame_source,
2497 bool throttle_frame_production) {
2498 scheduler_settings_.use_external_begin_frame_source =
2499 use_external_begin_frame_source;
2500 scheduler_settings_.throttle_frame_production = throttle_frame_production;
2501 SetUpScheduler(true);
2503 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
2505 // To test swap ack throttling, this test disables automatic swap acks.
2506 scheduler_->SetMaxSwapsPending(1);
2507 client_->SetAutomaticSwapAck(false);
2509 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2510 client_->Reset();
2511 scheduler_->SetNeedsCommit();
2512 EXPECT_NO_ACTION(client_);
2513 client_->Reset();
2515 // Trigger the first BeginImplFrame and BeginMainFrame
2516 EXPECT_SCOPED(AdvanceFrame());
2517 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2518 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2519 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2520 client_->Reset();
2522 // NotifyReadyToCommit should trigger the pending commit.
2523 scheduler_->NotifyBeginMainFrameStarted();
2524 scheduler_->NotifyReadyToCommit();
2525 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2526 client_->Reset();
2528 // NotifyReadyToActivate should trigger the activation and draw.
2529 scheduler_->NotifyReadyToActivate();
2530 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2531 client_->Reset();
2533 // Swapping will put us into a swap throttled state.
2534 // Run posted deadline.
2535 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2536 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2537 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2538 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2539 client_->Reset();
2541 // While swap throttled, BeginFrames should trigger BeginImplFrames,
2542 // but not a BeginMainFrame or draw.
2543 scheduler_->SetNeedsCommit();
2544 scheduler_->SetNeedsRedraw();
2545 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
2546 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2547 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2548 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2549 client_->Reset();
2551 // Let time pass sufficiently beyond the regular deadline but not beyond the
2552 // late deadline.
2553 now_src()->Advance(BeginFrameArgs::DefaultInterval() -
2554 base::TimeDelta::FromMicroseconds(1));
2555 task_runner().RunUntilTime(now_src()->NowTicks());
2556 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2558 // Take us out of a swap throttled state.
2559 scheduler_->DidSwapBuffersComplete();
2560 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
2561 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2562 client_->Reset();
2564 // Verify that the deadline was rescheduled.
2565 // We can't use RunUntilTime(now) here because the next frame is also
2566 // scheduled if throttle_frame_production = false.
2567 base::TimeTicks before_deadline = now_src()->NowTicks();
2568 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2569 base::TimeTicks after_deadline = now_src()->NowTicks();
2570 EXPECT_EQ(after_deadline, before_deadline);
2571 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2572 client_->Reset();
2575 TEST_F(SchedulerTest, SyntheticBeginFrames_SwapThrottled) {
2576 bool use_external_begin_frame_source = false;
2577 bool throttle_frame_production = true;
2578 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
2579 throttle_frame_production);
2582 TEST_F(SchedulerTest, VSyncThrottlingDisabled_SwapThrottled) {
2583 bool use_external_begin_frame_source = true;
2584 bool throttle_frame_production = false;
2585 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
2586 throttle_frame_production);
2589 TEST_F(SchedulerTest,
2590 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled) {
2591 bool use_external_begin_frame_source = false;
2592 bool throttle_frame_production = false;
2593 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
2594 throttle_frame_production);
2597 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized) {
2598 scheduler_settings_.use_external_begin_frame_source = true;
2599 SetUpScheduler(false);
2601 scheduler_->SetCanStart();
2602 scheduler_->SetVisible(true);
2603 scheduler_->SetCanDraw(true);
2605 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
2606 client_->Reset();
2607 scheduler_->DidCreateAndInitializeOutputSurface();
2608 EXPECT_NO_ACTION(client_);
2610 scheduler_->DidLoseOutputSurface();
2611 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
2614 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) {
2615 scheduler_settings_.use_external_begin_frame_source = true;
2616 SetUpScheduler(true);
2618 // SetNeedsCommit should begin the frame.
2619 scheduler_->SetNeedsCommit();
2620 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2622 client_->Reset();
2623 EXPECT_SCOPED(AdvanceFrame());
2624 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2625 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2626 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2628 client_->Reset();
2629 scheduler_->DidLoseOutputSurface();
2630 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2631 EXPECT_NO_ACTION(client_);
2633 client_->Reset();
2634 scheduler_->NotifyBeginMainFrameStarted();
2635 scheduler_->NotifyReadyToCommit();
2636 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2);
2637 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2);
2639 client_->Reset();
2640 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2641 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2642 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2643 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2646 TEST_F(SchedulerTest,
2647 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) {
2648 scheduler_settings_.use_external_begin_frame_source = true;
2649 SetUpScheduler(true);
2651 // SetNeedsCommit should begin the frame.
2652 scheduler_->SetNeedsCommit();
2653 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2655 client_->Reset();
2656 EXPECT_SCOPED(AdvanceFrame());
2657 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2658 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2659 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2661 client_->Reset();
2662 scheduler_->DidLoseOutputSurface();
2663 // Do nothing when impl frame is in deadine pending state.
2664 EXPECT_NO_ACTION(client_);
2666 client_->Reset();
2667 // Run posted deadline.
2668 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2669 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2670 // OnBeginImplFrameDeadline didn't schedule output surface creation because
2671 // main frame is not yet completed.
2672 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
2673 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2674 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2676 // BeginImplFrame is not started.
2677 client_->Reset();
2678 task_runner().RunUntilTime(now_src()->NowTicks() +
2679 base::TimeDelta::FromMilliseconds(10));
2680 EXPECT_NO_ACTION(client_);
2681 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2683 client_->Reset();
2684 scheduler_->NotifyBeginMainFrameStarted();
2685 scheduler_->NotifyReadyToCommit();
2686 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 3);
2687 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 3);
2688 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 2, 3);
2691 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) {
2692 scheduler_settings_.use_external_begin_frame_source = true;
2693 SetUpScheduler(true);
2695 // SetNeedsCommit should begin the frame.
2696 scheduler_->SetNeedsCommit();
2697 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2699 client_->Reset();
2700 EXPECT_SCOPED(AdvanceFrame());
2701 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2702 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2703 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2705 client_->Reset();
2706 scheduler_->NotifyBeginMainFrameStarted();
2707 scheduler_->NotifyReadyToCommit();
2708 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2710 client_->Reset();
2711 scheduler_->DidLoseOutputSurface();
2712 // Sync tree should be forced to activate.
2713 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2715 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2716 client_->Reset();
2717 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2718 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2719 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2720 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2723 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles) {
2724 scheduler_settings_.use_external_begin_frame_source = true;
2725 SetUpScheduler(true);
2727 scheduler_->SetNeedsPrepareTiles();
2728 scheduler_->SetNeedsRedraw();
2729 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2731 client_->Reset();
2732 EXPECT_SCOPED(AdvanceFrame());
2733 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2734 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2735 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2737 client_->Reset();
2738 scheduler_->DidLoseOutputSurface();
2739 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2740 EXPECT_NO_ACTION(client_);
2742 client_->Reset();
2743 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2744 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 0, 4);
2745 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 4);
2746 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 2, 4);
2747 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 3, 4);
2750 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) {
2751 scheduler_settings_.use_external_begin_frame_source = true;
2752 SetUpScheduler(true);
2754 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2755 scheduler_->SetNeedsCommit();
2756 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2758 // Create a BeginFrame with a long deadline to avoid race conditions.
2759 // This is the first BeginFrame, which will be handled immediately.
2760 client_->Reset();
2761 BeginFrameArgs args =
2762 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2763 args.deadline += base::TimeDelta::FromHours(1);
2764 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2765 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2766 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2767 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2768 EXPECT_TRUE(client_->needs_begin_frames());
2770 // Queue BeginFrames while we are still handling the previous BeginFrame.
2771 args.frame_time += base::TimeDelta::FromSeconds(1);
2772 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2773 args.frame_time += base::TimeDelta::FromSeconds(1);
2774 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2776 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2777 client_->Reset();
2778 task_runner().RunPendingTasks(); // Run posted deadline.
2779 EXPECT_NO_ACTION(client_);
2780 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2781 EXPECT_TRUE(client_->needs_begin_frames());
2783 // NotifyReadyToCommit should trigger the commit.
2784 client_->Reset();
2785 scheduler_->NotifyBeginMainFrameStarted();
2786 scheduler_->NotifyReadyToCommit();
2787 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2788 EXPECT_TRUE(client_->needs_begin_frames());
2790 // NotifyReadyToActivate should trigger the activation.
2791 client_->Reset();
2792 scheduler_->NotifyReadyToActivate();
2793 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2794 EXPECT_TRUE(client_->needs_begin_frames());
2796 client_->Reset();
2797 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty());
2798 scheduler_->DidLoseOutputSurface();
2799 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2800 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2801 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2802 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty());
2804 // Posted BeginRetroFrame is aborted.
2805 client_->Reset();
2806 task_runner().RunPendingTasks();
2807 EXPECT_NO_ACTION(client_);
2810 TEST_F(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) {
2811 scheduler_settings_.use_external_begin_frame_source = true;
2812 SetUpScheduler(true);
2814 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2815 scheduler_->SetNeedsCommit();
2816 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2818 // Create a BeginFrame with a long deadline to avoid race conditions.
2819 // This is the first BeginFrame, which will be handled immediately.
2820 client_->Reset();
2821 BeginFrameArgs args =
2822 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2823 args.deadline += base::TimeDelta::FromHours(1);
2824 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2825 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2826 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2827 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2828 EXPECT_TRUE(client_->needs_begin_frames());
2830 // Queue BeginFrames while we are still handling the previous BeginFrame.
2831 args.frame_time += base::TimeDelta::FromSeconds(1);
2832 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2833 args.frame_time += base::TimeDelta::FromSeconds(1);
2834 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2836 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2837 client_->Reset();
2838 task_runner().RunPendingTasks(); // Run posted deadline.
2839 EXPECT_NO_ACTION(client_);
2840 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2841 EXPECT_TRUE(client_->needs_begin_frames());
2843 // NotifyReadyToCommit should trigger the commit.
2844 client_->Reset();
2845 scheduler_->NotifyBeginMainFrameStarted();
2846 scheduler_->NotifyReadyToCommit();
2847 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2848 EXPECT_TRUE(client_->needs_begin_frames());
2850 // NotifyReadyToActivate should trigger the activation.
2851 client_->Reset();
2852 scheduler_->NotifyReadyToActivate();
2853 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2854 EXPECT_TRUE(client_->needs_begin_frames());
2856 // BeginImplFrame should prepare the draw.
2857 client_->Reset();
2858 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2859 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2860 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2861 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2862 EXPECT_TRUE(client_->needs_begin_frames());
2864 client_->Reset();
2865 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty());
2866 scheduler_->DidLoseOutputSurface();
2867 EXPECT_NO_ACTION(client_);
2868 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty());
2870 // BeginImplFrame deadline should abort drawing.
2871 client_->Reset();
2872 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2873 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2874 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2875 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2876 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2877 EXPECT_FALSE(client_->needs_begin_frames());
2879 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
2880 client_->Reset();
2881 task_runner().RunPendingTasks();
2882 EXPECT_NO_ACTION(client_);
2885 TEST_F(SchedulerTest, DidLoseOutputSurfaceWithSyntheticBeginFrameSource) {
2886 SetUpScheduler(true);
2888 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2889 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2890 scheduler_->SetNeedsCommit();
2891 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2893 client_->Reset();
2894 AdvanceFrame();
2895 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2896 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2897 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2898 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2900 // NotifyReadyToCommit should trigger the commit.
2901 client_->Reset();
2902 scheduler_->NotifyBeginMainFrameStarted();
2903 scheduler_->NotifyReadyToCommit();
2904 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2905 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2907 // NotifyReadyToActivate should trigger the activation.
2908 client_->Reset();
2909 scheduler_->NotifyReadyToActivate();
2910 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2911 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2913 client_->Reset();
2914 scheduler_->DidLoseOutputSurface();
2915 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2916 EXPECT_NO_ACTION(client_);
2917 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2919 client_->Reset();
2920 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2921 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 2);
2922 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2923 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2926 TEST_F(SchedulerTest, DidLoseOutputSurfaceWhenIdle) {
2927 scheduler_settings_.use_external_begin_frame_source = true;
2928 SetUpScheduler(true);
2930 // SetNeedsCommit should begin the frame.
2931 scheduler_->SetNeedsCommit();
2932 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2934 client_->Reset();
2935 EXPECT_SCOPED(AdvanceFrame());
2936 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2937 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2938 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2940 client_->Reset();
2941 scheduler_->NotifyBeginMainFrameStarted();
2942 scheduler_->NotifyReadyToCommit();
2943 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2945 client_->Reset();
2946 scheduler_->NotifyReadyToActivate();
2947 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2949 client_->Reset();
2950 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2951 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2952 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2954 // Idle time between BeginFrames.
2955 client_->Reset();
2956 scheduler_->DidLoseOutputSurface();
2957 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2958 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2959 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2962 TEST_F(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) {
2963 scheduler_settings_.use_external_begin_frame_source = true;
2964 SetUpScheduler(true);
2966 // SetNeedsCommit should begin the frame.
2967 scheduler_->SetNeedsCommit();
2968 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2970 client_->Reset();
2971 EXPECT_SCOPED(AdvanceFrame());
2972 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2973 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2974 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2976 client_->Reset();
2977 scheduler_->NotifyBeginMainFrameStarted();
2978 scheduler_->NotifyReadyToCommit();
2979 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2980 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2982 client_->Reset();
2983 scheduler_->SetVisible(false);
2984 task_runner().RunPendingTasks(); // Run posted deadline.
2986 // Sync tree should be forced to activate.
2987 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 3);
2988 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2989 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2992 // Tests to ensure frame sources can be successfully changed while drawing.
2993 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottled) {
2994 scheduler_settings_.use_external_begin_frame_source = true;
2995 SetUpScheduler(true);
2997 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2998 scheduler_->SetNeedsRedraw();
2999 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3000 client_->Reset();
3002 EXPECT_SCOPED(AdvanceFrame());
3003 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3004 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
3005 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3006 EXPECT_TRUE(client_->needs_begin_frames());
3007 client_->Reset();
3008 task_runner().RunPendingTasks(); // Run posted deadline.
3009 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
3010 scheduler_->SetNeedsRedraw();
3012 // Switch to an unthrottled frame source.
3013 scheduler_->SetThrottleFrameProduction(false);
3014 client_->Reset();
3016 // Unthrottled frame source will immediately begin a new frame.
3017 task_runner().RunPendingTasks(); // Run posted BeginFrame.
3018 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3019 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
3020 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3021 client_->Reset();
3023 // If we don't swap on the deadline, we wait for the next BeginFrame.
3024 task_runner().RunPendingTasks(); // Run posted deadline.
3025 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
3026 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3027 client_->Reset();
3030 // Tests to ensure frame sources can be successfully changed while a frame
3031 // deadline is pending.
3032 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottledBeforeDeadline) {
3033 scheduler_settings_.use_external_begin_frame_source = true;
3034 SetUpScheduler(true);
3036 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
3037 scheduler_->SetNeedsRedraw();
3038 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3039 client_->Reset();
3041 EXPECT_SCOPED(AdvanceFrame());
3042 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3043 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
3045 // Switch to an unthrottled frame source before the frame deadline is hit.
3046 scheduler_->SetThrottleFrameProduction(false);
3047 client_->Reset();
3049 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3050 EXPECT_TRUE(client_->needs_begin_frames());
3051 client_->Reset();
3053 task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame.
3054 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
3055 // Unthrottled frame source will immediately begin a new frame.
3056 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 2);
3057 scheduler_->SetNeedsRedraw();
3058 client_->Reset();
3060 task_runner().RunPendingTasks(); // Run posted deadline.
3061 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
3062 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
3063 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3064 client_->Reset();
3067 // Tests to ensure that the active frame source can successfully be changed from
3068 // unthrottled to throttled.
3069 TEST_F(SchedulerTest, SwitchFrameSourceToThrottled) {
3070 scheduler_settings_.throttle_frame_production = false;
3071 scheduler_settings_.use_external_begin_frame_source = true;
3072 SetUpScheduler(true);
3074 scheduler_->SetNeedsRedraw();
3075 EXPECT_NO_ACTION(client_);
3076 client_->Reset();
3078 task_runner().RunPendingTasks(); // Run posted BeginFrame.
3079 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3080 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
3081 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3082 client_->Reset();
3084 task_runner().RunPendingTasks(); // Run posted deadline.
3085 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
3086 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3087 client_->Reset();
3089 // Switch to a throttled frame source.
3090 scheduler_->SetThrottleFrameProduction(true);
3091 client_->Reset();
3093 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
3094 scheduler_->SetNeedsRedraw();
3095 task_runner().RunPendingTasks();
3096 EXPECT_NO_ACTION(client_);
3097 client_->Reset();
3099 EXPECT_SCOPED(AdvanceFrame());
3100 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3101 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
3102 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3103 EXPECT_TRUE(client_->needs_begin_frames());
3104 client_->Reset();
3105 task_runner().RunPendingTasks(); // Run posted deadline.
3106 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
3109 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
3110 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon) {
3111 scheduler_settings_.use_external_begin_frame_source = true;
3112 SetUpScheduler(true);
3114 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
3115 scheduler_->SetNeedsCommit();
3116 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3117 client_->Reset();
3119 // Trigger a frame draw.
3120 EXPECT_SCOPED(AdvanceFrame());
3121 scheduler_->NotifyBeginMainFrameStarted();
3122 scheduler_->NotifyReadyToCommit();
3123 scheduler_->NotifyReadyToActivate();
3124 task_runner().RunPendingTasks();
3125 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6);
3126 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 6);
3127 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 6);
3128 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 3, 6);
3129 EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 6);
3130 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 5, 6);
3131 client_->Reset();
3133 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
3134 // and send a SendBeginMainFrameNotExpectedSoon.
3135 EXPECT_SCOPED(AdvanceFrame());
3136 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
3137 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3138 client_->Reset();
3140 task_runner().RunPendingTasks(); // Run posted deadline.
3141 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
3142 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
3143 client_->Reset();
3146 TEST_F(SchedulerTest, SynchronousCompositorAnimation) {
3147 scheduler_settings_.using_synchronous_renderer_compositor = true;
3148 scheduler_settings_.use_external_begin_frame_source = true;
3149 SetUpScheduler(true);
3151 scheduler_->SetNeedsAnimate();
3152 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3153 client_->Reset();
3155 // Next vsync.
3156 AdvanceFrame();
3157 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3158 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3159 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3160 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3161 client_->Reset();
3163 // Continue with animation.
3164 scheduler_->SetNeedsAnimate();
3165 EXPECT_NO_ACTION(client_);
3167 // Android onDraw.
3168 scheduler_->SetNeedsRedraw();
3169 scheduler_->OnDrawForOutputSurface();
3170 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
3171 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3172 client_->Reset();
3174 // Next vsync.
3175 AdvanceFrame();
3176 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3177 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3178 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3179 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3180 client_->Reset();
3182 // Android onDraw.
3183 scheduler_->SetNeedsRedraw();
3184 scheduler_->OnDrawForOutputSurface();
3185 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
3186 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3187 client_->Reset();
3189 // Idle on next vsync.
3190 AdvanceFrame();
3191 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3192 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
3193 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
3194 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3195 client_->Reset();
3198 TEST_F(SchedulerTest, SynchronousCompositorOnDrawDuringIdle) {
3199 scheduler_settings_.using_synchronous_renderer_compositor = true;
3200 scheduler_settings_.use_external_begin_frame_source = true;
3201 SetUpScheduler(true);
3203 scheduler_->SetNeedsRedraw();
3204 scheduler_->OnDrawForOutputSurface();
3205 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3);
3206 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3207 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3);
3208 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3209 client_->Reset();
3211 // Idle on next vsync.
3212 AdvanceFrame();
3213 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3214 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
3215 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
3216 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3217 client_->Reset();
3220 TEST_F(SchedulerTest, SynchronousCompositorCommit) {
3221 scheduler_settings_.using_synchronous_renderer_compositor = true;
3222 scheduler_settings_.use_external_begin_frame_source = true;
3223 SetUpScheduler(true);
3225 scheduler_->SetNeedsCommit();
3226 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3227 client_->Reset();
3229 // Next vsync.
3230 AdvanceFrame();
3231 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3232 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
3233 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3234 client_->Reset();
3236 scheduler_->NotifyBeginMainFrameStarted();
3237 EXPECT_NO_ACTION(client_);
3239 // Next vsync.
3240 AdvanceFrame();
3241 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
3242 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3243 client_->Reset();
3245 scheduler_->NotifyReadyToCommit();
3246 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
3247 client_->Reset();
3249 scheduler_->NotifyReadyToActivate();
3250 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
3251 client_->Reset();
3253 // Next vsync.
3254 AdvanceFrame();
3255 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3256 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3257 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3258 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3259 client_->Reset();
3261 // Android onDraw.
3262 scheduler_->SetNeedsRedraw();
3263 scheduler_->OnDrawForOutputSurface();
3264 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
3265 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3266 client_->Reset();
3268 // Idle on next vsync.
3269 AdvanceFrame();
3270 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3271 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
3272 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
3273 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3274 client_->Reset();
3277 TEST_F(SchedulerTest, SynchronousCompositorDoubleCommitWithoutDraw) {
3278 scheduler_settings_.using_synchronous_renderer_compositor = true;
3279 scheduler_settings_.use_external_begin_frame_source = true;
3280 SetUpScheduler(true);
3282 scheduler_->SetNeedsCommit();
3283 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3284 client_->Reset();
3286 // Next vsync.
3287 AdvanceFrame();
3288 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3289 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
3290 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3291 client_->Reset();
3293 scheduler_->NotifyBeginMainFrameStarted();
3294 EXPECT_NO_ACTION(client_);
3296 scheduler_->NotifyReadyToCommit();
3297 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
3298 client_->Reset();
3300 scheduler_->NotifyReadyToActivate();
3301 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
3302 client_->Reset();
3304 // Ask for another commit.
3305 scheduler_->SetNeedsCommit();
3307 AdvanceFrame();
3308 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4);
3309 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4);
3310 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4);
3311 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 3, 4);
3312 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3313 client_->Reset();
3315 scheduler_->NotifyBeginMainFrameStarted();
3316 EXPECT_NO_ACTION(client_);
3318 // Allow new commit even though previous commit hasn't been drawn.
3319 scheduler_->NotifyReadyToCommit();
3320 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
3321 client_->Reset();
3324 class SchedulerClientSetNeedsPrepareTilesOnDraw : public FakeSchedulerClient {
3325 public:
3326 SchedulerClientSetNeedsPrepareTilesOnDraw() : FakeSchedulerClient() {}
3328 protected:
3329 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
3330 scheduler_->SetNeedsPrepareTiles();
3331 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
3335 TEST_F(SchedulerTest, SynchronousCompositorPrepareTilesOnDraw) {
3336 scheduler_settings_.using_synchronous_renderer_compositor = true;
3337 scheduler_settings_.use_external_begin_frame_source = true;
3339 scoped_ptr<FakeSchedulerClient> client =
3340 make_scoped_ptr(new SchedulerClientSetNeedsPrepareTilesOnDraw);
3341 SetUpScheduler(client.Pass(), true);
3343 scheduler_->SetNeedsRedraw();
3344 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3345 client_->Reset();
3347 // Next vsync.
3348 EXPECT_SCOPED(AdvanceFrame());
3349 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3350 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3351 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3352 client_->Reset();
3354 // Android onDraw.
3355 scheduler_->SetNeedsRedraw();
3356 scheduler_->OnDrawForOutputSurface();
3357 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
3358 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 1, 2);
3359 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3360 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3361 client_->Reset();
3363 // Android onDraw.
3364 scheduler_->SetNeedsRedraw();
3365 scheduler_->OnDrawForOutputSurface();
3366 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
3367 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 1, 2);
3368 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3369 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3370 client_->Reset();
3372 // Next vsync.
3373 EXPECT_SCOPED(AdvanceFrame());
3374 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3375 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3376 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
3377 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
3378 EXPECT_FALSE(client_->needs_begin_frames());
3379 client_->Reset();
3382 TEST_F(SchedulerTest, SynchronousCompositorSendBeginMainFrameWhileIdle) {
3383 scheduler_settings_.using_synchronous_renderer_compositor = true;
3384 scheduler_settings_.use_external_begin_frame_source = true;
3386 SetUpScheduler(true);
3388 scheduler_->SetNeedsRedraw();
3389 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3390 client_->Reset();
3392 // Next vsync.
3393 EXPECT_SCOPED(AdvanceFrame());
3394 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3395 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3396 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3397 client_->Reset();
3399 // Android onDraw.
3400 scheduler_->SetNeedsRedraw();
3401 scheduler_->OnDrawForOutputSurface();
3402 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
3403 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3404 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3405 client_->Reset();
3407 // Simulate SetNeedsCommit due to input event.
3408 scheduler_->SetNeedsCommit();
3409 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
3410 client_->Reset();
3412 scheduler_->NotifyBeginMainFrameStarted();
3413 scheduler_->NotifyReadyToCommit();
3414 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
3415 client_->Reset();
3417 scheduler_->NotifyReadyToActivate();
3418 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
3419 client_->Reset();
3421 // Next vsync.
3422 EXPECT_SCOPED(AdvanceFrame());
3423 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3424 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3425 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3426 client_->Reset();
3428 // Android onDraw.
3429 scheduler_->SetNeedsRedraw();
3430 scheduler_->OnDrawForOutputSurface();
3431 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
3432 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3433 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3434 client_->Reset();
3436 // Simulate SetNeedsCommit due to input event.
3437 scheduler_->SetNeedsCommit();
3438 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
3439 client_->Reset();
3442 TEST_F(SchedulerTest, AuthoritativeVSyncInterval) {
3443 SetUpScheduler(true);
3444 base::TimeDelta initial_interval = scheduler_->BeginImplFrameInterval();
3445 base::TimeDelta authoritative_interval =
3446 base::TimeDelta::FromMilliseconds(33);
3448 scheduler_->SetNeedsCommit();
3449 EXPECT_SCOPED(AdvanceFrame());
3451 EXPECT_EQ(initial_interval, scheduler_->BeginImplFrameInterval());
3453 scheduler_->NotifyBeginMainFrameStarted();
3454 scheduler_->NotifyReadyToCommit();
3455 scheduler_->NotifyReadyToActivate();
3456 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
3458 scheduler_->SetAuthoritativeVSyncInterval(authoritative_interval);
3460 EXPECT_SCOPED(AdvanceFrame());
3462 // At the next BeginFrame, authoritative interval is used instead of previous
3463 // interval.
3464 EXPECT_NE(initial_interval, scheduler_->BeginImplFrameInterval());
3465 EXPECT_EQ(authoritative_interval, scheduler_->BeginImplFrameInterval());
3468 TEST_F(SchedulerTest, ImplLatencyTakesPriority) {
3469 SetUpScheduler(true);
3470 scheduler_->SetImplLatencyTakesPriority(true);
3471 EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority());
3473 scheduler_->SetImplLatencyTakesPriority(false);
3474 EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority());
3477 TEST_F(SchedulerTest, BeginFrameArgs_OnCriticalPath) {
3478 scheduler_settings_.use_external_begin_frame_source = true;
3479 SetUpScheduler(true);
3481 scheduler_->SetImplLatencyTakesPriority(false);
3482 scheduler_->SetChildrenNeedBeginFrames(true);
3484 EXPECT_SCOPED(AdvanceFrame());
3485 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
3486 EXPECT_TRUE(client_->begin_frame_args_sent_to_children().on_critical_path);
3489 TEST_F(SchedulerTest, BeginFrameArgs_NotOnCriticalPath) {
3490 scheduler_settings_.use_external_begin_frame_source = true;
3491 SetUpScheduler(true);
3493 scheduler_->SetImplLatencyTakesPriority(true);
3494 scheduler_->SetChildrenNeedBeginFrames(true);
3496 EXPECT_SCOPED(AdvanceFrame());
3497 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
3498 EXPECT_FALSE(client_->begin_frame_args_sent_to_children().on_critical_path);
3501 } // namespace
3502 } // namespace cc