Revert "Reland c91b178b07b0d - Delete dead signin code (SigninGlobalError)"
[chromium-blink-merge.git] / cc / scheduler / scheduler_unittest.cc
blob4bdd4f6c4ca25a23d75e16cf795e92375e3fcc7f
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_->SetNeedsBeginMainFrame();
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();
315 scheduler_->NotifyReadyToDraw();
317 EXPECT_FALSE(scheduler_->CommitPending());
319 if (scheduler_settings_.using_synchronous_renderer_compositor) {
320 scheduler_->SetNeedsRedraw();
321 scheduler_->OnDrawForOutputSurface();
322 } else {
323 // Run the posted deadline task.
324 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
325 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
328 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
331 client_->Reset();
334 SCOPED_TRACE(
335 "Run second frame so Scheduler calls SetNeedsBeginFrame(false).");
336 AdvanceFrame();
338 if (!scheduler_settings_.using_synchronous_renderer_compositor) {
339 // Run the posted deadline task.
340 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
341 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
344 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
347 EXPECT_FALSE(client_->needs_begin_frames());
348 client_->Reset();
351 // As this function contains EXPECT macros, to allow debugging it should be
352 // called inside EXPECT_SCOPED like so;
353 // EXPECT_SCOPED(client.AdvanceFrame());
354 void AdvanceFrame() {
355 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
356 "FakeSchedulerClient::AdvanceFrame");
357 // Consume any previous deadline first, if no deadline is currently
358 // pending, ImplFrameDeadlinePending will return false straight away and we
359 // will run no tasks.
360 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
361 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
363 // Send the next BeginFrame message if using an external source, otherwise
364 // it will be already in the task queue.
365 if (scheduler_->settings().use_external_begin_frame_source &&
366 scheduler_->FrameProductionThrottled()) {
367 EXPECT_TRUE(client_->needs_begin_frames());
368 SendNextBeginFrame();
371 if (!scheduler_->settings().using_synchronous_renderer_compositor) {
372 // Then run tasks until new deadline is scheduled.
373 EXPECT_TRUE(task_runner_->RunTasksWhile(
374 client_->ImplFrameDeadlinePending(false)));
375 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
379 BeginFrameArgs SendNextBeginFrame() {
380 DCHECK(scheduler_->settings().use_external_begin_frame_source);
381 // Creep the time forward so that any BeginFrameArgs is not equal to the
382 // last one otherwise we violate the BeginFrameSource contract.
383 now_src_->Advance(BeginFrameArgs::DefaultInterval());
384 BeginFrameArgs args =
385 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
386 fake_external_begin_frame_source_->TestOnBeginFrame(args);
387 return args;
390 FakeExternalBeginFrameSource* fake_external_begin_frame_source() const {
391 return fake_external_begin_frame_source_.get();
394 void CheckMainFrameSkippedAfterLateCommit(bool expect_send_begin_main_frame);
395 void ImplFrameSkippedAfterLateSwapAck(bool swap_ack_before_deadline);
396 void ImplFrameIsNotSkippedAfterLateSwapAck();
397 void BeginFramesNotFromClient(bool use_external_begin_frame_source,
398 bool throttle_frame_production);
399 void BeginFramesNotFromClient_SwapThrottled(
400 bool use_external_begin_frame_source,
401 bool throttle_frame_production);
403 scoped_ptr<base::SimpleTestTickClock> now_src_;
404 scoped_refptr<OrderedSimpleTaskRunner> task_runner_;
405 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source_;
406 SchedulerSettings scheduler_settings_;
407 scoped_ptr<FakeSchedulerClient> client_;
408 scoped_ptr<TestScheduler> scheduler_;
409 FakeCompositorTimingHistory* fake_compositor_timing_history_;
412 TEST_F(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) {
413 scheduler_settings_.use_external_begin_frame_source = true;
414 SetUpScheduler(false);
415 scheduler_->SetCanStart();
416 scheduler_->SetVisible(true);
417 scheduler_->SetCanDraw(true);
419 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
420 client_->Reset();
421 scheduler_->DidCreateAndInitializeOutputSurface();
422 EXPECT_NO_ACTION(client_);
425 TEST_F(SchedulerTest, SendBeginFramesToChildren) {
426 scheduler_settings_.use_external_begin_frame_source = true;
427 SetUpScheduler(true);
429 EXPECT_FALSE(client_->begin_frame_is_sent_to_children());
430 scheduler_->SetNeedsBeginMainFrame();
431 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
432 EXPECT_TRUE(client_->needs_begin_frames());
434 scheduler_->SetChildrenNeedBeginFrames(true);
436 client_->Reset();
437 EXPECT_SCOPED(AdvanceFrame());
438 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
439 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
440 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
441 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
442 EXPECT_TRUE(client_->needs_begin_frames());
445 TEST_F(SchedulerTest, SendBeginFramesToChildrenWithoutCommit) {
446 scheduler_settings_.use_external_begin_frame_source = true;
447 SetUpScheduler(true);
449 EXPECT_FALSE(client_->needs_begin_frames());
450 scheduler_->SetChildrenNeedBeginFrames(true);
451 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
452 EXPECT_TRUE(client_->needs_begin_frames());
454 client_->Reset();
455 EXPECT_SCOPED(AdvanceFrame());
456 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
459 TEST_F(SchedulerTest, SendBeginFramesToChildrenDeadlineNotAdjusted) {
460 // Set up client with specified estimates.
461 scheduler_settings_.use_external_begin_frame_source = true;
462 SetUpScheduler(true);
464 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate(
465 base::TimeDelta::FromMilliseconds(2));
466 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate(
467 base::TimeDelta::FromMilliseconds(4));
468 fake_compositor_timing_history_->SetDrawDurationEstimate(
469 base::TimeDelta::FromMilliseconds(1));
471 EXPECT_FALSE(client_->needs_begin_frames());
472 scheduler_->SetChildrenNeedBeginFrames(true);
473 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
474 EXPECT_TRUE(client_->needs_begin_frames());
476 client_->Reset();
478 BeginFrameArgs frame_args =
479 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
480 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args);
482 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
483 EXPECT_EQ(client_->begin_frame_args_sent_to_children().deadline,
484 frame_args.deadline);
487 TEST_F(SchedulerTest, VideoNeedsBeginFrames) {
488 scheduler_settings_.use_external_begin_frame_source = true;
489 SetUpScheduler(true);
491 scheduler_->SetVideoNeedsBeginFrames(true);
492 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
493 EXPECT_TRUE(client_->needs_begin_frames());
495 client_->Reset();
496 EXPECT_SCOPED(AdvanceFrame());
497 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
498 // WillBeginImplFrame is responsible for sending BeginFrames to video.
499 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
501 client_->Reset();
502 EXPECT_SCOPED(AdvanceFrame());
503 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
504 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
506 client_->Reset();
507 scheduler_->SetVideoNeedsBeginFrames(false);
508 EXPECT_NO_ACTION(client_);
510 client_->Reset();
511 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
512 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
513 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
514 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
515 EXPECT_FALSE(client_->needs_begin_frames());
518 TEST_F(SchedulerTest, RequestCommit) {
519 scheduler_settings_.use_external_begin_frame_source = true;
520 SetUpScheduler(true);
522 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
523 scheduler_->SetNeedsBeginMainFrame();
524 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
525 client_->Reset();
527 EXPECT_SCOPED(AdvanceFrame());
528 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
529 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
530 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
531 EXPECT_TRUE(client_->needs_begin_frames());
532 client_->Reset();
534 // If we don't swap on the deadline, we wait for the next BeginFrame.
535 task_runner().RunPendingTasks(); // Run posted deadline.
536 EXPECT_NO_ACTION(client_);
537 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
538 EXPECT_TRUE(client_->needs_begin_frames());
539 client_->Reset();
541 // NotifyReadyToCommit should trigger the commit.
542 scheduler_->NotifyBeginMainFrameStarted();
543 scheduler_->NotifyReadyToCommit();
544 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
545 EXPECT_TRUE(client_->needs_begin_frames());
546 client_->Reset();
548 // NotifyReadyToActivate should trigger the activation.
549 scheduler_->NotifyReadyToActivate();
550 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
551 EXPECT_TRUE(client_->needs_begin_frames());
552 client_->Reset();
554 // BeginImplFrame should prepare the draw.
555 EXPECT_SCOPED(AdvanceFrame());
556 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
557 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
558 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
559 EXPECT_TRUE(client_->needs_begin_frames());
560 client_->Reset();
562 // BeginImplFrame deadline should draw.
563 task_runner().RunPendingTasks(); // Run posted deadline.
564 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
565 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
566 EXPECT_TRUE(client_->needs_begin_frames());
567 client_->Reset();
569 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
570 // to avoid excessive toggles.
571 EXPECT_SCOPED(AdvanceFrame());
572 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
573 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
574 client_->Reset();
576 task_runner().RunPendingTasks(); // Run posted deadline.
577 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
578 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
579 client_->Reset();
582 TEST_F(SchedulerTest, RequestCommitAfterSetDeferCommit) {
583 scheduler_settings_.use_external_begin_frame_source = true;
584 SetUpScheduler(true);
586 scheduler_->SetDeferCommits(true);
588 scheduler_->SetNeedsBeginMainFrame();
589 EXPECT_NO_ACTION(client_);
591 client_->Reset();
592 task_runner().RunPendingTasks();
593 // There are no pending tasks or actions.
594 EXPECT_NO_ACTION(client_);
595 EXPECT_FALSE(client_->needs_begin_frames());
597 client_->Reset();
598 scheduler_->SetDeferCommits(false);
599 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
601 // Start new BeginMainFrame after defer commit is off.
602 client_->Reset();
603 EXPECT_SCOPED(AdvanceFrame());
604 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
605 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
606 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
609 TEST_F(SchedulerTest, DeferCommitWithRedraw) {
610 scheduler_settings_.use_external_begin_frame_source = true;
611 SetUpScheduler(true);
613 scheduler_->SetDeferCommits(true);
615 scheduler_->SetNeedsBeginMainFrame();
616 EXPECT_NO_ACTION(client_);
618 // The SetNeedsRedraw will override the SetDeferCommits(true), to allow a
619 // begin frame to be needed.
620 client_->Reset();
621 scheduler_->SetNeedsRedraw();
622 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
624 client_->Reset();
625 AdvanceFrame();
626 // BeginMainFrame is not sent during the defer commit is on.
627 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
628 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
630 client_->Reset();
631 task_runner().RunPendingTasks(); // Run posted deadline.
632 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
633 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
634 EXPECT_TRUE(client_->needs_begin_frames());
636 client_->Reset();
637 AdvanceFrame();
638 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
641 TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
642 scheduler_settings_.use_external_begin_frame_source = true;
643 SetUpScheduler(true);
645 // SetNeedsBeginMainFrame should begin the frame.
646 scheduler_->SetNeedsBeginMainFrame();
647 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
649 client_->Reset();
650 EXPECT_SCOPED(AdvanceFrame());
651 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
652 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
653 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
655 EXPECT_TRUE(client_->needs_begin_frames());
656 client_->Reset();
658 // Now SetNeedsBeginMainFrame again. Calling here means we need a second
659 // commit.
660 scheduler_->SetNeedsBeginMainFrame();
661 EXPECT_EQ(client_->num_actions_(), 0);
662 client_->Reset();
664 // Finish the first commit.
665 scheduler_->NotifyBeginMainFrameStarted();
666 scheduler_->NotifyReadyToCommit();
667 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
668 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
669 client_->Reset();
671 // Activate it.
672 scheduler_->NotifyReadyToActivate();
673 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
674 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
675 client_->Reset();
677 task_runner().RunPendingTasks(); // Run posted deadline.
678 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
679 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
680 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
682 // Because we just swapped, the Scheduler should also request the next
683 // BeginImplFrame from the OutputSurface.
684 EXPECT_TRUE(client_->needs_begin_frames());
685 client_->Reset();
686 // Since another commit is needed, the next BeginImplFrame should initiate
687 // the second commit.
688 EXPECT_SCOPED(AdvanceFrame());
689 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
690 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
691 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
692 client_->Reset();
694 // Finishing the commit before the deadline should post a new deadline task
695 // to trigger the deadline early.
696 scheduler_->NotifyBeginMainFrameStarted();
697 scheduler_->NotifyReadyToCommit();
698 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
699 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
700 client_->Reset();
701 scheduler_->NotifyReadyToActivate();
702 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
703 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
704 client_->Reset();
705 task_runner().RunPendingTasks(); // Run posted deadline.
706 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
707 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
708 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
709 EXPECT_TRUE(client_->needs_begin_frames());
710 client_->Reset();
712 // On the next BeginImplFrame, verify we go back to a quiescent state and
713 // no longer request BeginImplFrames.
714 EXPECT_SCOPED(AdvanceFrame());
715 task_runner().RunPendingTasks(); // Run posted deadline.
716 EXPECT_FALSE(client_->needs_begin_frames());
717 client_->Reset();
720 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
721 public:
722 SchedulerClientThatsetNeedsDrawInsideDraw()
723 : FakeSchedulerClient(), request_redraws_(false) {}
725 void SetRequestRedrawsInsideDraw(bool enable) { request_redraws_ = enable; }
727 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
728 // Only SetNeedsRedraw the first time this is called
729 if (request_redraws_) {
730 scheduler_->SetNeedsRedraw();
732 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
735 DrawResult ScheduledActionDrawAndSwapForced() override {
736 NOTREACHED();
737 return DRAW_SUCCESS;
740 private:
741 bool request_redraws_;
744 // Tests for two different situations:
745 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
746 // a ScheduledActionDrawAndSwap
747 // 2. the scheduler drawing twice inside a single tick
748 TEST_F(SchedulerTest, RequestRedrawInsideDraw) {
749 SchedulerClientThatsetNeedsDrawInsideDraw* client =
750 new SchedulerClientThatsetNeedsDrawInsideDraw;
751 scheduler_settings_.use_external_begin_frame_source = true;
752 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
753 client->SetRequestRedrawsInsideDraw(true);
755 scheduler_->SetNeedsRedraw();
756 EXPECT_TRUE(scheduler_->RedrawPending());
757 EXPECT_TRUE(client->needs_begin_frames());
758 EXPECT_EQ(0, client->num_draws());
760 EXPECT_SCOPED(AdvanceFrame());
761 task_runner().RunPendingTasks(); // Run posted deadline.
762 EXPECT_EQ(1, client->num_draws());
763 EXPECT_TRUE(scheduler_->RedrawPending());
764 EXPECT_TRUE(client->needs_begin_frames());
766 client->SetRequestRedrawsInsideDraw(false);
768 EXPECT_SCOPED(AdvanceFrame());
769 task_runner().RunPendingTasks(); // Run posted deadline.
770 EXPECT_EQ(2, client_->num_draws());
771 EXPECT_FALSE(scheduler_->RedrawPending());
772 EXPECT_TRUE(client->needs_begin_frames());
774 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
775 // swap.
776 EXPECT_SCOPED(AdvanceFrame());
777 task_runner().RunPendingTasks(); // Run posted deadline.
778 EXPECT_EQ(2, client->num_draws());
779 EXPECT_FALSE(scheduler_->RedrawPending());
780 EXPECT_FALSE(client->needs_begin_frames());
783 // Test that requesting redraw inside a failed draw doesn't lose the request.
784 TEST_F(SchedulerTest, RequestRedrawInsideFailedDraw) {
785 SchedulerClientThatsetNeedsDrawInsideDraw* client =
786 new SchedulerClientThatsetNeedsDrawInsideDraw;
787 scheduler_settings_.use_external_begin_frame_source = true;
788 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
790 client->SetRequestRedrawsInsideDraw(true);
791 client->SetDrawWillHappen(false);
793 scheduler_->SetNeedsRedraw();
794 EXPECT_TRUE(scheduler_->RedrawPending());
795 EXPECT_TRUE(client->needs_begin_frames());
796 EXPECT_EQ(0, client->num_draws());
798 // Fail the draw.
799 EXPECT_SCOPED(AdvanceFrame());
800 task_runner().RunPendingTasks(); // Run posted deadline.
801 EXPECT_EQ(1, client->num_draws());
803 // We have a commit pending and the draw failed, and we didn't lose the redraw
804 // request.
805 EXPECT_TRUE(scheduler_->CommitPending());
806 EXPECT_TRUE(scheduler_->RedrawPending());
807 EXPECT_TRUE(client->needs_begin_frames());
809 client->SetRequestRedrawsInsideDraw(false);
811 // Fail the draw again.
812 EXPECT_SCOPED(AdvanceFrame());
813 task_runner().RunPendingTasks(); // Run posted deadline.
814 EXPECT_EQ(2, client->num_draws());
815 EXPECT_TRUE(scheduler_->CommitPending());
816 EXPECT_TRUE(scheduler_->RedrawPending());
817 EXPECT_TRUE(client->needs_begin_frames());
819 // Draw successfully.
820 client->SetDrawWillHappen(true);
821 EXPECT_SCOPED(AdvanceFrame());
822 task_runner().RunPendingTasks(); // Run posted deadline.
823 EXPECT_EQ(3, client->num_draws());
824 EXPECT_TRUE(scheduler_->CommitPending());
825 EXPECT_FALSE(scheduler_->RedrawPending());
826 EXPECT_TRUE(client->needs_begin_frames());
829 class SchedulerClientThatSetNeedsBeginMainFrameInsideDraw
830 : public FakeSchedulerClient {
831 public:
832 SchedulerClientThatSetNeedsBeginMainFrameInsideDraw()
833 : set_needs_commit_on_next_draw_(false) {}
835 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
836 // Only SetNeedsBeginMainFrame the first time this is called
837 if (set_needs_commit_on_next_draw_) {
838 scheduler_->SetNeedsBeginMainFrame();
839 set_needs_commit_on_next_draw_ = false;
841 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
844 DrawResult ScheduledActionDrawAndSwapForced() override {
845 NOTREACHED();
846 return DRAW_SUCCESS;
849 void SetNeedsBeginMainFrameOnNextDraw() {
850 set_needs_commit_on_next_draw_ = true;
853 private:
854 bool set_needs_commit_on_next_draw_;
857 // Tests for the scheduler infinite-looping on SetNeedsBeginMainFrame requests
858 // that happen inside a ScheduledActionDrawAndSwap
859 TEST_F(SchedulerTest, RequestCommitInsideDraw) {
860 SchedulerClientThatSetNeedsBeginMainFrameInsideDraw* client =
861 new SchedulerClientThatSetNeedsBeginMainFrameInsideDraw;
863 scheduler_settings_.use_external_begin_frame_source = true;
864 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
866 EXPECT_FALSE(client->needs_begin_frames());
867 scheduler_->SetNeedsRedraw();
868 EXPECT_TRUE(scheduler_->RedrawPending());
869 EXPECT_EQ(0, client->num_draws());
870 EXPECT_TRUE(client->needs_begin_frames());
872 client->SetNeedsBeginMainFrameOnNextDraw();
873 EXPECT_SCOPED(AdvanceFrame());
874 client->SetNeedsBeginMainFrameOnNextDraw();
875 task_runner().RunPendingTasks(); // Run posted deadline.
876 EXPECT_EQ(1, client->num_draws());
877 EXPECT_TRUE(scheduler_->CommitPending());
878 EXPECT_TRUE(client->needs_begin_frames());
879 scheduler_->NotifyBeginMainFrameStarted();
880 scheduler_->NotifyReadyToCommit();
881 scheduler_->NotifyReadyToActivate();
883 EXPECT_SCOPED(AdvanceFrame());
884 task_runner().RunPendingTasks(); // Run posted deadline.
885 EXPECT_EQ(2, client->num_draws());
887 EXPECT_FALSE(scheduler_->RedrawPending());
888 EXPECT_FALSE(scheduler_->CommitPending());
889 EXPECT_TRUE(client->needs_begin_frames());
891 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
892 // swap.
893 EXPECT_SCOPED(AdvanceFrame());
894 task_runner().RunPendingTasks(); // Run posted deadline.
895 EXPECT_EQ(2, client->num_draws());
896 EXPECT_FALSE(scheduler_->RedrawPending());
897 EXPECT_FALSE(scheduler_->CommitPending());
898 EXPECT_FALSE(client->needs_begin_frames());
901 // Tests that when a draw fails then the pending commit should not be dropped.
902 TEST_F(SchedulerTest, RequestCommitInsideFailedDraw) {
903 SchedulerClientThatsetNeedsDrawInsideDraw* client =
904 new SchedulerClientThatsetNeedsDrawInsideDraw;
905 scheduler_settings_.use_external_begin_frame_source = true;
906 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
908 client->SetDrawWillHappen(false);
910 scheduler_->SetNeedsRedraw();
911 EXPECT_TRUE(scheduler_->RedrawPending());
912 EXPECT_TRUE(client->needs_begin_frames());
913 EXPECT_EQ(0, client->num_draws());
915 // Fail the draw.
916 EXPECT_SCOPED(AdvanceFrame());
917 task_runner().RunPendingTasks(); // Run posted deadline.
918 EXPECT_EQ(1, client->num_draws());
920 // We have a commit pending and the draw failed, and we didn't lose the commit
921 // request.
922 EXPECT_TRUE(scheduler_->CommitPending());
923 EXPECT_TRUE(scheduler_->RedrawPending());
924 EXPECT_TRUE(client->needs_begin_frames());
926 // Fail the draw again.
927 EXPECT_SCOPED(AdvanceFrame());
929 task_runner().RunPendingTasks(); // Run posted deadline.
930 EXPECT_EQ(2, client->num_draws());
931 EXPECT_TRUE(scheduler_->CommitPending());
932 EXPECT_TRUE(scheduler_->RedrawPending());
933 EXPECT_TRUE(client->needs_begin_frames());
935 // Draw successfully.
936 client->SetDrawWillHappen(true);
937 EXPECT_SCOPED(AdvanceFrame());
938 task_runner().RunPendingTasks(); // Run posted deadline.
939 EXPECT_EQ(3, client->num_draws());
940 EXPECT_TRUE(scheduler_->CommitPending());
941 EXPECT_FALSE(scheduler_->RedrawPending());
942 EXPECT_TRUE(client->needs_begin_frames());
945 TEST_F(SchedulerTest, NoSwapWhenDrawFails) {
946 SchedulerClientThatSetNeedsBeginMainFrameInsideDraw* client =
947 new SchedulerClientThatSetNeedsBeginMainFrameInsideDraw;
948 scheduler_settings_.use_external_begin_frame_source = true;
949 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
951 scheduler_->SetNeedsRedraw();
952 EXPECT_TRUE(scheduler_->RedrawPending());
953 EXPECT_TRUE(client->needs_begin_frames());
954 EXPECT_EQ(0, client->num_draws());
956 // Draw successfully, this starts a new frame.
957 client->SetNeedsBeginMainFrameOnNextDraw();
958 EXPECT_SCOPED(AdvanceFrame());
959 task_runner().RunPendingTasks(); // Run posted deadline.
960 EXPECT_EQ(1, client->num_draws());
962 scheduler_->SetNeedsRedraw();
963 EXPECT_TRUE(scheduler_->RedrawPending());
964 EXPECT_TRUE(client->needs_begin_frames());
966 // Fail to draw, this should not start a frame.
967 client->SetDrawWillHappen(false);
968 client->SetNeedsBeginMainFrameOnNextDraw();
969 EXPECT_SCOPED(AdvanceFrame());
970 task_runner().RunPendingTasks(); // Run posted deadline.
971 EXPECT_EQ(2, client->num_draws());
974 class SchedulerClientNeedsPrepareTilesInDraw : public FakeSchedulerClient {
975 public:
976 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
977 scheduler_->SetNeedsPrepareTiles();
978 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
982 // Test prepare tiles is independant of draws.
983 TEST_F(SchedulerTest, PrepareTiles) {
984 SchedulerClientNeedsPrepareTilesInDraw* client =
985 new SchedulerClientNeedsPrepareTilesInDraw;
986 scheduler_settings_.use_external_begin_frame_source = true;
987 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
989 // Request both draw and prepare tiles. PrepareTiles shouldn't
990 // be trigged until BeginImplFrame.
991 client->Reset();
992 scheduler_->SetNeedsPrepareTiles();
993 scheduler_->SetNeedsRedraw();
994 EXPECT_TRUE(scheduler_->RedrawPending());
995 EXPECT_TRUE(scheduler_->PrepareTilesPending());
996 EXPECT_TRUE(client->needs_begin_frames());
997 EXPECT_EQ(0, client->num_draws());
998 EXPECT_FALSE(client->HasAction("ScheduledActionPrepareTiles"));
999 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1001 // We have no immediate actions to perform, so the BeginImplFrame should post
1002 // the deadline task.
1003 client->Reset();
1004 EXPECT_SCOPED(AdvanceFrame());
1005 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1006 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1007 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1009 // On the deadline, he actions should have occured in the right order.
1010 client->Reset();
1011 task_runner().RunPendingTasks(); // Run posted deadline.
1012 EXPECT_EQ(1, client->num_draws());
1013 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1014 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1015 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1016 client->ActionIndex("ScheduledActionPrepareTiles"));
1017 EXPECT_FALSE(scheduler_->RedrawPending());
1018 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1019 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1021 // Request a draw. We don't need a PrepareTiles yet.
1022 client->Reset();
1023 scheduler_->SetNeedsRedraw();
1024 EXPECT_TRUE(scheduler_->RedrawPending());
1025 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1026 EXPECT_TRUE(client->needs_begin_frames());
1027 EXPECT_EQ(0, client->num_draws());
1029 // We have no immediate actions to perform, so the BeginImplFrame should post
1030 // the deadline task.
1031 client->Reset();
1032 EXPECT_SCOPED(AdvanceFrame());
1033 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1034 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1035 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1037 // Draw. The draw will trigger SetNeedsPrepareTiles, and
1038 // then the PrepareTiles action will be triggered after the Draw.
1039 // Afterwards, neither a draw nor PrepareTiles are pending.
1040 client->Reset();
1041 task_runner().RunPendingTasks(); // Run posted deadline.
1042 EXPECT_EQ(1, client->num_draws());
1043 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1044 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1045 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1046 client->ActionIndex("ScheduledActionPrepareTiles"));
1047 EXPECT_FALSE(scheduler_->RedrawPending());
1048 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1049 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1051 // We need a BeginImplFrame where we don't swap to go idle.
1052 client->Reset();
1053 EXPECT_SCOPED(AdvanceFrame());
1054 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1055 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1056 client->Reset();
1057 task_runner().RunPendingTasks(); // Run posted deadline.
1058 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1059 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1060 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1061 EXPECT_EQ(0, client->num_draws());
1063 // Now trigger a PrepareTiles outside of a draw. We will then need
1064 // a begin-frame for the PrepareTiles, but we don't need a draw.
1065 client->Reset();
1066 EXPECT_FALSE(client->needs_begin_frames());
1067 scheduler_->SetNeedsPrepareTiles();
1068 EXPECT_TRUE(client->needs_begin_frames());
1069 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1070 EXPECT_FALSE(scheduler_->RedrawPending());
1072 // BeginImplFrame. There will be no draw, only PrepareTiles.
1073 client->Reset();
1074 EXPECT_SCOPED(AdvanceFrame());
1075 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1076 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1077 client->Reset();
1078 task_runner().RunPendingTasks(); // Run posted deadline.
1079 EXPECT_EQ(0, client->num_draws());
1080 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1081 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1082 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1085 // Test that PrepareTiles only happens once per frame. If an external caller
1086 // initiates it, then the state machine should not PrepareTiles on that frame.
1087 TEST_F(SchedulerTest, PrepareTilesOncePerFrame) {
1088 scheduler_settings_.use_external_begin_frame_source = true;
1089 SetUpScheduler(true);
1091 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
1092 // again.
1093 scheduler_->SetNeedsPrepareTiles();
1094 scheduler_->SetNeedsRedraw();
1095 client_->Reset();
1096 EXPECT_SCOPED(AdvanceFrame());
1097 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1098 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1099 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1101 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1102 scheduler_->WillPrepareTiles();
1103 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1104 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1106 client_->Reset();
1107 task_runner().RunPendingTasks(); // Run posted deadline.
1108 EXPECT_EQ(1, client_->num_draws());
1109 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1110 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1111 EXPECT_FALSE(scheduler_->RedrawPending());
1112 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1113 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1115 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1116 scheduler_->SetNeedsPrepareTiles();
1117 scheduler_->SetNeedsRedraw();
1118 client_->Reset();
1119 EXPECT_SCOPED(AdvanceFrame());
1120 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1121 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1122 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1124 client_->Reset();
1125 task_runner().RunPendingTasks(); // Run posted deadline.
1126 EXPECT_EQ(1, client_->num_draws());
1127 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1128 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1129 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1130 client_->ActionIndex("ScheduledActionPrepareTiles"));
1131 EXPECT_FALSE(scheduler_->RedrawPending());
1132 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1133 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1135 // If we get another DidPrepareTiles within the same frame, we should
1136 // not PrepareTiles on the next frame.
1137 scheduler_->WillPrepareTiles();
1138 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1139 scheduler_->SetNeedsPrepareTiles();
1140 scheduler_->SetNeedsRedraw();
1141 client_->Reset();
1142 EXPECT_SCOPED(AdvanceFrame());
1143 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1144 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1145 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1147 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1149 client_->Reset();
1150 task_runner().RunPendingTasks(); // Run posted deadline.
1151 EXPECT_EQ(1, client_->num_draws());
1152 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1153 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1154 EXPECT_FALSE(scheduler_->RedrawPending());
1155 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1157 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1158 // frame. This verifies we don't alternate calling PrepareTiles once and
1159 // twice.
1160 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1161 scheduler_->WillPrepareTiles();
1162 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1163 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1164 scheduler_->SetNeedsPrepareTiles();
1165 scheduler_->SetNeedsRedraw();
1166 client_->Reset();
1167 EXPECT_SCOPED(AdvanceFrame());
1168 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1169 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1170 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1172 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1174 client_->Reset();
1175 task_runner().RunPendingTasks(); // Run posted deadline.
1176 EXPECT_EQ(1, client_->num_draws());
1177 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1178 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1179 EXPECT_FALSE(scheduler_->RedrawPending());
1180 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1182 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1183 scheduler_->SetNeedsPrepareTiles();
1184 scheduler_->SetNeedsRedraw();
1185 client_->Reset();
1186 EXPECT_SCOPED(AdvanceFrame());
1187 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1188 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1189 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1191 client_->Reset();
1192 task_runner().RunPendingTasks(); // Run posted deadline.
1193 EXPECT_EQ(1, client_->num_draws());
1194 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1195 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1196 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1197 client_->ActionIndex("ScheduledActionPrepareTiles"));
1198 EXPECT_FALSE(scheduler_->RedrawPending());
1199 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1200 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1203 TEST_F(SchedulerTest, PrepareTilesFunnelResetOnVisibilityChange) {
1204 scoped_ptr<SchedulerClientNeedsPrepareTilesInDraw> client =
1205 make_scoped_ptr(new SchedulerClientNeedsPrepareTilesInDraw);
1206 scheduler_settings_.use_external_begin_frame_source = true;
1207 SetUpScheduler(client.Pass(), true);
1209 // Simulate a few visibility changes and associated PrepareTiles.
1210 for (int i = 0; i < 10; i++) {
1211 scheduler_->SetVisible(false);
1212 scheduler_->WillPrepareTiles();
1213 scheduler_->DidPrepareTiles();
1215 scheduler_->SetVisible(true);
1216 scheduler_->WillPrepareTiles();
1217 scheduler_->DidPrepareTiles();
1220 client_->Reset();
1221 scheduler_->SetNeedsRedraw();
1222 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1224 client_->Reset();
1225 AdvanceFrame();
1226 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1227 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1228 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1230 client_->Reset();
1231 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1232 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1233 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
1234 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 1, 2);
1237 TEST_F(SchedulerTest, TriggerBeginFrameDeadlineEarly) {
1238 SchedulerClientNeedsPrepareTilesInDraw* client =
1239 new SchedulerClientNeedsPrepareTilesInDraw;
1240 scheduler_settings_.use_external_begin_frame_source = true;
1241 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1243 scheduler_->SetNeedsRedraw();
1244 EXPECT_SCOPED(AdvanceFrame());
1246 // The deadline should be zero since there is no work other than drawing
1247 // pending.
1248 EXPECT_EQ(base::TimeTicks(), client->posted_begin_impl_frame_deadline());
1251 TEST_F(SchedulerTest, WaitForReadyToDrawDoNotPostDeadline) {
1252 SchedulerClientNeedsPrepareTilesInDraw* client =
1253 new SchedulerClientNeedsPrepareTilesInDraw;
1254 scheduler_settings_.use_external_begin_frame_source = true;
1255 scheduler_settings_.commit_to_active_tree = true;
1256 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1258 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
1259 scheduler_->SetNeedsBeginMainFrame();
1260 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1261 client_->Reset();
1263 // Begin new frame.
1264 EXPECT_SCOPED(AdvanceFrame());
1265 scheduler_->NotifyBeginMainFrameStarted();
1266 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1267 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1269 client_->Reset();
1270 scheduler_->NotifyReadyToCommit();
1271 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1273 client_->Reset();
1274 scheduler_->NotifyReadyToActivate();
1275 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
1277 // Scheduler won't post deadline in the mode.
1278 client_->Reset();
1279 task_runner().RunPendingTasks(); // Try to run posted deadline.
1280 // There is no posted deadline.
1281 EXPECT_NO_ACTION(client_);
1283 // Scheduler received ready to draw signal, and posted deadline.
1284 scheduler_->NotifyReadyToDraw();
1285 client_->Reset();
1286 task_runner().RunPendingTasks(); // Run posted deadline.
1287 EXPECT_EQ(1, client_->num_draws());
1288 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1291 TEST_F(SchedulerTest, WaitForReadyToDrawCancelledWhenLostOutputSurface) {
1292 SchedulerClientNeedsPrepareTilesInDraw* client =
1293 new SchedulerClientNeedsPrepareTilesInDraw;
1294 scheduler_settings_.use_external_begin_frame_source = true;
1295 scheduler_settings_.commit_to_active_tree = true;
1296 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1298 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
1299 scheduler_->SetNeedsBeginMainFrame();
1300 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1301 client_->Reset();
1303 // Begin new frame.
1304 EXPECT_SCOPED(AdvanceFrame());
1305 scheduler_->NotifyBeginMainFrameStarted();
1306 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1307 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1309 client_->Reset();
1310 scheduler_->NotifyReadyToCommit();
1311 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1313 client_->Reset();
1314 scheduler_->NotifyReadyToActivate();
1315 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
1317 // Scheduler won't post deadline in the mode.
1318 client_->Reset();
1319 task_runner().RunPendingTasks(); // Try to run posted deadline.
1320 // There is no posted deadline.
1321 EXPECT_NO_ACTION(client_);
1323 // Scheduler loses output surface, and stops waiting for ready to draw signal.
1324 client_->Reset();
1325 scheduler_->DidLoseOutputSurface();
1326 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1327 task_runner().RunPendingTasks(); // Run posted deadline.
1328 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
1329 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
1330 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
1333 void SchedulerTest::CheckMainFrameSkippedAfterLateCommit(
1334 bool expect_send_begin_main_frame) {
1335 // Impl thread hits deadline before commit finishes.
1336 scheduler_->SetNeedsBeginMainFrame();
1337 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1338 EXPECT_SCOPED(AdvanceFrame());
1339 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1340 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1341 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1342 scheduler_->NotifyBeginMainFrameStarted();
1343 scheduler_->NotifyReadyToCommit();
1344 scheduler_->NotifyReadyToActivate();
1345 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5);
1346 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5);
1347 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5);
1348 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5);
1349 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 4, 5);
1350 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1352 client_->Reset();
1353 scheduler_->SetNeedsBeginMainFrame();
1354 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1355 EXPECT_SCOPED(AdvanceFrame());
1356 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1357 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1358 EXPECT_EQ(expect_send_begin_main_frame,
1359 scheduler_->MainThreadMissedLastDeadline());
1360 EXPECT_EQ(expect_send_begin_main_frame,
1361 client_->HasAction("ScheduledActionSendBeginMainFrame"));
1364 TEST_F(SchedulerTest, MainFrameSkippedAfterLateCommit) {
1365 scheduler_settings_.use_external_begin_frame_source = true;
1366 SetUpScheduler(true);
1368 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1369 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1371 bool expect_send_begin_main_frame = false;
1372 EXPECT_SCOPED(
1373 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1376 TEST_F(SchedulerTest,
1377 MainFrameNotSkippedAfterLateCommitInPreferImplLatencyMode) {
1378 scheduler_settings_.use_external_begin_frame_source = true;
1379 SetUpScheduler(true);
1380 scheduler_->SetImplLatencyTakesPriority(true);
1382 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1383 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1385 bool expect_send_begin_main_frame = true;
1386 EXPECT_SCOPED(
1387 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1390 TEST_F(SchedulerTest,
1391 MainFrameNotSkippedAfterLateCommit_CommitEstimateTooLong) {
1392 scheduler_settings_.use_external_begin_frame_source = true;
1393 SetUpScheduler(true);
1394 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1395 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1396 auto slow_duration = base::TimeDelta::FromSeconds(1);
1397 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate(
1398 slow_duration);
1400 bool expect_send_begin_main_frame = true;
1401 EXPECT_SCOPED(
1402 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1405 TEST_F(SchedulerTest,
1406 MainFrameNotSkippedAfterLateCommit_ReadyToActivateEstimateTooLong) {
1407 scheduler_settings_.use_external_begin_frame_source = true;
1408 SetUpScheduler(true);
1409 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1410 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1411 auto slow_duration = base::TimeDelta::FromSeconds(1);
1412 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate(
1413 slow_duration);
1415 bool expect_send_begin_main_frame = true;
1416 EXPECT_SCOPED(
1417 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1420 TEST_F(SchedulerTest,
1421 MainFrameNotSkippedAfterLateCommit_ActivateEstimateTooLong) {
1422 scheduler_settings_.use_external_begin_frame_source = true;
1423 SetUpScheduler(true);
1424 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1425 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1426 auto slow_duration = base::TimeDelta::FromSeconds(1);
1427 fake_compositor_timing_history_->SetActivateDurationEstimate(slow_duration);
1429 bool expect_send_begin_main_frame = true;
1430 EXPECT_SCOPED(
1431 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1434 TEST_F(SchedulerTest, MainFrameNotSkippedAfterLateCommit_DrawEstimateTooLong) {
1435 scheduler_settings_.use_external_begin_frame_source = true;
1436 SetUpScheduler(true);
1437 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1438 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1439 auto slow_duration = base::TimeDelta::FromSeconds(1);
1440 fake_compositor_timing_history_->SetDrawDurationEstimate(slow_duration);
1442 bool expect_send_begin_main_frame = true;
1443 EXPECT_SCOPED(
1444 CheckMainFrameSkippedAfterLateCommit(expect_send_begin_main_frame));
1447 void SchedulerTest::ImplFrameSkippedAfterLateSwapAck(
1448 bool swap_ack_before_deadline) {
1449 // To get into a high latency state, this test disables automatic swap acks.
1450 scheduler_->SetMaxSwapsPending(1);
1451 client_->SetAutomaticSwapAck(false);
1453 // Draw and swap for first BeginFrame
1454 client_->Reset();
1455 scheduler_->SetNeedsBeginMainFrame();
1456 scheduler_->SetNeedsRedraw();
1457 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1458 SendNextBeginFrame();
1459 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 4);
1460 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 4);
1461 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4);
1462 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 4);
1464 client_->Reset();
1465 scheduler_->NotifyBeginMainFrameStarted();
1466 scheduler_->NotifyReadyToCommit();
1467 scheduler_->NotifyReadyToActivate();
1468 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1469 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1470 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4);
1471 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4);
1472 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4);
1473 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1475 // Verify we skip every other frame if the swap ack consistently
1476 // comes back late.
1477 for (int i = 0; i < 10; i++) {
1478 // Not calling scheduler_->DidSwapBuffersComplete() until after next
1479 // BeginImplFrame puts the impl thread in high latency mode.
1480 client_->Reset();
1481 scheduler_->SetNeedsBeginMainFrame();
1482 scheduler_->SetNeedsRedraw();
1483 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1484 SendNextBeginFrame();
1485 // Verify that we skip the BeginImplFrame
1486 EXPECT_NO_ACTION(client_);
1487 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1488 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1490 // Verify that we do not perform any actions after we are no longer
1491 // swap throttled.
1492 client_->Reset();
1493 if (swap_ack_before_deadline) {
1494 // It shouldn't matter if the swap ack comes back before the deadline...
1495 scheduler_->DidSwapBuffersComplete();
1496 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1497 } else {
1498 // ... or after the deadline.
1499 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1500 scheduler_->DidSwapBuffersComplete();
1502 EXPECT_NO_ACTION(client_);
1504 // Verify that we start the next BeginImplFrame and continue normally
1505 // after having just skipped a BeginImplFrame.
1506 client_->Reset();
1507 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1508 SendNextBeginFrame();
1509 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
1510 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
1511 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3);
1513 client_->Reset();
1514 scheduler_->NotifyBeginMainFrameStarted();
1515 scheduler_->NotifyReadyToCommit();
1516 scheduler_->NotifyReadyToActivate();
1517 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1518 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4);
1519 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4);
1520 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4);
1521 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1525 TEST_F(SchedulerTest,
1526 ImplFrameSkippedAfterLateSwapAck_FastEstimates_SwapAckThenDeadline) {
1527 scheduler_settings_.use_external_begin_frame_source = true;
1528 SetUpScheduler(true);
1530 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1531 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1533 bool swap_ack_before_deadline = true;
1534 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline));
1537 TEST_F(SchedulerTest,
1538 ImplFrameSkippedAfterLateSwapAck_FastEstimates_DeadlineThenSwapAck) {
1539 scheduler_settings_.use_external_begin_frame_source = true;
1540 SetUpScheduler(true);
1542 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1543 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1545 bool swap_ack_before_deadline = false;
1546 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline));
1549 TEST_F(SchedulerTest,
1550 ImplFrameSkippedAfterLateSwapAck_ImplLatencyTakesPriority) {
1551 scheduler_settings_.use_external_begin_frame_source = true;
1552 SetUpScheduler(true);
1554 // Even if every estimate related to the main thread is slow, we should
1555 // still expect to recover impl thread latency if the draw is fast and we
1556 // are in impl latency takes priority.
1557 scheduler_->SetImplLatencyTakesPriority(true);
1558 auto slow_duration = base::TimeDelta::FromSeconds(1);
1559 fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration);
1560 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1561 fake_compositor_timing_history_->SetDrawDurationEstimate(fast_duration);
1563 bool swap_ack_before_deadline = false;
1564 EXPECT_SCOPED(ImplFrameSkippedAfterLateSwapAck(swap_ack_before_deadline));
1567 TEST_F(SchedulerTest,
1568 ImplFrameSkippedAfterLateSwapAck_OnlyImplSideUpdatesExpected) {
1569 // This tests that we recover impl thread latency when there are no commits.
1570 scheduler_settings_.use_external_begin_frame_source = true;
1571 SetUpScheduler(true);
1573 // To get into a high latency state, this test disables automatic swap acks.
1574 scheduler_->SetMaxSwapsPending(1);
1575 client_->SetAutomaticSwapAck(false);
1577 // Even if every estimate related to the main thread is slow, we should
1578 // still expect to recover impl thread latency if there are no commits from
1579 // the main thread.
1580 auto slow_duration = base::TimeDelta::FromSeconds(1);
1581 fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration);
1582 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1583 fake_compositor_timing_history_->SetDrawDurationEstimate(fast_duration);
1585 // Draw and swap for first BeginFrame
1586 client_->Reset();
1587 scheduler_->SetNeedsRedraw();
1588 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1589 SendNextBeginFrame();
1590 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3);
1591 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3);
1592 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 3);
1594 client_->Reset();
1595 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1596 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1597 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
1599 // Verify we skip every other frame if the swap ack consistently
1600 // comes back late.
1601 for (int i = 0; i < 10; i++) {
1602 // Not calling scheduler_->DidSwapBuffersComplete() until after next
1603 // BeginImplFrame puts the impl thread in high latency mode.
1604 client_->Reset();
1605 scheduler_->SetNeedsRedraw();
1606 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1607 SendNextBeginFrame();
1608 // Verify that we skip the BeginImplFrame
1609 EXPECT_NO_ACTION(client_);
1610 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1611 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1613 // Verify that we do not perform any actions after we are no longer
1614 // swap throttled.
1615 client_->Reset();
1616 scheduler_->DidSwapBuffersComplete();
1617 EXPECT_NO_ACTION(client_);
1619 // Verify that we start the next BeginImplFrame and continue normally
1620 // after having just skipped a BeginImplFrame.
1621 client_->Reset();
1622 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1623 SendNextBeginFrame();
1624 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1625 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1627 client_->Reset();
1628 // Deadline should be immediate.
1629 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1630 task_runner().RunUntilTime(now_src_->NowTicks());
1631 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1632 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
1636 void SchedulerTest::ImplFrameIsNotSkippedAfterLateSwapAck() {
1637 // To get into a high latency state, this test disables automatic swap acks.
1638 scheduler_->SetMaxSwapsPending(1);
1639 client_->SetAutomaticSwapAck(false);
1641 // Draw and swap for first BeginFrame
1642 client_->Reset();
1643 scheduler_->SetNeedsBeginMainFrame();
1644 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1645 SendNextBeginFrame();
1646 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3);
1647 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3);
1648 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3);
1650 client_->Reset();
1651 scheduler_->NotifyBeginMainFrameStarted();
1652 scheduler_->NotifyReadyToCommit();
1653 scheduler_->NotifyReadyToActivate();
1654 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1655 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1656 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 4);
1657 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 4);
1658 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 4);
1659 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1661 // Verify impl thread consistently operates in high latency mode
1662 // without skipping any frames.
1663 for (int i = 0; i < 10; i++) {
1664 // Not calling scheduler_->DidSwapBuffersComplete() until after next frame
1665 // puts the impl thread in high latency mode.
1666 client_->Reset();
1667 scheduler_->SetNeedsBeginMainFrame();
1668 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1669 SendNextBeginFrame();
1670 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
1671 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1672 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1674 client_->Reset();
1675 scheduler_->DidSwapBuffersComplete();
1676 scheduler_->NotifyBeginMainFrameStarted();
1677 scheduler_->NotifyReadyToCommit();
1678 scheduler_->NotifyReadyToActivate();
1679 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1681 // Verify that we don't skip the actions of the BeginImplFrame
1682 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 0, 5);
1683 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 5);
1684 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 2, 5);
1685 EXPECT_ACTION("ScheduledActionAnimate", client_, 3, 5);
1686 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 5);
1690 TEST_F(SchedulerTest,
1691 ImplFrameIsNotSkippedAfterLateSwapAck_CommitEstimateTooLong) {
1692 scheduler_settings_.use_external_begin_frame_source = true;
1693 SetUpScheduler(true);
1694 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1695 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1696 auto slow_duration = base::TimeDelta::FromSeconds(1);
1697 fake_compositor_timing_history_->SetBeginMainFrameToCommitDurationEstimate(
1698 slow_duration);
1699 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck());
1702 TEST_F(SchedulerTest,
1703 ImplFrameIsNotSkippedAfterLateSwapAck_ReadyToActivateEstimateTooLong) {
1704 scheduler_settings_.use_external_begin_frame_source = true;
1705 SetUpScheduler(true);
1706 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1707 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1708 auto slow_duration = base::TimeDelta::FromSeconds(1);
1709 fake_compositor_timing_history_->SetCommitToReadyToActivateDurationEstimate(
1710 slow_duration);
1711 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck());
1714 TEST_F(SchedulerTest,
1715 ImplFrameIsNotSkippedAfterLateSwapAck_ActivateEstimateTooLong) {
1716 scheduler_settings_.use_external_begin_frame_source = true;
1717 SetUpScheduler(true);
1718 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1719 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1720 auto slow_duration = base::TimeDelta::FromSeconds(1);
1721 fake_compositor_timing_history_->SetActivateDurationEstimate(slow_duration);
1722 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck());
1725 TEST_F(SchedulerTest,
1726 ImplFrameIsNotSkippedAfterLateSwapAck_DrawEstimateTooLong) {
1727 scheduler_settings_.use_external_begin_frame_source = true;
1728 SetUpScheduler(true);
1729 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1730 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1731 auto slow_duration = base::TimeDelta::FromSeconds(1);
1732 fake_compositor_timing_history_->SetDrawDurationEstimate(slow_duration);
1733 EXPECT_SCOPED(ImplFrameIsNotSkippedAfterLateSwapAck());
1736 TEST_F(SchedulerTest,
1737 MainFrameThenImplFrameSkippedAfterLateCommitAndLateSwapAck) {
1738 // Set up client with custom estimates.
1739 // This test starts off with expensive estimates to prevent latency recovery
1740 // initially, then lowers the estimates to enable it once both the main
1741 // and impl threads are in a high latency mode.
1742 scheduler_settings_.use_external_begin_frame_source = true;
1743 SetUpScheduler(true);
1745 auto slow_duration = base::TimeDelta::FromSeconds(1);
1746 fake_compositor_timing_history_->SetAllEstimatesTo(slow_duration);
1748 // To get into a high latency state, this test disables automatic swap acks.
1749 scheduler_->SetMaxSwapsPending(1);
1750 client_->SetAutomaticSwapAck(false);
1752 // Impl thread hits deadline before commit finishes to make
1753 // MainThreadMissedLastDeadline true
1754 client_->Reset();
1755 scheduler_->SetNeedsBeginMainFrame();
1756 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1757 EXPECT_SCOPED(AdvanceFrame());
1758 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1759 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1760 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1761 scheduler_->NotifyBeginMainFrameStarted();
1762 scheduler_->NotifyReadyToCommit();
1763 scheduler_->NotifyReadyToActivate();
1764 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1766 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5);
1767 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5);
1768 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5);
1769 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5);
1770 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 4, 5);
1772 // Draw and swap for first commit, start second commit.
1773 client_->Reset();
1774 scheduler_->SetNeedsBeginMainFrame();
1775 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1776 EXPECT_SCOPED(AdvanceFrame());
1777 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1778 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1779 scheduler_->NotifyBeginMainFrameStarted();
1780 scheduler_->NotifyReadyToCommit();
1781 scheduler_->NotifyReadyToActivate();
1783 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6);
1784 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 6);
1785 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 6);
1786 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 6);
1787 EXPECT_ACTION("ScheduledActionCommit", client_, 4, 6);
1788 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 5, 6);
1790 // Don't call scheduler_->DidSwapBuffersComplete() until after next frame
1791 // to put the impl thread in a high latency mode.
1792 client_->Reset();
1793 scheduler_->SetNeedsBeginMainFrame();
1794 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1795 EXPECT_SCOPED(AdvanceFrame());
1796 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1797 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1799 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1800 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1801 // Note: BeginMainFrame and swap are skipped here because of
1802 // swap ack backpressure, not because of latency recovery.
1803 EXPECT_FALSE(client_->HasAction("ScheduledActionSendBeginMainFrame"));
1804 EXPECT_FALSE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1805 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1807 // Lower estimates so that the scheduler will attempt latency recovery.
1808 auto fast_duration = base::TimeDelta::FromMilliseconds(1);
1809 fake_compositor_timing_history_->SetAllEstimatesTo(fast_duration);
1811 // Now that both threads are in a high latency mode, make sure we
1812 // skip the BeginMainFrame, then the BeginImplFrame, but not both
1813 // at the same time.
1815 // Verify we skip BeginMainFrame first.
1816 client_->Reset();
1817 // Previous commit request is still outstanding.
1818 EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
1819 EXPECT_TRUE(scheduler_->SwapThrottled());
1820 SendNextBeginFrame();
1821 EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
1822 scheduler_->DidSwapBuffersComplete();
1823 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1825 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1826 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
1827 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
1828 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3);
1830 // Verify we skip the BeginImplFrame second.
1831 client_->Reset();
1832 // Previous commit request is still outstanding.
1833 EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
1834 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1835 SendNextBeginFrame();
1836 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1837 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1838 scheduler_->DidSwapBuffersComplete();
1839 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1841 EXPECT_NO_ACTION(client_);
1843 // Then verify we operate in a low latency mode.
1844 client_->Reset();
1845 // Previous commit request is still outstanding.
1846 EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
1847 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1848 SendNextBeginFrame();
1849 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1850 scheduler_->NotifyBeginMainFrameStarted();
1851 scheduler_->NotifyReadyToCommit();
1852 scheduler_->NotifyReadyToActivate();
1853 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1854 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1855 scheduler_->DidSwapBuffersComplete();
1856 EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
1858 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6);
1859 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 6);
1860 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 6);
1861 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 3, 6);
1862 EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 6);
1863 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 5, 6);
1866 TEST_F(
1867 SchedulerTest,
1868 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) {
1869 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1870 // thread. This prevents the scheduler from receiving any pending swap acks.
1872 scheduler_settings_.use_external_begin_frame_source = true;
1873 scheduler_settings_.main_frame_while_swap_throttled_enabled = true;
1874 SetUpScheduler(true);
1876 // Disables automatic swap acks so this test can force swap ack throttling
1877 // to simulate a blocked Browser ui thread.
1878 scheduler_->SetMaxSwapsPending(1);
1879 client_->SetAutomaticSwapAck(false);
1881 // Get a new active tree in main-thread high latency mode and put us
1882 // in a swap throttled state.
1883 client_->Reset();
1884 EXPECT_FALSE(scheduler_->CommitPending());
1885 scheduler_->SetNeedsBeginMainFrame();
1886 scheduler_->SetNeedsRedraw();
1887 EXPECT_SCOPED(AdvanceFrame());
1888 EXPECT_TRUE(scheduler_->CommitPending());
1889 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1890 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1891 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1892 scheduler_->NotifyBeginMainFrameStarted();
1893 scheduler_->NotifyReadyToCommit();
1894 scheduler_->NotifyReadyToActivate();
1895 EXPECT_FALSE(scheduler_->CommitPending());
1896 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 7);
1897 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 7);
1898 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 7);
1899 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 7);
1900 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 7);
1901 EXPECT_ACTION("ScheduledActionCommit", client_, 5, 7);
1902 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 6, 7);
1904 // Make sure that we can finish the next commit even while swap throttled.
1905 client_->Reset();
1906 EXPECT_FALSE(scheduler_->CommitPending());
1907 scheduler_->SetNeedsBeginMainFrame();
1908 EXPECT_SCOPED(AdvanceFrame());
1909 scheduler_->NotifyBeginMainFrameStarted();
1910 scheduler_->NotifyReadyToCommit();
1911 scheduler_->NotifyReadyToActivate();
1912 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1913 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1914 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1915 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 5);
1916 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 5);
1917 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5);
1918 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5);
1919 EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 5);
1921 // Make sure we do not send a BeginMainFrame while swap throttled and
1922 // we have both a pending tree and an active tree.
1923 client_->Reset();
1924 EXPECT_FALSE(scheduler_->CommitPending());
1925 scheduler_->SetNeedsBeginMainFrame();
1926 EXPECT_SCOPED(AdvanceFrame());
1927 EXPECT_FALSE(scheduler_->CommitPending());
1928 task_runner().RunPendingTasks(); // Run posted deadline.
1929 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1930 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1933 TEST_F(SchedulerTest,
1934 Deadlock_NoBeginMainFrameWhileSwapTrottledAndPipelineFull) {
1935 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1936 // thread. This prevents the scheduler from receiving any pending swap acks.
1938 // This particular test makes sure we do not send a BeginMainFrame while
1939 // swap trottled and we have a pending tree and active tree that
1940 // still needs to be drawn for the first time.
1942 scheduler_settings_.use_external_begin_frame_source = true;
1943 scheduler_settings_.main_frame_while_swap_throttled_enabled = true;
1944 scheduler_settings_.main_frame_before_activation_enabled = true;
1945 SetUpScheduler(true);
1947 // Disables automatic swap acks so this test can force swap ack throttling
1948 // to simulate a blocked Browser ui thread.
1949 scheduler_->SetMaxSwapsPending(1);
1950 client_->SetAutomaticSwapAck(false);
1952 // Start a new commit in main-thread high latency mode and hold off on
1953 // activation.
1954 client_->Reset();
1955 EXPECT_FALSE(scheduler_->CommitPending());
1956 scheduler_->SetNeedsBeginMainFrame();
1957 scheduler_->SetNeedsRedraw();
1958 EXPECT_SCOPED(AdvanceFrame());
1959 EXPECT_TRUE(scheduler_->CommitPending());
1960 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1961 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1962 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1963 scheduler_->DidSwapBuffersComplete();
1964 scheduler_->NotifyBeginMainFrameStarted();
1965 scheduler_->NotifyReadyToCommit();
1966 EXPECT_FALSE(scheduler_->CommitPending());
1967 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 6);
1968 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 6);
1969 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 6);
1970 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 6);
1971 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 6);
1972 EXPECT_ACTION("ScheduledActionCommit", client_, 5, 6);
1974 // Start another commit while we still have aa pending tree.
1975 // Enter a swap throttled state.
1976 client_->Reset();
1977 EXPECT_FALSE(scheduler_->CommitPending());
1978 scheduler_->SetNeedsBeginMainFrame();
1979 scheduler_->SetNeedsRedraw();
1980 EXPECT_SCOPED(AdvanceFrame());
1981 EXPECT_TRUE(scheduler_->CommitPending());
1982 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1983 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1984 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1985 scheduler_->NotifyBeginMainFrameStarted();
1986 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4);
1987 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4);
1988 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4);
1989 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1991 // Can't commit yet because there's still a pending tree.
1992 client_->Reset();
1993 scheduler_->NotifyReadyToCommit();
1994 EXPECT_NO_ACTION(client_);
1996 // Activate the pending tree, which also unblocks the commit immediately.
1997 client_->Reset();
1998 scheduler_->NotifyReadyToActivate();
1999 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 2);
2000 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 2);
2002 // Make sure we do not send a BeginMainFrame while swap throttled and
2003 // we have both a pending tree and an active tree that still needs
2004 // it's first draw.
2005 client_->Reset();
2006 EXPECT_FALSE(scheduler_->CommitPending());
2007 scheduler_->SetNeedsBeginMainFrame();
2008 EXPECT_SCOPED(AdvanceFrame());
2009 EXPECT_FALSE(scheduler_->CommitPending());
2010 task_runner().RunPendingTasks(); // Run posted deadline.
2011 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2012 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2015 TEST_F(
2016 SchedulerTest,
2017 CommitMakesProgressWhenIdleAndHasPendingTreeAndActiveTreeNeedsFirstDraw) {
2018 // This verifies we don't block commits longer than we need to
2019 // for performance reasons - not deadlock reasons.
2021 // Since we are simulating a long commit, set up a client with draw duration
2022 // estimates that prevent skipping main frames to get to low latency mode.
2023 scheduler_settings_.use_external_begin_frame_source = true;
2024 scheduler_settings_.main_frame_while_swap_throttled_enabled = true;
2025 scheduler_settings_.main_frame_before_activation_enabled = true;
2026 SetUpScheduler(true);
2028 // Disables automatic swap acks so this test can force swap ack throttling
2029 // to simulate a blocked Browser ui thread.
2030 scheduler_->SetMaxSwapsPending(1);
2031 client_->SetAutomaticSwapAck(false);
2033 // Start a new commit in main-thread high latency mode and hold off on
2034 // activation.
2035 client_->Reset();
2036 EXPECT_FALSE(scheduler_->CommitPending());
2037 scheduler_->SetNeedsBeginMainFrame();
2038 scheduler_->SetNeedsRedraw();
2039 EXPECT_SCOPED(AdvanceFrame());
2040 EXPECT_TRUE(scheduler_->CommitPending());
2041 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2042 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2043 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2044 scheduler_->DidSwapBuffersComplete();
2045 scheduler_->NotifyBeginMainFrameStarted();
2046 scheduler_->NotifyReadyToCommit();
2047 EXPECT_FALSE(scheduler_->CommitPending());
2048 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 6);
2049 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 6);
2050 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 6);
2051 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 6);
2052 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 6);
2053 EXPECT_ACTION("ScheduledActionCommit", client_, 5, 6);
2055 // Start another commit while we still have an active tree.
2056 client_->Reset();
2057 EXPECT_FALSE(scheduler_->CommitPending());
2058 scheduler_->SetNeedsBeginMainFrame();
2059 scheduler_->SetNeedsRedraw();
2060 EXPECT_SCOPED(AdvanceFrame());
2061 EXPECT_TRUE(scheduler_->CommitPending());
2062 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2063 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2064 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2065 scheduler_->DidSwapBuffersComplete();
2066 scheduler_->NotifyBeginMainFrameStarted();
2067 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4);
2068 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4);
2069 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4);
2070 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
2072 // Can't commit yet because there's still a pending tree.
2073 client_->Reset();
2074 scheduler_->NotifyReadyToCommit();
2075 EXPECT_NO_ACTION(client_);
2077 // Activate the pending tree, which also unblocks the commit immediately
2078 // while we are in an idle state.
2079 client_->Reset();
2080 scheduler_->NotifyReadyToActivate();
2081 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 2);
2082 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 2);
2085 TEST_F(SchedulerTest, BeginRetroFrame) {
2086 scheduler_settings_.use_external_begin_frame_source = true;
2087 SetUpScheduler(true);
2089 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2090 scheduler_->SetNeedsBeginMainFrame();
2091 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2092 client_->Reset();
2094 // Create a BeginFrame with a long deadline to avoid race conditions.
2095 // This is the first BeginFrame, which will be handled immediately.
2096 BeginFrameArgs args =
2097 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2098 args.deadline += base::TimeDelta::FromHours(1);
2099 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2100 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2101 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2102 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2103 EXPECT_TRUE(client_->needs_begin_frames());
2104 client_->Reset();
2106 // Queue BeginFrames while we are still handling the previous BeginFrame.
2107 args.frame_time += base::TimeDelta::FromSeconds(1);
2108 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2109 args.frame_time += base::TimeDelta::FromSeconds(1);
2110 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2112 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2113 task_runner().RunPendingTasks(); // Run posted deadline.
2114 EXPECT_NO_ACTION(client_);
2115 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2116 EXPECT_TRUE(client_->needs_begin_frames());
2117 client_->Reset();
2119 // NotifyReadyToCommit should trigger the commit.
2120 scheduler_->NotifyBeginMainFrameStarted();
2121 scheduler_->NotifyReadyToCommit();
2122 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2123 EXPECT_TRUE(client_->needs_begin_frames());
2124 client_->Reset();
2126 // NotifyReadyToActivate should trigger the activation.
2127 scheduler_->NotifyReadyToActivate();
2128 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2129 EXPECT_TRUE(client_->needs_begin_frames());
2130 client_->Reset();
2132 // BeginImplFrame should prepare the draw.
2133 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2134 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2135 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2136 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2137 EXPECT_TRUE(client_->needs_begin_frames());
2138 client_->Reset();
2140 // BeginImplFrame deadline should draw.
2141 task_runner().RunPendingTasks(); // Run posted deadline.
2142 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2143 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2144 EXPECT_TRUE(client_->needs_begin_frames());
2145 client_->Reset();
2147 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2148 // to avoid excessive toggles.
2149 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2150 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
2151 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2152 client_->Reset();
2154 task_runner().RunPendingTasks(); // Run posted deadline.
2155 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
2156 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2157 client_->Reset();
2160 TEST_F(SchedulerTest, BeginRetroFrame_SwapThrottled) {
2161 scheduler_settings_.use_external_begin_frame_source = true;
2162 SetUpScheduler(true);
2164 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
2166 // To test swap ack throttling, this test disables automatic swap acks.
2167 scheduler_->SetMaxSwapsPending(1);
2168 client_->SetAutomaticSwapAck(false);
2170 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2171 client_->Reset();
2172 scheduler_->SetNeedsBeginMainFrame();
2173 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2174 client_->Reset();
2176 EXPECT_SCOPED(AdvanceFrame());
2177 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2178 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2179 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2180 EXPECT_TRUE(client_->needs_begin_frames());
2181 client_->Reset();
2183 // Queue BeginFrame while we are still handling the previous BeginFrame.
2184 SendNextBeginFrame();
2185 EXPECT_NO_ACTION(client_);
2186 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2187 EXPECT_TRUE(client_->needs_begin_frames());
2188 client_->Reset();
2190 // NotifyReadyToCommit should trigger the pending commit.
2191 scheduler_->NotifyBeginMainFrameStarted();
2192 scheduler_->NotifyReadyToCommit();
2193 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2194 EXPECT_TRUE(client_->needs_begin_frames());
2195 client_->Reset();
2197 // NotifyReadyToActivate should trigger the activation and draw.
2198 scheduler_->NotifyReadyToActivate();
2199 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2200 EXPECT_TRUE(client_->needs_begin_frames());
2201 client_->Reset();
2203 // Swapping will put us into a swap throttled state.
2204 // Run posted deadline.
2205 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2206 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2207 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2208 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2209 EXPECT_TRUE(client_->needs_begin_frames());
2210 client_->Reset();
2212 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
2213 // but not a BeginMainFrame or draw.
2214 scheduler_->SetNeedsBeginMainFrame();
2215 scheduler_->SetNeedsRedraw();
2216 // Run posted BeginRetroFrame.
2217 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
2218 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2219 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2220 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2221 EXPECT_TRUE(client_->needs_begin_frames());
2222 client_->Reset();
2224 // Let time pass sufficiently beyond the regular deadline but not beyond the
2225 // late deadline.
2226 now_src()->Advance(BeginFrameArgs::DefaultInterval() -
2227 base::TimeDelta::FromMicroseconds(1));
2228 task_runner().RunUntilTime(now_src()->NowTicks());
2229 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2231 // Take us out of a swap throttled state.
2232 scheduler_->DidSwapBuffersComplete();
2233 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
2234 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2235 EXPECT_TRUE(client_->needs_begin_frames());
2236 client_->Reset();
2238 // Verify that the deadline was rescheduled.
2239 task_runner().RunUntilTime(now_src()->NowTicks());
2240 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
2241 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2242 EXPECT_TRUE(client_->needs_begin_frames());
2243 client_->Reset();
2246 TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooEarly) {
2247 scheduler_settings_.use_external_begin_frame_source = true;
2248 SetUpScheduler(true);
2250 scheduler_->SetNeedsBeginMainFrame();
2251 EXPECT_TRUE(client_->needs_begin_frames());
2252 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2254 client_->Reset();
2255 EXPECT_SCOPED(AdvanceFrame());
2256 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2257 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2258 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2260 client_->Reset();
2261 scheduler_->NotifyBeginMainFrameStarted();
2263 client_->Reset();
2264 BeginFrameArgs retro_frame_args = SendNextBeginFrame();
2265 // This BeginFrame is queued up as a retro frame.
2266 EXPECT_NO_ACTION(client_);
2267 // The previous deadline is still pending.
2268 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2270 client_->Reset();
2271 // This main frame activating should schedule the (previous) deadline to
2272 // trigger immediately.
2273 scheduler_->NotifyReadyToCommit();
2274 scheduler_->NotifyReadyToActivate();
2275 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2);
2276 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2);
2278 client_->Reset();
2279 // The deadline task should trigger causing a draw.
2280 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2281 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2282 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2283 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2285 // Keep animating.
2286 client_->Reset();
2287 scheduler_->SetNeedsAnimate();
2288 scheduler_->SetNeedsRedraw();
2289 EXPECT_NO_ACTION(client_);
2291 // Let's advance to the retro frame's deadline.
2292 now_src()->Advance(retro_frame_args.deadline - now_src()->NowTicks());
2294 // The retro frame hasn't expired yet.
2295 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
2296 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2297 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2298 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2300 // This is an immediate deadline case.
2301 client_->Reset();
2302 task_runner().RunPendingTasks();
2303 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2304 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
2307 TEST_F(SchedulerTest, RetroFrameExpiresOnTime) {
2308 scheduler_settings_.use_external_begin_frame_source = true;
2309 SetUpScheduler(true);
2311 scheduler_->SetNeedsBeginMainFrame();
2312 EXPECT_TRUE(client_->needs_begin_frames());
2313 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2315 client_->Reset();
2316 EXPECT_SCOPED(AdvanceFrame());
2317 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2318 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2319 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2321 client_->Reset();
2322 scheduler_->NotifyBeginMainFrameStarted();
2324 client_->Reset();
2325 BeginFrameArgs retro_frame_args = SendNextBeginFrame();
2326 // This BeginFrame is queued up as a retro frame.
2327 EXPECT_NO_ACTION(client_);
2328 // The previous deadline is still pending.
2329 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2331 client_->Reset();
2332 // This main frame activating should schedule the (previous) deadline to
2333 // trigger immediately.
2334 scheduler_->NotifyReadyToCommit();
2335 scheduler_->NotifyReadyToActivate();
2336 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2);
2337 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2);
2339 client_->Reset();
2340 // The deadline task should trigger causing a draw.
2341 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2342 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2343 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2344 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2346 // Keep animating.
2347 client_->Reset();
2348 scheduler_->SetNeedsAnimate();
2349 scheduler_->SetNeedsRedraw();
2350 EXPECT_NO_ACTION(client_);
2352 // Let's advance sufficiently past the retro frame's deadline.
2353 now_src()->Advance(retro_frame_args.deadline - now_src()->NowTicks() +
2354 base::TimeDelta::FromMicroseconds(1));
2356 // The retro frame should've expired.
2357 EXPECT_NO_ACTION(client_);
2360 TEST_F(SchedulerTest, MissedFrameDoesNotExpireTooEarly) {
2361 scheduler_settings_.use_external_begin_frame_source = true;
2362 SetUpScheduler(true);
2364 scheduler_->SetNeedsBeginMainFrame();
2365 EXPECT_TRUE(client_->needs_begin_frames());
2366 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2368 BeginFrameArgs missed_frame_args =
2369 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2370 missed_frame_args.type = BeginFrameArgs::MISSED;
2372 // Advance to the deadline.
2373 now_src()->Advance(missed_frame_args.deadline - now_src()->NowTicks());
2375 // Missed frame is handled because it's on time.
2376 client_->Reset();
2377 fake_external_begin_frame_source_->TestOnBeginFrame(missed_frame_args);
2378 EXPECT_TRUE(
2379 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false)));
2380 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2381 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2382 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2385 TEST_F(SchedulerTest, MissedFrameExpiresOnTime) {
2386 scheduler_settings_.use_external_begin_frame_source = true;
2387 SetUpScheduler(true);
2389 scheduler_->SetNeedsBeginMainFrame();
2390 EXPECT_TRUE(client_->needs_begin_frames());
2391 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2393 BeginFrameArgs missed_frame_args =
2394 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2395 missed_frame_args.type = BeginFrameArgs::MISSED;
2397 // Advance sufficiently past the deadline.
2398 now_src()->Advance(missed_frame_args.deadline - now_src()->NowTicks() +
2399 base::TimeDelta::FromMicroseconds(1));
2401 // Missed frame is dropped because it's too late.
2402 client_->Reset();
2403 fake_external_begin_frame_source_->TestOnBeginFrame(missed_frame_args);
2404 EXPECT_FALSE(
2405 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false)));
2406 EXPECT_NO_ACTION(client_);
2407 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2410 void SchedulerTest::BeginFramesNotFromClient(
2411 bool use_external_begin_frame_source,
2412 bool throttle_frame_production) {
2413 scheduler_settings_.use_external_begin_frame_source =
2414 use_external_begin_frame_source;
2415 scheduler_settings_.throttle_frame_production = throttle_frame_production;
2416 SetUpScheduler(true);
2418 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame
2419 // without calling SetNeedsBeginFrame.
2420 scheduler_->SetNeedsBeginMainFrame();
2421 EXPECT_NO_ACTION(client_);
2422 client_->Reset();
2424 // When the client-driven BeginFrame are disabled, the scheduler posts it's
2425 // own BeginFrame tasks.
2426 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2427 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2428 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2429 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2430 client_->Reset();
2432 // If we don't swap on the deadline, we wait for the next BeginFrame.
2433 task_runner().RunPendingTasks(); // Run posted deadline.
2434 EXPECT_NO_ACTION(client_);
2435 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2436 client_->Reset();
2438 // NotifyReadyToCommit should trigger the commit.
2439 scheduler_->NotifyBeginMainFrameStarted();
2440 scheduler_->NotifyReadyToCommit();
2441 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2442 client_->Reset();
2444 // NotifyReadyToActivate should trigger the activation.
2445 scheduler_->NotifyReadyToActivate();
2446 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2447 client_->Reset();
2449 // BeginImplFrame should prepare the draw.
2450 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2451 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2452 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2453 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2454 client_->Reset();
2456 // BeginImplFrame deadline should draw.
2457 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2458 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2459 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2460 client_->Reset();
2462 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2463 // to avoid excessive toggles.
2464 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2465 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
2466 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2467 client_->Reset();
2469 // Make sure SetNeedsBeginFrame isn't called on the client
2470 // when the BeginFrame is no longer needed.
2471 task_runner().RunPendingTasks(); // Run posted deadline.
2472 EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_);
2473 client_->Reset();
2476 TEST_F(SchedulerTest, SyntheticBeginFrames) {
2477 bool use_external_begin_frame_source = false;
2478 bool throttle_frame_production = true;
2479 BeginFramesNotFromClient(use_external_begin_frame_source,
2480 throttle_frame_production);
2483 TEST_F(SchedulerTest, VSyncThrottlingDisabled) {
2484 bool use_external_begin_frame_source = true;
2485 bool throttle_frame_production = false;
2486 BeginFramesNotFromClient(use_external_begin_frame_source,
2487 throttle_frame_production);
2490 TEST_F(SchedulerTest, SyntheticBeginFrames_And_VSyncThrottlingDisabled) {
2491 bool use_external_begin_frame_source = false;
2492 bool throttle_frame_production = false;
2493 BeginFramesNotFromClient(use_external_begin_frame_source,
2494 throttle_frame_production);
2497 void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
2498 bool use_external_begin_frame_source,
2499 bool throttle_frame_production) {
2500 scheduler_settings_.use_external_begin_frame_source =
2501 use_external_begin_frame_source;
2502 scheduler_settings_.throttle_frame_production = throttle_frame_production;
2503 SetUpScheduler(true);
2505 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
2507 // To test swap ack throttling, this test disables automatic swap acks.
2508 scheduler_->SetMaxSwapsPending(1);
2509 client_->SetAutomaticSwapAck(false);
2511 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2512 client_->Reset();
2513 scheduler_->SetNeedsBeginMainFrame();
2514 EXPECT_NO_ACTION(client_);
2515 client_->Reset();
2517 // Trigger the first BeginImplFrame and BeginMainFrame
2518 EXPECT_SCOPED(AdvanceFrame());
2519 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2520 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2521 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2522 client_->Reset();
2524 // NotifyReadyToCommit should trigger the pending commit.
2525 scheduler_->NotifyBeginMainFrameStarted();
2526 scheduler_->NotifyReadyToCommit();
2527 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2528 client_->Reset();
2530 // NotifyReadyToActivate should trigger the activation and draw.
2531 scheduler_->NotifyReadyToActivate();
2532 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2533 client_->Reset();
2535 // Swapping will put us into a swap throttled state.
2536 // Run posted deadline.
2537 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2538 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2539 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2540 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2541 client_->Reset();
2543 // While swap throttled, BeginFrames should trigger BeginImplFrames,
2544 // but not a BeginMainFrame or draw.
2545 scheduler_->SetNeedsBeginMainFrame();
2546 scheduler_->SetNeedsRedraw();
2547 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
2548 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2549 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2550 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2551 client_->Reset();
2553 // Let time pass sufficiently beyond the regular deadline but not beyond the
2554 // late deadline.
2555 now_src()->Advance(BeginFrameArgs::DefaultInterval() -
2556 base::TimeDelta::FromMicroseconds(1));
2557 task_runner().RunUntilTime(now_src()->NowTicks());
2558 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2560 // Take us out of a swap throttled state.
2561 scheduler_->DidSwapBuffersComplete();
2562 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
2563 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2564 client_->Reset();
2566 // Verify that the deadline was rescheduled.
2567 // We can't use RunUntilTime(now) here because the next frame is also
2568 // scheduled if throttle_frame_production = false.
2569 base::TimeTicks before_deadline = now_src()->NowTicks();
2570 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2571 base::TimeTicks after_deadline = now_src()->NowTicks();
2572 EXPECT_EQ(after_deadline, before_deadline);
2573 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2574 client_->Reset();
2577 TEST_F(SchedulerTest, SyntheticBeginFrames_SwapThrottled) {
2578 bool use_external_begin_frame_source = false;
2579 bool throttle_frame_production = true;
2580 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
2581 throttle_frame_production);
2584 TEST_F(SchedulerTest, VSyncThrottlingDisabled_SwapThrottled) {
2585 bool use_external_begin_frame_source = true;
2586 bool throttle_frame_production = false;
2587 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
2588 throttle_frame_production);
2591 TEST_F(SchedulerTest,
2592 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled) {
2593 bool use_external_begin_frame_source = false;
2594 bool throttle_frame_production = false;
2595 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
2596 throttle_frame_production);
2599 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized) {
2600 scheduler_settings_.use_external_begin_frame_source = true;
2601 SetUpScheduler(false);
2603 scheduler_->SetCanStart();
2604 scheduler_->SetVisible(true);
2605 scheduler_->SetCanDraw(true);
2607 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
2608 client_->Reset();
2609 scheduler_->DidCreateAndInitializeOutputSurface();
2610 EXPECT_NO_ACTION(client_);
2612 scheduler_->DidLoseOutputSurface();
2613 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
2616 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) {
2617 scheduler_settings_.use_external_begin_frame_source = true;
2618 SetUpScheduler(true);
2620 // SetNeedsBeginMainFrame should begin the frame.
2621 scheduler_->SetNeedsBeginMainFrame();
2622 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2624 client_->Reset();
2625 EXPECT_SCOPED(AdvanceFrame());
2626 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2627 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2628 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2630 client_->Reset();
2631 scheduler_->DidLoseOutputSurface();
2632 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2633 EXPECT_NO_ACTION(client_);
2635 client_->Reset();
2636 scheduler_->NotifyBeginMainFrameStarted();
2637 scheduler_->NotifyReadyToCommit();
2638 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2);
2639 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2);
2641 client_->Reset();
2642 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2643 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2644 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2645 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2648 TEST_F(SchedulerTest,
2649 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) {
2650 scheduler_settings_.use_external_begin_frame_source = true;
2651 SetUpScheduler(true);
2653 // SetNeedsBeginMainFrame should begin the frame.
2654 scheduler_->SetNeedsBeginMainFrame();
2655 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2657 client_->Reset();
2658 EXPECT_SCOPED(AdvanceFrame());
2659 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2660 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2661 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2663 client_->Reset();
2664 scheduler_->DidLoseOutputSurface();
2665 // Do nothing when impl frame is in deadine pending state.
2666 EXPECT_NO_ACTION(client_);
2668 client_->Reset();
2669 // Run posted deadline.
2670 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2671 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2672 // OnBeginImplFrameDeadline didn't schedule output surface creation because
2673 // main frame is not yet completed.
2674 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
2675 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2676 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2678 // BeginImplFrame is not started.
2679 client_->Reset();
2680 task_runner().RunUntilTime(now_src()->NowTicks() +
2681 base::TimeDelta::FromMilliseconds(10));
2682 EXPECT_NO_ACTION(client_);
2683 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2685 client_->Reset();
2686 scheduler_->NotifyBeginMainFrameStarted();
2687 scheduler_->NotifyReadyToCommit();
2688 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 3);
2689 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 3);
2690 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 2, 3);
2693 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) {
2694 scheduler_settings_.use_external_begin_frame_source = true;
2695 SetUpScheduler(true);
2697 // SetNeedsBeginMainFrame should begin the frame.
2698 scheduler_->SetNeedsBeginMainFrame();
2699 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2701 client_->Reset();
2702 EXPECT_SCOPED(AdvanceFrame());
2703 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2704 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2705 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2707 client_->Reset();
2708 scheduler_->NotifyBeginMainFrameStarted();
2709 scheduler_->NotifyReadyToCommit();
2710 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2712 client_->Reset();
2713 scheduler_->DidLoseOutputSurface();
2714 // Sync tree should be forced to activate.
2715 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2717 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2718 client_->Reset();
2719 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2720 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2721 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2722 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2725 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles) {
2726 scheduler_settings_.use_external_begin_frame_source = true;
2727 SetUpScheduler(true);
2729 scheduler_->SetNeedsPrepareTiles();
2730 scheduler_->SetNeedsRedraw();
2731 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2733 client_->Reset();
2734 EXPECT_SCOPED(AdvanceFrame());
2735 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2736 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2737 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2739 client_->Reset();
2740 scheduler_->DidLoseOutputSurface();
2741 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2742 EXPECT_NO_ACTION(client_);
2744 client_->Reset();
2745 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2746 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 0, 4);
2747 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 4);
2748 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 2, 4);
2749 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 3, 4);
2752 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) {
2753 scheduler_settings_.use_external_begin_frame_source = true;
2754 SetUpScheduler(true);
2756 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2757 scheduler_->SetNeedsBeginMainFrame();
2758 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2760 // Create a BeginFrame with a long deadline to avoid race conditions.
2761 // This is the first BeginFrame, which will be handled immediately.
2762 client_->Reset();
2763 BeginFrameArgs args =
2764 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2765 args.deadline += base::TimeDelta::FromHours(1);
2766 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2767 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2768 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2769 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2770 EXPECT_TRUE(client_->needs_begin_frames());
2772 // Queue BeginFrames while we are still handling the previous BeginFrame.
2773 args.frame_time += base::TimeDelta::FromSeconds(1);
2774 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2775 args.frame_time += base::TimeDelta::FromSeconds(1);
2776 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2778 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2779 client_->Reset();
2780 task_runner().RunPendingTasks(); // Run posted deadline.
2781 EXPECT_NO_ACTION(client_);
2782 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2783 EXPECT_TRUE(client_->needs_begin_frames());
2785 // NotifyReadyToCommit should trigger the commit.
2786 client_->Reset();
2787 scheduler_->NotifyBeginMainFrameStarted();
2788 scheduler_->NotifyReadyToCommit();
2789 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2790 EXPECT_TRUE(client_->needs_begin_frames());
2792 // NotifyReadyToActivate should trigger the activation.
2793 client_->Reset();
2794 scheduler_->NotifyReadyToActivate();
2795 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2796 EXPECT_TRUE(client_->needs_begin_frames());
2798 client_->Reset();
2799 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty());
2800 scheduler_->DidLoseOutputSurface();
2801 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2802 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2803 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2804 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty());
2806 // Posted BeginRetroFrame is aborted.
2807 client_->Reset();
2808 task_runner().RunPendingTasks();
2809 EXPECT_NO_ACTION(client_);
2812 TEST_F(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) {
2813 scheduler_settings_.use_external_begin_frame_source = true;
2814 SetUpScheduler(true);
2816 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2817 scheduler_->SetNeedsBeginMainFrame();
2818 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2820 // Create a BeginFrame with a long deadline to avoid race conditions.
2821 // This is the first BeginFrame, which will be handled immediately.
2822 client_->Reset();
2823 BeginFrameArgs args =
2824 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2825 args.deadline += base::TimeDelta::FromHours(1);
2826 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2827 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2828 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2829 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2830 EXPECT_TRUE(client_->needs_begin_frames());
2832 // Queue BeginFrames while we are still handling the previous BeginFrame.
2833 args.frame_time += base::TimeDelta::FromSeconds(1);
2834 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2835 args.frame_time += base::TimeDelta::FromSeconds(1);
2836 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2838 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2839 client_->Reset();
2840 task_runner().RunPendingTasks(); // Run posted deadline.
2841 EXPECT_NO_ACTION(client_);
2842 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2843 EXPECT_TRUE(client_->needs_begin_frames());
2845 // NotifyReadyToCommit should trigger the commit.
2846 client_->Reset();
2847 scheduler_->NotifyBeginMainFrameStarted();
2848 scheduler_->NotifyReadyToCommit();
2849 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2850 EXPECT_TRUE(client_->needs_begin_frames());
2852 // NotifyReadyToActivate should trigger the activation.
2853 client_->Reset();
2854 scheduler_->NotifyReadyToActivate();
2855 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2856 EXPECT_TRUE(client_->needs_begin_frames());
2858 // BeginImplFrame should prepare the draw.
2859 client_->Reset();
2860 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2861 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2862 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2863 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2864 EXPECT_TRUE(client_->needs_begin_frames());
2866 client_->Reset();
2867 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty());
2868 scheduler_->DidLoseOutputSurface();
2869 EXPECT_NO_ACTION(client_);
2870 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty());
2872 // BeginImplFrame deadline should abort drawing.
2873 client_->Reset();
2874 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2875 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2876 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2877 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2878 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2879 EXPECT_FALSE(client_->needs_begin_frames());
2881 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
2882 client_->Reset();
2883 task_runner().RunPendingTasks();
2884 EXPECT_NO_ACTION(client_);
2887 TEST_F(SchedulerTest, DidLoseOutputSurfaceWithSyntheticBeginFrameSource) {
2888 SetUpScheduler(true);
2890 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
2891 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2892 scheduler_->SetNeedsBeginMainFrame();
2893 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2895 client_->Reset();
2896 AdvanceFrame();
2897 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2898 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2899 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2900 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2902 // NotifyReadyToCommit should trigger the commit.
2903 client_->Reset();
2904 scheduler_->NotifyBeginMainFrameStarted();
2905 scheduler_->NotifyReadyToCommit();
2906 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2907 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2909 // NotifyReadyToActivate should trigger the activation.
2910 client_->Reset();
2911 scheduler_->NotifyReadyToActivate();
2912 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2913 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2915 client_->Reset();
2916 scheduler_->DidLoseOutputSurface();
2917 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2918 EXPECT_NO_ACTION(client_);
2919 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2921 client_->Reset();
2922 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2923 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 2);
2924 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2925 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2928 TEST_F(SchedulerTest, DidLoseOutputSurfaceWhenIdle) {
2929 scheduler_settings_.use_external_begin_frame_source = true;
2930 SetUpScheduler(true);
2932 // SetNeedsBeginMainFrame should begin the frame.
2933 scheduler_->SetNeedsBeginMainFrame();
2934 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2936 client_->Reset();
2937 EXPECT_SCOPED(AdvanceFrame());
2938 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2939 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2940 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2942 client_->Reset();
2943 scheduler_->NotifyBeginMainFrameStarted();
2944 scheduler_->NotifyReadyToCommit();
2945 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2947 client_->Reset();
2948 scheduler_->NotifyReadyToActivate();
2949 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2951 client_->Reset();
2952 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2953 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2954 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2956 // Idle time between BeginFrames.
2957 client_->Reset();
2958 scheduler_->DidLoseOutputSurface();
2959 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2960 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2961 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2964 TEST_F(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) {
2965 scheduler_settings_.use_external_begin_frame_source = true;
2966 SetUpScheduler(true);
2968 // SetNeedsBeginMainFrame should begin the frame.
2969 scheduler_->SetNeedsBeginMainFrame();
2970 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2972 client_->Reset();
2973 EXPECT_SCOPED(AdvanceFrame());
2974 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2975 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2976 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2978 client_->Reset();
2979 scheduler_->NotifyBeginMainFrameStarted();
2980 scheduler_->NotifyReadyToCommit();
2981 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2982 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2984 client_->Reset();
2985 scheduler_->SetVisible(false);
2986 task_runner().RunPendingTasks(); // Run posted deadline.
2988 // Sync tree should be forced to activate.
2989 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 3);
2990 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2991 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2994 // Tests to ensure frame sources can be successfully changed while drawing.
2995 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottled) {
2996 scheduler_settings_.use_external_begin_frame_source = true;
2997 SetUpScheduler(true);
2999 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
3000 scheduler_->SetNeedsRedraw();
3001 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3002 client_->Reset();
3004 EXPECT_SCOPED(AdvanceFrame());
3005 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3006 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
3007 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3008 EXPECT_TRUE(client_->needs_begin_frames());
3009 client_->Reset();
3010 task_runner().RunPendingTasks(); // Run posted deadline.
3011 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
3012 scheduler_->SetNeedsRedraw();
3014 // Switch to an unthrottled frame source.
3015 scheduler_->SetThrottleFrameProduction(false);
3016 client_->Reset();
3018 // Unthrottled frame source will immediately begin a new frame.
3019 task_runner().RunPendingTasks(); // Run posted BeginFrame.
3020 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3021 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
3022 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3023 client_->Reset();
3025 // If we don't swap on the deadline, we wait for the next BeginFrame.
3026 task_runner().RunPendingTasks(); // Run posted deadline.
3027 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
3028 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3029 client_->Reset();
3032 // Tests to ensure frame sources can be successfully changed while a frame
3033 // deadline is pending.
3034 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottledBeforeDeadline) {
3035 scheduler_settings_.use_external_begin_frame_source = true;
3036 SetUpScheduler(true);
3038 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
3039 scheduler_->SetNeedsRedraw();
3040 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3041 client_->Reset();
3043 EXPECT_SCOPED(AdvanceFrame());
3044 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3045 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
3047 // Switch to an unthrottled frame source before the frame deadline is hit.
3048 scheduler_->SetThrottleFrameProduction(false);
3049 client_->Reset();
3051 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3052 EXPECT_TRUE(client_->needs_begin_frames());
3053 client_->Reset();
3055 task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame.
3056 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
3057 // Unthrottled frame source will immediately begin a new frame.
3058 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 2);
3059 scheduler_->SetNeedsRedraw();
3060 client_->Reset();
3062 task_runner().RunPendingTasks(); // Run posted deadline.
3063 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
3064 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
3065 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3066 client_->Reset();
3069 // Tests to ensure that the active frame source can successfully be changed from
3070 // unthrottled to throttled.
3071 TEST_F(SchedulerTest, SwitchFrameSourceToThrottled) {
3072 scheduler_settings_.throttle_frame_production = false;
3073 scheduler_settings_.use_external_begin_frame_source = true;
3074 SetUpScheduler(true);
3076 scheduler_->SetNeedsRedraw();
3077 EXPECT_NO_ACTION(client_);
3078 client_->Reset();
3080 task_runner().RunPendingTasks(); // Run posted BeginFrame.
3081 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3082 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
3083 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3084 client_->Reset();
3086 task_runner().RunPendingTasks(); // Run posted deadline.
3087 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
3088 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3089 client_->Reset();
3091 // Switch to a throttled frame source.
3092 scheduler_->SetThrottleFrameProduction(true);
3093 client_->Reset();
3095 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
3096 scheduler_->SetNeedsRedraw();
3097 task_runner().RunPendingTasks();
3098 EXPECT_NO_ACTION(client_);
3099 client_->Reset();
3101 EXPECT_SCOPED(AdvanceFrame());
3102 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3103 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
3104 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3105 EXPECT_TRUE(client_->needs_begin_frames());
3106 client_->Reset();
3107 task_runner().RunPendingTasks(); // Run posted deadline.
3108 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
3111 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
3112 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon) {
3113 scheduler_settings_.use_external_begin_frame_source = true;
3114 SetUpScheduler(true);
3116 // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame.
3117 scheduler_->SetNeedsBeginMainFrame();
3118 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3119 client_->Reset();
3121 // Trigger a frame draw.
3122 EXPECT_SCOPED(AdvanceFrame());
3123 scheduler_->NotifyBeginMainFrameStarted();
3124 scheduler_->NotifyReadyToCommit();
3125 scheduler_->NotifyReadyToActivate();
3126 task_runner().RunPendingTasks();
3127 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 6);
3128 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 6);
3129 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 6);
3130 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 3, 6);
3131 EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 6);
3132 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 5, 6);
3133 client_->Reset();
3135 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
3136 // and send a SendBeginMainFrameNotExpectedSoon.
3137 EXPECT_SCOPED(AdvanceFrame());
3138 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
3139 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
3140 client_->Reset();
3142 task_runner().RunPendingTasks(); // Run posted deadline.
3143 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
3144 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
3145 client_->Reset();
3148 TEST_F(SchedulerTest, SynchronousCompositorAnimation) {
3149 scheduler_settings_.using_synchronous_renderer_compositor = true;
3150 scheduler_settings_.use_external_begin_frame_source = true;
3151 SetUpScheduler(true);
3153 scheduler_->SetNeedsAnimate();
3154 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3155 client_->Reset();
3157 // Next vsync.
3158 AdvanceFrame();
3159 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3160 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3161 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3162 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3163 client_->Reset();
3165 // Continue with animation.
3166 scheduler_->SetNeedsAnimate();
3167 EXPECT_NO_ACTION(client_);
3169 // Android onDraw.
3170 scheduler_->SetNeedsRedraw();
3171 scheduler_->OnDrawForOutputSurface();
3172 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
3173 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3174 client_->Reset();
3176 // Next vsync.
3177 AdvanceFrame();
3178 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3179 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3180 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3181 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3182 client_->Reset();
3184 // Android onDraw.
3185 scheduler_->SetNeedsRedraw();
3186 scheduler_->OnDrawForOutputSurface();
3187 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
3188 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3189 client_->Reset();
3191 // Idle on next vsync.
3192 AdvanceFrame();
3193 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3194 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
3195 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
3196 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3197 client_->Reset();
3200 TEST_F(SchedulerTest, SynchronousCompositorOnDrawDuringIdle) {
3201 scheduler_settings_.using_synchronous_renderer_compositor = true;
3202 scheduler_settings_.use_external_begin_frame_source = true;
3203 SetUpScheduler(true);
3205 scheduler_->SetNeedsRedraw();
3206 scheduler_->OnDrawForOutputSurface();
3207 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3);
3208 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3209 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3);
3210 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3211 client_->Reset();
3213 // Idle on next vsync.
3214 AdvanceFrame();
3215 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3216 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
3217 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
3218 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3219 client_->Reset();
3222 TEST_F(SchedulerTest, SynchronousCompositorCommit) {
3223 scheduler_settings_.using_synchronous_renderer_compositor = true;
3224 scheduler_settings_.use_external_begin_frame_source = true;
3225 SetUpScheduler(true);
3227 scheduler_->SetNeedsBeginMainFrame();
3228 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3229 client_->Reset();
3231 // Next vsync.
3232 AdvanceFrame();
3233 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3234 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
3235 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3236 client_->Reset();
3238 scheduler_->NotifyBeginMainFrameStarted();
3239 EXPECT_NO_ACTION(client_);
3241 // Next vsync.
3242 AdvanceFrame();
3243 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
3244 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3245 client_->Reset();
3247 scheduler_->NotifyReadyToCommit();
3248 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
3249 client_->Reset();
3251 scheduler_->NotifyReadyToActivate();
3252 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
3253 client_->Reset();
3255 // Next vsync.
3256 AdvanceFrame();
3257 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3258 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3259 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3260 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3261 client_->Reset();
3263 // Android onDraw.
3264 scheduler_->SetNeedsRedraw();
3265 scheduler_->OnDrawForOutputSurface();
3266 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
3267 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3268 client_->Reset();
3270 // Idle on next vsync.
3271 AdvanceFrame();
3272 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3273 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
3274 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
3275 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3276 client_->Reset();
3279 TEST_F(SchedulerTest, SynchronousCompositorDoubleCommitWithoutDraw) {
3280 scheduler_settings_.using_synchronous_renderer_compositor = true;
3281 scheduler_settings_.use_external_begin_frame_source = true;
3282 SetUpScheduler(true);
3284 scheduler_->SetNeedsBeginMainFrame();
3285 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3286 client_->Reset();
3288 // Next vsync.
3289 AdvanceFrame();
3290 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
3291 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
3292 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3293 client_->Reset();
3295 scheduler_->NotifyBeginMainFrameStarted();
3296 EXPECT_NO_ACTION(client_);
3298 scheduler_->NotifyReadyToCommit();
3299 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
3300 client_->Reset();
3302 scheduler_->NotifyReadyToActivate();
3303 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
3304 client_->Reset();
3306 // Ask for another commit.
3307 scheduler_->SetNeedsBeginMainFrame();
3309 AdvanceFrame();
3310 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4);
3311 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4);
3312 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4);
3313 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 3, 4);
3314 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3315 client_->Reset();
3317 scheduler_->NotifyBeginMainFrameStarted();
3318 EXPECT_NO_ACTION(client_);
3320 // Allow new commit even though previous commit hasn't been drawn.
3321 scheduler_->NotifyReadyToCommit();
3322 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
3323 client_->Reset();
3326 class SchedulerClientSetNeedsPrepareTilesOnDraw : public FakeSchedulerClient {
3327 public:
3328 SchedulerClientSetNeedsPrepareTilesOnDraw() : FakeSchedulerClient() {}
3330 protected:
3331 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
3332 scheduler_->SetNeedsPrepareTiles();
3333 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
3337 TEST_F(SchedulerTest, SynchronousCompositorPrepareTilesOnDraw) {
3338 scheduler_settings_.using_synchronous_renderer_compositor = true;
3339 scheduler_settings_.use_external_begin_frame_source = true;
3341 scoped_ptr<FakeSchedulerClient> client =
3342 make_scoped_ptr(new SchedulerClientSetNeedsPrepareTilesOnDraw);
3343 SetUpScheduler(client.Pass(), true);
3345 scheduler_->SetNeedsRedraw();
3346 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3347 client_->Reset();
3349 // Next vsync.
3350 EXPECT_SCOPED(AdvanceFrame());
3351 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3352 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3353 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3354 client_->Reset();
3356 // Android onDraw.
3357 scheduler_->SetNeedsRedraw();
3358 scheduler_->OnDrawForOutputSurface();
3359 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
3360 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 1, 2);
3361 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3362 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3363 client_->Reset();
3365 // Android onDraw.
3366 scheduler_->SetNeedsRedraw();
3367 scheduler_->OnDrawForOutputSurface();
3368 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
3369 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 1, 2);
3370 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3371 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3372 client_->Reset();
3374 // Next vsync.
3375 EXPECT_SCOPED(AdvanceFrame());
3376 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3377 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3378 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
3379 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
3380 EXPECT_FALSE(client_->needs_begin_frames());
3381 client_->Reset();
3384 TEST_F(SchedulerTest, SynchronousCompositorSendBeginMainFrameWhileIdle) {
3385 scheduler_settings_.using_synchronous_renderer_compositor = true;
3386 scheduler_settings_.use_external_begin_frame_source = true;
3388 SetUpScheduler(true);
3390 scheduler_->SetNeedsRedraw();
3391 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
3392 client_->Reset();
3394 // Next vsync.
3395 EXPECT_SCOPED(AdvanceFrame());
3396 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3397 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3398 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3399 client_->Reset();
3401 // Android onDraw.
3402 scheduler_->SetNeedsRedraw();
3403 scheduler_->OnDrawForOutputSurface();
3404 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
3405 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3406 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3407 client_->Reset();
3409 // Simulate SetNeedsBeginMainFrame due to input event.
3410 scheduler_->SetNeedsBeginMainFrame();
3411 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
3412 client_->Reset();
3414 scheduler_->NotifyBeginMainFrameStarted();
3415 scheduler_->NotifyReadyToCommit();
3416 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
3417 client_->Reset();
3419 scheduler_->NotifyReadyToActivate();
3420 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
3421 client_->Reset();
3423 // Next vsync.
3424 EXPECT_SCOPED(AdvanceFrame());
3425 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
3426 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
3427 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
3428 client_->Reset();
3430 // Android onDraw.
3431 scheduler_->SetNeedsRedraw();
3432 scheduler_->OnDrawForOutputSurface();
3433 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
3434 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
3435 EXPECT_FALSE(scheduler_->PrepareTilesPending());
3436 client_->Reset();
3438 // Simulate SetNeedsBeginMainFrame due to input event.
3439 scheduler_->SetNeedsBeginMainFrame();
3440 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
3441 client_->Reset();
3444 TEST_F(SchedulerTest, AuthoritativeVSyncInterval) {
3445 SetUpScheduler(true);
3446 base::TimeDelta initial_interval = scheduler_->BeginImplFrameInterval();
3447 base::TimeDelta authoritative_interval =
3448 base::TimeDelta::FromMilliseconds(33);
3450 scheduler_->SetNeedsBeginMainFrame();
3451 EXPECT_SCOPED(AdvanceFrame());
3453 EXPECT_EQ(initial_interval, scheduler_->BeginImplFrameInterval());
3455 scheduler_->NotifyBeginMainFrameStarted();
3456 scheduler_->NotifyReadyToCommit();
3457 scheduler_->NotifyReadyToActivate();
3458 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
3460 scheduler_->SetAuthoritativeVSyncInterval(authoritative_interval);
3462 EXPECT_SCOPED(AdvanceFrame());
3464 // At the next BeginFrame, authoritative interval is used instead of previous
3465 // interval.
3466 EXPECT_NE(initial_interval, scheduler_->BeginImplFrameInterval());
3467 EXPECT_EQ(authoritative_interval, scheduler_->BeginImplFrameInterval());
3470 TEST_F(SchedulerTest, ImplLatencyTakesPriority) {
3471 SetUpScheduler(true);
3472 scheduler_->SetImplLatencyTakesPriority(true);
3473 EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority());
3475 scheduler_->SetImplLatencyTakesPriority(false);
3476 EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority());
3479 TEST_F(SchedulerTest, BeginFrameArgs_OnCriticalPath) {
3480 scheduler_settings_.use_external_begin_frame_source = true;
3481 SetUpScheduler(true);
3483 scheduler_->SetImplLatencyTakesPriority(false);
3484 scheduler_->SetChildrenNeedBeginFrames(true);
3486 EXPECT_SCOPED(AdvanceFrame());
3487 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
3488 EXPECT_TRUE(client_->begin_frame_args_sent_to_children().on_critical_path);
3491 TEST_F(SchedulerTest, BeginFrameArgs_NotOnCriticalPath) {
3492 scheduler_settings_.use_external_begin_frame_source = true;
3493 SetUpScheduler(true);
3495 scheduler_->SetImplLatencyTakesPriority(true);
3496 scheduler_->SetChildrenNeedBeginFrames(true);
3498 EXPECT_SCOPED(AdvanceFrame());
3499 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
3500 EXPECT_FALSE(client_->begin_frame_args_sent_to_children().on_critical_path);
3503 } // namespace
3504 } // namespace cc