Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / cc / scheduler / scheduler_unittest.cc
blobeaa013861fb9263ed3d4b96fa383bb5a64b0547b
1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/scheduler/scheduler.h"
7 #include <string>
8 #include <vector>
10 #include "base/logging.h"
11 #include "base/memory/scoped_vector.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "base/time/time.h"
15 #include "base/trace_event/trace_event.h"
16 #include "cc/test/begin_frame_args_test.h"
17 #include "cc/test/ordered_simple_task_runner.h"
18 #include "cc/test/scheduler_test_common.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
23 do { \
24 EXPECT_EQ(expected_num_actions, client->num_actions_()); \
25 if (action_index >= 0) { \
26 ASSERT_LT(action_index, client->num_actions_()) << scheduler_.get(); \
27 EXPECT_STREQ(action, client->Action(action_index)); \
28 } \
29 for (int i = expected_num_actions; i < client->num_actions_(); ++i) \
30 ADD_FAILURE() << "Unexpected action: " << client->Action(i) \
31 << " with state:\n" << client->StateForAction(i); \
32 } while (false)
34 #define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0)
36 #define EXPECT_SINGLE_ACTION(action, client) \
37 EXPECT_ACTION(action, client, 0, 1)
39 #define EXPECT_SCOPED(statements) \
40 { \
41 SCOPED_TRACE(""); \
42 statements; \
45 namespace cc {
46 namespace {
48 class FakeSchedulerClient : public SchedulerClient {
49 public:
50 FakeSchedulerClient()
51 : automatic_swap_ack_(true),
52 scheduler_(nullptr) {
53 Reset();
56 void Reset() {
57 actions_.clear();
58 states_.clear();
59 draw_will_happen_ = true;
60 swap_will_happen_if_draw_happens_ = true;
61 num_draws_ = 0;
62 log_anticipated_draw_time_change_ = false;
63 begin_frame_args_sent_to_children_ = BeginFrameArgs();
66 void set_scheduler(TestScheduler* scheduler) { scheduler_ = scheduler; }
68 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
69 // for tests that do.
70 void set_log_anticipated_draw_time_change(bool log) {
71 log_anticipated_draw_time_change_ = log;
73 bool needs_begin_frames() {
74 return scheduler_->frame_source().NeedsBeginFrames();
76 int num_draws() const { return num_draws_; }
77 int num_actions_() const { return static_cast<int>(actions_.size()); }
78 const char* Action(int i) const { return actions_[i]; }
79 std::string StateForAction(int i) const { return states_[i]->ToString(); }
80 base::TimeTicks posted_begin_impl_frame_deadline() const {
81 return posted_begin_impl_frame_deadline_;
84 int ActionIndex(const char* action) const {
85 for (size_t i = 0; i < actions_.size(); i++)
86 if (!strcmp(actions_[i], action))
87 return i;
88 return -1;
91 bool HasAction(const char* action) const {
92 return ActionIndex(action) >= 0;
95 void SetDrawWillHappen(bool draw_will_happen) {
96 draw_will_happen_ = draw_will_happen;
98 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
99 swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
101 void SetAutomaticSwapAck(bool automatic_swap_ack) {
102 automatic_swap_ack_ = automatic_swap_ack;
104 // SchedulerClient implementation.
105 void WillBeginImplFrame(const BeginFrameArgs& args) override {
106 PushAction("WillBeginImplFrame");
108 void DidFinishImplFrame() override {}
110 void ScheduledActionSendBeginMainFrame() override {
111 PushAction("ScheduledActionSendBeginMainFrame");
113 void ScheduledActionAnimate() override {
114 PushAction("ScheduledActionAnimate");
116 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
117 PushAction("ScheduledActionDrawAndSwapIfPossible");
118 num_draws_++;
119 DrawResult result =
120 draw_will_happen_ ? DRAW_SUCCESS : DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
121 bool swap_will_happen =
122 draw_will_happen_ && swap_will_happen_if_draw_happens_;
123 if (swap_will_happen) {
124 scheduler_->DidSwapBuffers();
126 if (automatic_swap_ack_)
127 scheduler_->DidSwapBuffersComplete();
129 return result;
131 DrawResult ScheduledActionDrawAndSwapForced() override {
132 PushAction("ScheduledActionDrawAndSwapForced");
133 return DRAW_SUCCESS;
135 void ScheduledActionCommit() override { PushAction("ScheduledActionCommit"); }
136 void ScheduledActionActivateSyncTree() override {
137 PushAction("ScheduledActionActivateSyncTree");
139 void ScheduledActionBeginOutputSurfaceCreation() override {
140 PushAction("ScheduledActionBeginOutputSurfaceCreation");
142 void ScheduledActionPrepareTiles() override {
143 PushAction("ScheduledActionPrepareTiles");
145 void ScheduledActionInvalidateOutputSurface() override {
146 actions_.push_back("ScheduledActionInvalidateOutputSurface");
147 states_.push_back(scheduler_->AsValue());
149 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {
150 if (log_anticipated_draw_time_change_)
151 PushAction("DidAnticipatedDrawTimeChange");
153 base::TimeDelta DrawDurationEstimate() override { return base::TimeDelta(); }
154 base::TimeDelta BeginMainFrameToCommitDurationEstimate() override {
155 return base::TimeDelta();
157 base::TimeDelta CommitToActivateDurationEstimate() override {
158 return base::TimeDelta();
161 void SendBeginFramesToChildren(const BeginFrameArgs& args) override {
162 begin_frame_args_sent_to_children_ = args;
165 void SendBeginMainFrameNotExpectedSoon() override {
166 PushAction("SendBeginMainFrameNotExpectedSoon");
169 base::Callback<bool(void)> ImplFrameDeadlinePending(bool state) {
170 return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback,
171 base::Unretained(this),
172 state);
175 bool begin_frame_is_sent_to_children() const {
176 return begin_frame_args_sent_to_children_.IsValid();
179 const BeginFrameArgs& begin_frame_args_sent_to_children() const {
180 return begin_frame_args_sent_to_children_;
183 void PushAction(const char* description) {
184 actions_.push_back(description);
185 states_.push_back(scheduler_->AsValue());
188 protected:
189 bool ImplFrameDeadlinePendingCallback(bool state) {
190 return scheduler_->BeginImplFrameDeadlinePending() == state;
193 bool draw_will_happen_;
194 bool swap_will_happen_if_draw_happens_;
195 bool automatic_swap_ack_;
196 int num_draws_;
197 bool log_anticipated_draw_time_change_;
198 BeginFrameArgs begin_frame_args_sent_to_children_;
199 base::TimeTicks posted_begin_impl_frame_deadline_;
200 std::vector<const char*> actions_;
201 std::vector<scoped_refptr<base::trace_event::ConvertableToTraceFormat>>
202 states_;
203 TestScheduler* scheduler_;
206 class SchedulerClientWithFixedEstimates : public FakeSchedulerClient {
207 public:
208 SchedulerClientWithFixedEstimates(
209 base::TimeDelta draw_duration,
210 base::TimeDelta begin_main_frame_to_commit_duration,
211 base::TimeDelta commit_to_activate_duration)
212 : draw_duration_(draw_duration),
213 begin_main_frame_to_commit_duration_(
214 begin_main_frame_to_commit_duration),
215 commit_to_activate_duration_(commit_to_activate_duration) {}
217 base::TimeDelta DrawDurationEstimate() override { return draw_duration_; }
218 base::TimeDelta BeginMainFrameToCommitDurationEstimate() override {
219 return begin_main_frame_to_commit_duration_;
221 base::TimeDelta CommitToActivateDurationEstimate() override {
222 return commit_to_activate_duration_;
225 private:
226 base::TimeDelta draw_duration_;
227 base::TimeDelta begin_main_frame_to_commit_duration_;
228 base::TimeDelta commit_to_activate_duration_;
231 class FakeExternalBeginFrameSource : public BeginFrameSourceMixIn {
232 public:
233 explicit FakeExternalBeginFrameSource(FakeSchedulerClient* client)
234 : client_(client) {}
235 ~FakeExternalBeginFrameSource() override {}
237 void OnNeedsBeginFramesChange(bool needs_begin_frames) override {
238 if (needs_begin_frames) {
239 client_->PushAction("SetNeedsBeginFrames(true)");
240 } else {
241 client_->PushAction("SetNeedsBeginFrames(false)");
245 void TestOnBeginFrame(const BeginFrameArgs& args) {
246 return CallOnBeginFrame(args);
249 private:
250 FakeSchedulerClient* client_;
253 class SchedulerTest : public testing::Test {
254 public:
255 SchedulerTest()
256 : now_src_(TestNowSource::Create()),
257 task_runner_(new OrderedSimpleTaskRunner(now_src_, true)),
258 fake_external_begin_frame_source_(nullptr) {
259 // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval()
260 now_src_->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
261 // Fail if we need to run 100 tasks in a row.
262 task_runner_->SetRunTaskLimit(100);
265 ~SchedulerTest() override {}
267 protected:
268 TestScheduler* CreateScheduler() {
269 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source;
270 if (scheduler_settings_.use_external_begin_frame_source) {
271 fake_external_begin_frame_source.reset(
272 new FakeExternalBeginFrameSource(client_.get()));
273 fake_external_begin_frame_source_ =
274 fake_external_begin_frame_source.get();
276 scheduler_ = TestScheduler::Create(now_src_, client_.get(),
277 scheduler_settings_, 0, task_runner_,
278 fake_external_begin_frame_source.Pass());
279 DCHECK(scheduler_);
280 client_->set_scheduler(scheduler_.get());
281 return scheduler_.get();
284 void CreateSchedulerAndInitSurface() {
285 CreateScheduler();
286 EXPECT_SCOPED(InitializeOutputSurfaceAndFirstCommit());
289 void SetUpScheduler(bool initSurface) {
290 SetUpScheduler(make_scoped_ptr(new FakeSchedulerClient), initSurface);
293 void SetUpScheduler(scoped_ptr<FakeSchedulerClient> client,
294 bool initSurface) {
295 client_ = client.Pass();
296 if (initSurface)
297 CreateSchedulerAndInitSurface();
298 else
299 CreateScheduler();
302 OrderedSimpleTaskRunner& task_runner() { return *task_runner_; }
303 TestNowSource* now_src() { return now_src_.get(); }
305 // As this function contains EXPECT macros, to allow debugging it should be
306 // called inside EXPECT_SCOPED like so;
307 // EXPECT_SCOPED(client.InitializeOutputSurfaceAndFirstCommit(scheduler));
308 void InitializeOutputSurfaceAndFirstCommit() {
309 TRACE_EVENT0("cc",
310 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit");
311 DCHECK(scheduler_);
313 // Check the client doesn't have any actions queued when calling this
314 // function.
315 EXPECT_NO_ACTION(client_);
316 EXPECT_FALSE(client_->needs_begin_frames());
318 // Start the initial output surface creation.
319 EXPECT_FALSE(scheduler_->CanStart());
320 scheduler_->SetCanStart();
321 scheduler_->SetVisible(true);
322 scheduler_->SetCanDraw(true);
323 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
325 client_->Reset();
327 // We don't see anything happening until the first impl frame.
328 scheduler_->DidCreateAndInitializeOutputSurface();
329 scheduler_->SetNeedsCommit();
330 EXPECT_TRUE(client_->needs_begin_frames());
331 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
332 client_->Reset();
335 SCOPED_TRACE("Do first frame to commit after initialize.");
336 AdvanceFrame();
338 scheduler_->NotifyBeginMainFrameStarted();
339 scheduler_->NotifyReadyToCommitThenActivateIfNeeded();
341 EXPECT_FALSE(scheduler_->CommitPending());
343 if (scheduler_settings_.using_synchronous_renderer_compositor) {
344 scheduler_->SetNeedsRedraw();
345 scheduler_->OnDrawForOutputSurface();
346 } else {
347 // Run the posted deadline task.
348 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
349 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
352 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
355 client_->Reset();
358 SCOPED_TRACE(
359 "Run second frame so Scheduler calls SetNeedsBeginFrame(false).");
360 AdvanceFrame();
362 if (!scheduler_settings_.using_synchronous_renderer_compositor) {
363 // Run the posted deadline task.
364 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
365 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
368 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
371 EXPECT_FALSE(client_->needs_begin_frames());
372 client_->Reset();
375 // As this function contains EXPECT macros, to allow debugging it should be
376 // called inside EXPECT_SCOPED like so;
377 // EXPECT_SCOPED(client.AdvanceFrame());
378 void AdvanceFrame() {
379 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
380 "FakeSchedulerClient::AdvanceFrame");
381 // Consume any previous deadline first, if no deadline is currently
382 // pending, ImplFrameDeadlinePending will return false straight away and we
383 // will run no tasks.
384 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
385 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
387 // Send the next BeginFrame message if using an external source, otherwise
388 // it will be already in the task queue.
389 if (scheduler_->settings().use_external_begin_frame_source &&
390 scheduler_->FrameProductionThrottled()) {
391 EXPECT_TRUE(client_->needs_begin_frames());
392 SendNextBeginFrame();
395 if (!scheduler_->settings().using_synchronous_renderer_compositor) {
396 // Then run tasks until new deadline is scheduled.
397 EXPECT_TRUE(task_runner_->RunTasksWhile(
398 client_->ImplFrameDeadlinePending(false)));
399 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
403 BeginFrameArgs SendNextBeginFrame() {
404 DCHECK(scheduler_->settings().use_external_begin_frame_source);
405 // Creep the time forward so that any BeginFrameArgs is not equal to the
406 // last one otherwise we violate the BeginFrameSource contract.
407 now_src_->AdvanceNow(BeginFrameArgs::DefaultInterval());
408 BeginFrameArgs args =
409 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
410 fake_external_begin_frame_source_->TestOnBeginFrame(args);
411 return args;
414 FakeExternalBeginFrameSource* fake_external_begin_frame_source() const {
415 return fake_external_begin_frame_source_;
418 void MainFrameInHighLatencyMode(
419 int64 begin_main_frame_to_commit_estimate_in_ms,
420 int64 commit_to_activate_estimate_in_ms,
421 bool impl_latency_takes_priority,
422 bool should_send_begin_main_frame);
423 void BeginFramesNotFromClient(bool use_external_begin_frame_source,
424 bool throttle_frame_production);
425 void BeginFramesNotFromClient_SwapThrottled(
426 bool use_external_begin_frame_source,
427 bool throttle_frame_production);
428 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
429 bool impl_side_painting);
430 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting);
432 scoped_refptr<TestNowSource> now_src_;
433 scoped_refptr<OrderedSimpleTaskRunner> task_runner_;
434 FakeExternalBeginFrameSource* fake_external_begin_frame_source_;
435 SchedulerSettings scheduler_settings_;
436 scoped_ptr<FakeSchedulerClient> client_;
437 scoped_ptr<TestScheduler> scheduler_;
440 TEST_F(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) {
441 scheduler_settings_.use_external_begin_frame_source = true;
442 SetUpScheduler(false);
443 scheduler_->SetCanStart();
444 scheduler_->SetVisible(true);
445 scheduler_->SetCanDraw(true);
447 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
448 client_->Reset();
449 scheduler_->DidCreateAndInitializeOutputSurface();
450 EXPECT_NO_ACTION(client_);
453 TEST_F(SchedulerTest, SendBeginFramesToChildren) {
454 scheduler_settings_.use_external_begin_frame_source = true;
455 SetUpScheduler(true);
457 EXPECT_FALSE(client_->begin_frame_is_sent_to_children());
458 scheduler_->SetNeedsCommit();
459 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
460 EXPECT_TRUE(client_->needs_begin_frames());
462 scheduler_->SetChildrenNeedBeginFrames(true);
464 client_->Reset();
465 EXPECT_SCOPED(AdvanceFrame());
466 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
467 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
468 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
469 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
470 EXPECT_TRUE(client_->needs_begin_frames());
473 TEST_F(SchedulerTest, SendBeginFramesToChildrenWithoutCommit) {
474 scheduler_settings_.use_external_begin_frame_source = true;
475 SetUpScheduler(true);
477 EXPECT_FALSE(client_->needs_begin_frames());
478 scheduler_->SetChildrenNeedBeginFrames(true);
479 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
480 EXPECT_TRUE(client_->needs_begin_frames());
482 client_->Reset();
483 EXPECT_SCOPED(AdvanceFrame());
484 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
487 TEST_F(SchedulerTest, SendBeginFramesToChildrenDeadlineNotAdjusted) {
488 // Set up client with specified estimates.
489 SchedulerClientWithFixedEstimates* client =
490 new SchedulerClientWithFixedEstimates(
491 base::TimeDelta::FromMilliseconds(1),
492 base::TimeDelta::FromMilliseconds(2),
493 base::TimeDelta::FromMilliseconds(4));
494 scheduler_settings_.use_external_begin_frame_source = true;
495 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
497 EXPECT_FALSE(client_->needs_begin_frames());
498 scheduler_->SetChildrenNeedBeginFrames(true);
499 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
500 EXPECT_TRUE(client_->needs_begin_frames());
502 client_->Reset();
504 BeginFrameArgs frame_args =
505 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
506 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args);
508 EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
509 EXPECT_EQ(client_->begin_frame_args_sent_to_children().deadline,
510 frame_args.deadline);
513 TEST_F(SchedulerTest, VideoNeedsBeginFrames) {
514 scheduler_settings_.use_external_begin_frame_source = true;
515 SetUpScheduler(true);
517 scheduler_->SetVideoNeedsBeginFrames(true);
518 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
519 EXPECT_TRUE(client_->needs_begin_frames());
521 client_->Reset();
522 EXPECT_SCOPED(AdvanceFrame());
523 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
524 // WillBeginImplFrame is responsible for sending BeginFrames to video.
525 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
527 client_->Reset();
528 EXPECT_SCOPED(AdvanceFrame());
529 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
530 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
532 client_->Reset();
533 scheduler_->SetVideoNeedsBeginFrames(false);
534 EXPECT_NO_ACTION(client_);
536 client_->Reset();
537 task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
538 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
539 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
540 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
541 EXPECT_FALSE(client_->needs_begin_frames());
544 TEST_F(SchedulerTest, RequestCommit) {
545 scheduler_settings_.use_external_begin_frame_source = true;
546 SetUpScheduler(true);
548 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
549 scheduler_->SetNeedsCommit();
550 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
551 client_->Reset();
553 EXPECT_SCOPED(AdvanceFrame());
554 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
555 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
556 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
557 EXPECT_TRUE(client_->needs_begin_frames());
558 client_->Reset();
560 // If we don't swap on the deadline, we wait for the next BeginFrame.
561 task_runner().RunPendingTasks(); // Run posted deadline.
562 EXPECT_NO_ACTION(client_);
563 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
564 EXPECT_TRUE(client_->needs_begin_frames());
565 client_->Reset();
567 // NotifyReadyToCommit should trigger the commit.
568 scheduler_->NotifyBeginMainFrameStarted();
569 scheduler_->NotifyReadyToCommit();
570 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
571 EXPECT_TRUE(client_->needs_begin_frames());
572 client_->Reset();
574 // BeginImplFrame should prepare the draw.
575 EXPECT_SCOPED(AdvanceFrame());
576 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
577 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
578 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
579 EXPECT_TRUE(client_->needs_begin_frames());
580 client_->Reset();
582 // BeginImplFrame deadline should draw.
583 task_runner().RunPendingTasks(); // Run posted deadline.
584 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
585 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
586 EXPECT_TRUE(client_->needs_begin_frames());
587 client_->Reset();
589 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
590 // to avoid excessive toggles.
591 EXPECT_SCOPED(AdvanceFrame());
592 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
593 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
594 client_->Reset();
596 task_runner().RunPendingTasks(); // Run posted deadline.
597 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
598 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
599 client_->Reset();
602 TEST_F(SchedulerTest, RequestCommitAfterSetDeferCommit) {
603 scheduler_settings_.use_external_begin_frame_source = true;
604 SetUpScheduler(true);
606 scheduler_->SetDeferCommits(true);
608 scheduler_->SetNeedsCommit();
609 EXPECT_NO_ACTION(client_);
611 client_->Reset();
612 task_runner().RunPendingTasks();
613 // There are no pending tasks or actions.
614 EXPECT_NO_ACTION(client_);
615 EXPECT_FALSE(client_->needs_begin_frames());
617 client_->Reset();
618 scheduler_->SetDeferCommits(false);
619 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
621 // Start new BeginMainFrame after defer commit is off.
622 client_->Reset();
623 EXPECT_SCOPED(AdvanceFrame());
624 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
625 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
626 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
629 TEST_F(SchedulerTest, DeferCommitWithRedraw) {
630 scheduler_settings_.use_external_begin_frame_source = true;
631 SetUpScheduler(true);
633 scheduler_->SetDeferCommits(true);
635 scheduler_->SetNeedsCommit();
636 EXPECT_NO_ACTION(client_);
638 // The SetNeedsRedraw will override the SetDeferCommits(true), to allow a
639 // begin frame to be needed.
640 client_->Reset();
641 scheduler_->SetNeedsRedraw();
642 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
644 client_->Reset();
645 AdvanceFrame();
646 // BeginMainFrame is not sent during the defer commit is on.
647 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
648 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
650 client_->Reset();
651 task_runner().RunPendingTasks(); // Run posted deadline.
652 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
653 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
654 EXPECT_TRUE(client_->needs_begin_frames());
656 client_->Reset();
657 AdvanceFrame();
658 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
661 TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
662 scheduler_settings_.use_external_begin_frame_source = true;
663 SetUpScheduler(true);
665 // SetNeedsCommit should begin the frame.
666 scheduler_->SetNeedsCommit();
667 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
669 client_->Reset();
670 EXPECT_SCOPED(AdvanceFrame());
671 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
672 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
673 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
675 EXPECT_TRUE(client_->needs_begin_frames());
676 client_->Reset();
678 // Now SetNeedsCommit again. Calling here means we need a second commit.
679 scheduler_->SetNeedsCommit();
680 EXPECT_EQ(client_->num_actions_(), 0);
681 client_->Reset();
683 // Finish the first commit.
684 scheduler_->NotifyBeginMainFrameStarted();
685 scheduler_->NotifyReadyToCommit();
686 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
687 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
688 client_->Reset();
689 task_runner().RunPendingTasks(); // Run posted deadline.
690 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
691 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
692 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
694 // Because we just swapped, the Scheduler should also request the next
695 // BeginImplFrame from the OutputSurface.
696 EXPECT_TRUE(client_->needs_begin_frames());
697 client_->Reset();
698 // Since another commit is needed, the next BeginImplFrame should initiate
699 // the second commit.
700 EXPECT_SCOPED(AdvanceFrame());
701 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
702 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
703 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
704 client_->Reset();
706 // Finishing the commit before the deadline should post a new deadline task
707 // to trigger the deadline early.
708 scheduler_->NotifyBeginMainFrameStarted();
709 scheduler_->NotifyReadyToCommit();
710 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
711 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
712 client_->Reset();
713 task_runner().RunPendingTasks(); // Run posted deadline.
714 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
715 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
716 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
717 EXPECT_TRUE(client_->needs_begin_frames());
718 client_->Reset();
720 // On the next BeginImplFrame, verify we go back to a quiescent state and
721 // no longer request BeginImplFrames.
722 EXPECT_SCOPED(AdvanceFrame());
723 task_runner().RunPendingTasks(); // Run posted deadline.
724 EXPECT_FALSE(client_->needs_begin_frames());
725 client_->Reset();
728 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
729 public:
730 SchedulerClientThatsetNeedsDrawInsideDraw()
731 : FakeSchedulerClient(), request_redraws_(false) {}
733 void ScheduledActionSendBeginMainFrame() override {}
735 void SetRequestRedrawsInsideDraw(bool enable) { request_redraws_ = enable; }
737 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
738 // Only SetNeedsRedraw the first time this is called
739 if (request_redraws_) {
740 scheduler_->SetNeedsRedraw();
742 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
745 DrawResult ScheduledActionDrawAndSwapForced() override {
746 NOTREACHED();
747 return DRAW_SUCCESS;
750 void ScheduledActionCommit() override {}
751 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {}
753 private:
754 bool request_redraws_;
757 // Tests for two different situations:
758 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
759 // a ScheduledActionDrawAndSwap
760 // 2. the scheduler drawing twice inside a single tick
761 TEST_F(SchedulerTest, RequestRedrawInsideDraw) {
762 SchedulerClientThatsetNeedsDrawInsideDraw* client =
763 new SchedulerClientThatsetNeedsDrawInsideDraw;
764 scheduler_settings_.use_external_begin_frame_source = true;
765 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
766 client->SetRequestRedrawsInsideDraw(true);
768 scheduler_->SetNeedsRedraw();
769 EXPECT_TRUE(scheduler_->RedrawPending());
770 EXPECT_TRUE(client->needs_begin_frames());
771 EXPECT_EQ(0, client->num_draws());
773 EXPECT_SCOPED(AdvanceFrame());
774 task_runner().RunPendingTasks(); // Run posted deadline.
775 EXPECT_EQ(1, client->num_draws());
776 EXPECT_TRUE(scheduler_->RedrawPending());
777 EXPECT_TRUE(client->needs_begin_frames());
779 client->SetRequestRedrawsInsideDraw(false);
781 EXPECT_SCOPED(AdvanceFrame());
782 task_runner().RunPendingTasks(); // Run posted deadline.
783 EXPECT_EQ(2, client_->num_draws());
784 EXPECT_FALSE(scheduler_->RedrawPending());
785 EXPECT_TRUE(client->needs_begin_frames());
787 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
788 // swap.
789 EXPECT_SCOPED(AdvanceFrame());
790 task_runner().RunPendingTasks(); // Run posted deadline.
791 EXPECT_EQ(2, client->num_draws());
792 EXPECT_FALSE(scheduler_->RedrawPending());
793 EXPECT_FALSE(client->needs_begin_frames());
796 // Test that requesting redraw inside a failed draw doesn't lose the request.
797 TEST_F(SchedulerTest, RequestRedrawInsideFailedDraw) {
798 SchedulerClientThatsetNeedsDrawInsideDraw* client =
799 new SchedulerClientThatsetNeedsDrawInsideDraw;
800 scheduler_settings_.use_external_begin_frame_source = true;
801 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
803 client->SetRequestRedrawsInsideDraw(true);
804 client->SetDrawWillHappen(false);
806 scheduler_->SetNeedsRedraw();
807 EXPECT_TRUE(scheduler_->RedrawPending());
808 EXPECT_TRUE(client->needs_begin_frames());
809 EXPECT_EQ(0, client->num_draws());
811 // Fail the draw.
812 EXPECT_SCOPED(AdvanceFrame());
813 task_runner().RunPendingTasks(); // Run posted deadline.
814 EXPECT_EQ(1, client->num_draws());
816 // We have a commit pending and the draw failed, and we didn't lose the redraw
817 // request.
818 EXPECT_TRUE(scheduler_->CommitPending());
819 EXPECT_TRUE(scheduler_->RedrawPending());
820 EXPECT_TRUE(client->needs_begin_frames());
822 client->SetRequestRedrawsInsideDraw(false);
824 // Fail the draw again.
825 EXPECT_SCOPED(AdvanceFrame());
826 task_runner().RunPendingTasks(); // Run posted deadline.
827 EXPECT_EQ(2, client->num_draws());
828 EXPECT_TRUE(scheduler_->CommitPending());
829 EXPECT_TRUE(scheduler_->RedrawPending());
830 EXPECT_TRUE(client->needs_begin_frames());
832 // Draw successfully.
833 client->SetDrawWillHappen(true);
834 EXPECT_SCOPED(AdvanceFrame());
835 task_runner().RunPendingTasks(); // Run posted deadline.
836 EXPECT_EQ(3, client->num_draws());
837 EXPECT_TRUE(scheduler_->CommitPending());
838 EXPECT_FALSE(scheduler_->RedrawPending());
839 EXPECT_TRUE(client->needs_begin_frames());
842 class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
843 public:
844 SchedulerClientThatSetNeedsCommitInsideDraw()
845 : set_needs_commit_on_next_draw_(false) {}
847 void ScheduledActionSendBeginMainFrame() override {}
848 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
849 // Only SetNeedsCommit the first time this is called
850 if (set_needs_commit_on_next_draw_) {
851 scheduler_->SetNeedsCommit();
852 set_needs_commit_on_next_draw_ = false;
854 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
857 DrawResult ScheduledActionDrawAndSwapForced() override {
858 NOTREACHED();
859 return DRAW_SUCCESS;
862 void ScheduledActionCommit() override {}
863 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {}
865 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; }
867 private:
868 bool set_needs_commit_on_next_draw_;
871 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
872 // happen inside a ScheduledActionDrawAndSwap
873 TEST_F(SchedulerTest, RequestCommitInsideDraw) {
874 SchedulerClientThatSetNeedsCommitInsideDraw* client =
875 new SchedulerClientThatSetNeedsCommitInsideDraw;
877 scheduler_settings_.use_external_begin_frame_source = true;
878 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
880 EXPECT_FALSE(client->needs_begin_frames());
881 scheduler_->SetNeedsRedraw();
882 EXPECT_TRUE(scheduler_->RedrawPending());
883 EXPECT_EQ(0, client->num_draws());
884 EXPECT_TRUE(client->needs_begin_frames());
886 client->SetNeedsCommitOnNextDraw();
887 EXPECT_SCOPED(AdvanceFrame());
888 client->SetNeedsCommitOnNextDraw();
889 task_runner().RunPendingTasks(); // Run posted deadline.
890 EXPECT_EQ(1, client->num_draws());
891 EXPECT_TRUE(scheduler_->CommitPending());
892 EXPECT_TRUE(client->needs_begin_frames());
893 scheduler_->NotifyBeginMainFrameStarted();
894 scheduler_->NotifyReadyToCommit();
896 EXPECT_SCOPED(AdvanceFrame());
897 task_runner().RunPendingTasks(); // Run posted deadline.
898 EXPECT_EQ(2, client->num_draws());
900 EXPECT_FALSE(scheduler_->RedrawPending());
901 EXPECT_FALSE(scheduler_->CommitPending());
902 EXPECT_TRUE(client->needs_begin_frames());
904 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
905 // swap.
906 EXPECT_SCOPED(AdvanceFrame());
907 task_runner().RunPendingTasks(); // Run posted deadline.
908 EXPECT_EQ(2, client->num_draws());
909 EXPECT_FALSE(scheduler_->RedrawPending());
910 EXPECT_FALSE(scheduler_->CommitPending());
911 EXPECT_FALSE(client->needs_begin_frames());
914 // Tests that when a draw fails then the pending commit should not be dropped.
915 TEST_F(SchedulerTest, RequestCommitInsideFailedDraw) {
916 SchedulerClientThatsetNeedsDrawInsideDraw* client =
917 new SchedulerClientThatsetNeedsDrawInsideDraw;
918 scheduler_settings_.use_external_begin_frame_source = true;
919 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
921 client->SetDrawWillHappen(false);
923 scheduler_->SetNeedsRedraw();
924 EXPECT_TRUE(scheduler_->RedrawPending());
925 EXPECT_TRUE(client->needs_begin_frames());
926 EXPECT_EQ(0, client->num_draws());
928 // Fail the draw.
929 EXPECT_SCOPED(AdvanceFrame());
930 task_runner().RunPendingTasks(); // Run posted deadline.
931 EXPECT_EQ(1, client->num_draws());
933 // We have a commit pending and the draw failed, and we didn't lose the commit
934 // request.
935 EXPECT_TRUE(scheduler_->CommitPending());
936 EXPECT_TRUE(scheduler_->RedrawPending());
937 EXPECT_TRUE(client->needs_begin_frames());
939 // Fail the draw again.
940 EXPECT_SCOPED(AdvanceFrame());
942 task_runner().RunPendingTasks(); // Run posted deadline.
943 EXPECT_EQ(2, client->num_draws());
944 EXPECT_TRUE(scheduler_->CommitPending());
945 EXPECT_TRUE(scheduler_->RedrawPending());
946 EXPECT_TRUE(client->needs_begin_frames());
948 // Draw successfully.
949 client->SetDrawWillHappen(true);
950 EXPECT_SCOPED(AdvanceFrame());
951 task_runner().RunPendingTasks(); // Run posted deadline.
952 EXPECT_EQ(3, client->num_draws());
953 EXPECT_TRUE(scheduler_->CommitPending());
954 EXPECT_FALSE(scheduler_->RedrawPending());
955 EXPECT_TRUE(client->needs_begin_frames());
958 TEST_F(SchedulerTest, NoSwapWhenDrawFails) {
959 SchedulerClientThatSetNeedsCommitInsideDraw* client =
960 new SchedulerClientThatSetNeedsCommitInsideDraw;
961 scheduler_settings_.use_external_begin_frame_source = true;
962 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
964 scheduler_->SetNeedsRedraw();
965 EXPECT_TRUE(scheduler_->RedrawPending());
966 EXPECT_TRUE(client->needs_begin_frames());
967 EXPECT_EQ(0, client->num_draws());
969 // Draw successfully, this starts a new frame.
970 client->SetNeedsCommitOnNextDraw();
971 EXPECT_SCOPED(AdvanceFrame());
972 task_runner().RunPendingTasks(); // Run posted deadline.
973 EXPECT_EQ(1, client->num_draws());
975 scheduler_->SetNeedsRedraw();
976 EXPECT_TRUE(scheduler_->RedrawPending());
977 EXPECT_TRUE(client->needs_begin_frames());
979 // Fail to draw, this should not start a frame.
980 client->SetDrawWillHappen(false);
981 client->SetNeedsCommitOnNextDraw();
982 EXPECT_SCOPED(AdvanceFrame());
983 task_runner().RunPendingTasks(); // Run posted deadline.
984 EXPECT_EQ(2, client->num_draws());
987 class SchedulerClientNeedsPrepareTilesInDraw : public FakeSchedulerClient {
988 public:
989 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
990 scheduler_->SetNeedsPrepareTiles();
991 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
995 // Test prepare tiles is independant of draws.
996 TEST_F(SchedulerTest, PrepareTiles) {
997 SchedulerClientNeedsPrepareTilesInDraw* client =
998 new SchedulerClientNeedsPrepareTilesInDraw;
999 scheduler_settings_.use_external_begin_frame_source = true;
1000 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1002 // Request both draw and prepare tiles. PrepareTiles shouldn't
1003 // be trigged until BeginImplFrame.
1004 client->Reset();
1005 scheduler_->SetNeedsPrepareTiles();
1006 scheduler_->SetNeedsRedraw();
1007 EXPECT_TRUE(scheduler_->RedrawPending());
1008 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1009 EXPECT_TRUE(client->needs_begin_frames());
1010 EXPECT_EQ(0, client->num_draws());
1011 EXPECT_FALSE(client->HasAction("ScheduledActionPrepareTiles"));
1012 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1014 // We have no immediate actions to perform, so the BeginImplFrame should post
1015 // the deadline task.
1016 client->Reset();
1017 EXPECT_SCOPED(AdvanceFrame());
1018 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1019 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1020 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1022 // On the deadline, he actions should have occured in the right order.
1023 client->Reset();
1024 task_runner().RunPendingTasks(); // Run posted deadline.
1025 EXPECT_EQ(1, client->num_draws());
1026 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1027 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1028 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1029 client->ActionIndex("ScheduledActionPrepareTiles"));
1030 EXPECT_FALSE(scheduler_->RedrawPending());
1031 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1032 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1034 // Request a draw. We don't need a PrepareTiles yet.
1035 client->Reset();
1036 scheduler_->SetNeedsRedraw();
1037 EXPECT_TRUE(scheduler_->RedrawPending());
1038 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1039 EXPECT_TRUE(client->needs_begin_frames());
1040 EXPECT_EQ(0, client->num_draws());
1042 // We have no immediate actions to perform, so the BeginImplFrame should post
1043 // the deadline task.
1044 client->Reset();
1045 EXPECT_SCOPED(AdvanceFrame());
1046 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1047 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1048 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1050 // Draw. The draw will trigger SetNeedsPrepareTiles, and
1051 // then the PrepareTiles action will be triggered after the Draw.
1052 // Afterwards, neither a draw nor PrepareTiles are pending.
1053 client->Reset();
1054 task_runner().RunPendingTasks(); // Run posted deadline.
1055 EXPECT_EQ(1, client->num_draws());
1056 EXPECT_TRUE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1057 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1058 EXPECT_LT(client->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1059 client->ActionIndex("ScheduledActionPrepareTiles"));
1060 EXPECT_FALSE(scheduler_->RedrawPending());
1061 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1062 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1064 // We need a BeginImplFrame where we don't swap to go idle.
1065 client->Reset();
1066 EXPECT_SCOPED(AdvanceFrame());
1067 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1068 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1069 client->Reset();
1070 task_runner().RunPendingTasks(); // Run posted deadline.
1071 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1072 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1073 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1074 EXPECT_EQ(0, client->num_draws());
1076 // Now trigger a PrepareTiles outside of a draw. We will then need
1077 // a begin-frame for the PrepareTiles, but we don't need a draw.
1078 client->Reset();
1079 EXPECT_FALSE(client->needs_begin_frames());
1080 scheduler_->SetNeedsPrepareTiles();
1081 EXPECT_TRUE(client->needs_begin_frames());
1082 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1083 EXPECT_FALSE(scheduler_->RedrawPending());
1085 // BeginImplFrame. There will be no draw, only PrepareTiles.
1086 client->Reset();
1087 EXPECT_SCOPED(AdvanceFrame());
1088 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1089 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1090 client->Reset();
1091 task_runner().RunPendingTasks(); // Run posted deadline.
1092 EXPECT_EQ(0, client->num_draws());
1093 EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1094 EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
1095 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1098 // Test that PrepareTiles only happens once per frame. If an external caller
1099 // initiates it, then the state machine should not PrepareTiles on that frame.
1100 TEST_F(SchedulerTest, PrepareTilesOncePerFrame) {
1101 scheduler_settings_.use_external_begin_frame_source = true;
1102 SetUpScheduler(true);
1104 // If DidPrepareTiles during a frame, then PrepareTiles should not occur
1105 // again.
1106 scheduler_->SetNeedsPrepareTiles();
1107 scheduler_->SetNeedsRedraw();
1108 client_->Reset();
1109 EXPECT_SCOPED(AdvanceFrame());
1110 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1111 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1112 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1114 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1115 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1116 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1118 client_->Reset();
1119 task_runner().RunPendingTasks(); // Run posted deadline.
1120 EXPECT_EQ(1, client_->num_draws());
1121 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1122 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1123 EXPECT_FALSE(scheduler_->RedrawPending());
1124 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1125 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1127 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1128 scheduler_->SetNeedsPrepareTiles();
1129 scheduler_->SetNeedsRedraw();
1130 client_->Reset();
1131 EXPECT_SCOPED(AdvanceFrame());
1132 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1133 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1134 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1136 client_->Reset();
1137 task_runner().RunPendingTasks(); // Run posted deadline.
1138 EXPECT_EQ(1, client_->num_draws());
1139 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1140 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1141 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1142 client_->ActionIndex("ScheduledActionPrepareTiles"));
1143 EXPECT_FALSE(scheduler_->RedrawPending());
1144 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1145 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1146 scheduler_->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1148 // If we get another DidPrepareTiles within the same frame, we should
1149 // not PrepareTiles on the next frame.
1150 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1151 scheduler_->SetNeedsPrepareTiles();
1152 scheduler_->SetNeedsRedraw();
1153 client_->Reset();
1154 EXPECT_SCOPED(AdvanceFrame());
1155 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1156 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1157 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1159 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1161 client_->Reset();
1162 task_runner().RunPendingTasks(); // Run posted deadline.
1163 EXPECT_EQ(1, client_->num_draws());
1164 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1165 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1166 EXPECT_FALSE(scheduler_->RedrawPending());
1167 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1169 // If we get another DidPrepareTiles, we should not PrepareTiles on the next
1170 // frame. This verifies we don't alternate calling PrepareTiles once and
1171 // twice.
1172 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1173 scheduler_->DidPrepareTiles(); // An explicit PrepareTiles.
1174 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1175 scheduler_->SetNeedsPrepareTiles();
1176 scheduler_->SetNeedsRedraw();
1177 client_->Reset();
1178 EXPECT_SCOPED(AdvanceFrame());
1179 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1180 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1181 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1183 EXPECT_TRUE(scheduler_->PrepareTilesPending());
1185 client_->Reset();
1186 task_runner().RunPendingTasks(); // Run posted deadline.
1187 EXPECT_EQ(1, client_->num_draws());
1188 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1189 EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
1190 EXPECT_FALSE(scheduler_->RedrawPending());
1191 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1193 // Next frame without DidPrepareTiles should PrepareTiles with draw.
1194 scheduler_->SetNeedsPrepareTiles();
1195 scheduler_->SetNeedsRedraw();
1196 client_->Reset();
1197 EXPECT_SCOPED(AdvanceFrame());
1198 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1199 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1200 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1202 client_->Reset();
1203 task_runner().RunPendingTasks(); // Run posted deadline.
1204 EXPECT_EQ(1, client_->num_draws());
1205 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1206 EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
1207 EXPECT_LT(client_->ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1208 client_->ActionIndex("ScheduledActionPrepareTiles"));
1209 EXPECT_FALSE(scheduler_->RedrawPending());
1210 EXPECT_FALSE(scheduler_->PrepareTilesPending());
1211 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1212 scheduler_->DidPrepareTiles(); // Corresponds to ScheduledActionPrepareTiles
1215 TEST_F(SchedulerTest, TriggerBeginFrameDeadlineEarly) {
1216 SchedulerClientNeedsPrepareTilesInDraw* client =
1217 new SchedulerClientNeedsPrepareTilesInDraw;
1218 scheduler_settings_.use_external_begin_frame_source = true;
1219 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1221 scheduler_->SetNeedsRedraw();
1222 EXPECT_SCOPED(AdvanceFrame());
1224 // The deadline should be zero since there is no work other than drawing
1225 // pending.
1226 EXPECT_EQ(base::TimeTicks(), client->posted_begin_impl_frame_deadline());
1229 TEST_F(SchedulerTest, WaitForReadyToDrawDoNotPostDeadline) {
1230 SchedulerClientNeedsPrepareTilesInDraw* client =
1231 new SchedulerClientNeedsPrepareTilesInDraw;
1232 scheduler_settings_.use_external_begin_frame_source = true;
1233 scheduler_settings_.impl_side_painting = true;
1234 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1236 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1237 scheduler_->SetNeedsCommit();
1238 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1239 client_->Reset();
1241 // Begin new frame.
1242 EXPECT_SCOPED(AdvanceFrame());
1243 scheduler_->NotifyBeginMainFrameStarted();
1244 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1245 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1247 client_->Reset();
1248 scheduler_->NotifyReadyToCommit();
1249 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1251 client_->Reset();
1252 scheduler_->NotifyReadyToActivate();
1253 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
1255 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1256 // the mode.
1257 scheduler_->SetWaitForReadyToDraw();
1258 client_->Reset();
1259 task_runner().RunPendingTasks(); // Try to run posted deadline.
1260 // There is no posted deadline.
1261 EXPECT_NO_ACTION(client_);
1263 // Scheduler received ready to draw signal, and posted deadline.
1264 scheduler_->NotifyReadyToDraw();
1265 client_->Reset();
1266 task_runner().RunPendingTasks(); // Run posted deadline.
1267 EXPECT_EQ(1, client_->num_draws());
1268 EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible"));
1271 TEST_F(SchedulerTest, WaitForReadyToDrawCancelledWhenLostOutputSurface) {
1272 SchedulerClientNeedsPrepareTilesInDraw* client =
1273 new SchedulerClientNeedsPrepareTilesInDraw;
1274 scheduler_settings_.use_external_begin_frame_source = true;
1275 scheduler_settings_.impl_side_painting = true;
1276 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1278 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1279 scheduler_->SetNeedsCommit();
1280 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1281 client_->Reset();
1283 // Begin new frame.
1284 EXPECT_SCOPED(AdvanceFrame());
1285 scheduler_->NotifyBeginMainFrameStarted();
1286 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1287 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1289 client_->Reset();
1290 scheduler_->NotifyReadyToCommit();
1291 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1293 client_->Reset();
1294 scheduler_->NotifyReadyToActivate();
1295 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
1297 // Set scheduler to wait for ready to draw. Schedule won't post deadline in
1298 // the mode.
1299 scheduler_->SetWaitForReadyToDraw();
1300 client_->Reset();
1301 task_runner().RunPendingTasks(); // Try to run posted deadline.
1302 // There is no posted deadline.
1303 EXPECT_NO_ACTION(client_);
1305 // Scheduler loses output surface, and stops waiting for ready to draw signal.
1306 client_->Reset();
1307 scheduler_->DidLoseOutputSurface();
1308 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1309 task_runner().RunPendingTasks(); // Run posted deadline.
1310 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
1311 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
1312 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
1315 void SchedulerTest::MainFrameInHighLatencyMode(
1316 int64 begin_main_frame_to_commit_estimate_in_ms,
1317 int64 commit_to_activate_estimate_in_ms,
1318 bool impl_latency_takes_priority,
1319 bool should_send_begin_main_frame) {
1320 // Set up client with specified estimates (draw duration is set to 1).
1321 SchedulerClientWithFixedEstimates* client =
1322 new SchedulerClientWithFixedEstimates(
1323 base::TimeDelta::FromMilliseconds(1),
1324 base::TimeDelta::FromMilliseconds(
1325 begin_main_frame_to_commit_estimate_in_ms),
1326 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms));
1328 scheduler_settings_.use_external_begin_frame_source = true;
1329 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1331 scheduler_->SetImplLatencyTakesPriority(impl_latency_takes_priority);
1333 // Impl thread hits deadline before commit finishes.
1334 scheduler_->SetNeedsCommit();
1335 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1336 EXPECT_SCOPED(AdvanceFrame());
1337 EXPECT_FALSE(scheduler_->MainThreadIsInHighLatencyMode());
1338 task_runner().RunPendingTasks(); // Run posted deadline.
1339 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1340 scheduler_->NotifyBeginMainFrameStarted();
1341 scheduler_->NotifyReadyToCommit();
1342 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1343 EXPECT_TRUE(client->HasAction("ScheduledActionSendBeginMainFrame"));
1345 client->Reset();
1346 scheduler_->SetNeedsCommit();
1347 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1348 EXPECT_SCOPED(AdvanceFrame());
1349 EXPECT_TRUE(scheduler_->MainThreadIsInHighLatencyMode());
1350 task_runner().RunPendingTasks(); // Run posted deadline.
1351 EXPECT_EQ(scheduler_->MainThreadIsInHighLatencyMode(),
1352 should_send_begin_main_frame);
1353 EXPECT_EQ(client->HasAction("ScheduledActionSendBeginMainFrame"),
1354 should_send_begin_main_frame);
1357 TEST_F(SchedulerTest,
1358 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) {
1359 // Set up client so that estimates indicate that we can commit and activate
1360 // before the deadline (~8ms by default).
1361 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, false, false));
1364 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) {
1365 // Set up client so that estimates indicate that the commit cannot finish
1366 // before the deadline (~8ms by default).
1367 EXPECT_SCOPED(MainFrameInHighLatencyMode(10, 1, false, true));
1370 TEST_F(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) {
1371 // Set up client so that estimates indicate that the activate cannot finish
1372 // before the deadline (~8ms by default).
1373 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 10, false, true));
1376 TEST_F(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) {
1377 // Set up client so that estimates indicate that we can commit and activate
1378 // before the deadline (~8ms by default), but also enable impl latency takes
1379 // priority mode.
1380 EXPECT_SCOPED(MainFrameInHighLatencyMode(1, 1, true, true));
1383 TEST_F(SchedulerTest,
1384 Deadlock_NotifyReadyToCommitMakesProgressWhileSwapTrottled) {
1385 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1386 // thread. This prevents the scheduler from receiving any pending swap acks.
1387 // This test makes sure that we keep updating the TextureUploader with
1388 // DidAnticipatedDrawTimeChange's so that it can make forward progress and
1389 // upload all the textures needed for the commit to complete.
1391 // Since we are simulating a long commit, set up a client with draw duration
1392 // estimates that prevent skipping main frames to get to low latency mode.
1393 SchedulerClientWithFixedEstimates* client =
1394 new SchedulerClientWithFixedEstimates(
1395 base::TimeDelta::FromMilliseconds(1),
1396 base::TimeDelta::FromMilliseconds(32),
1397 base::TimeDelta::FromMilliseconds(32));
1398 scheduler_settings_.use_external_begin_frame_source = true;
1399 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1401 client->set_log_anticipated_draw_time_change(true);
1403 BeginFrameArgs frame_args =
1404 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
1405 frame_args.interval = base::TimeDelta::FromMilliseconds(1000);
1407 // At this point, we've drawn a frame. Start another commit, but hold off on
1408 // the NotifyReadyToCommit for now.
1409 EXPECT_FALSE(scheduler_->CommitPending());
1410 scheduler_->SetNeedsCommit();
1411 fake_external_begin_frame_source()->TestOnBeginFrame(frame_args);
1412 EXPECT_TRUE(scheduler_->CommitPending());
1414 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1415 // blocking on the renderer.
1416 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1417 task_runner().RunPendingTasks(); // Run posted deadline.
1418 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1419 scheduler_->DidSwapBuffers();
1421 // Spin the event loop a few times and make sure we get more
1422 // DidAnticipateDrawTimeChange calls every time.
1423 int actions_so_far = client->num_actions_();
1425 // Does three iterations to make sure that the timer is properly repeating.
1426 for (int i = 0; i < 3; ++i) {
1427 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1428 task_runner().DelayToNextTaskTime().InMicroseconds())
1429 << scheduler_->AsValue()->ToString();
1430 task_runner().RunPendingTasks();
1431 EXPECT_GT(client->num_actions_(), actions_so_far);
1432 EXPECT_STREQ(client->Action(client->num_actions_() - 1),
1433 "DidAnticipatedDrawTimeChange");
1434 actions_so_far = client->num_actions_();
1437 // Do the same thing after BeginMainFrame starts but still before activation.
1438 scheduler_->NotifyBeginMainFrameStarted();
1439 for (int i = 0; i < 3; ++i) {
1440 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1441 task_runner().DelayToNextTaskTime().InMicroseconds())
1442 << scheduler_->AsValue()->ToString();
1443 task_runner().RunPendingTasks();
1444 EXPECT_GT(client->num_actions_(), actions_so_far);
1445 EXPECT_STREQ(client->Action(client->num_actions_() - 1),
1446 "DidAnticipatedDrawTimeChange");
1447 actions_so_far = client->num_actions_();
1451 TEST_F(
1452 SchedulerTest,
1453 Deadlock_CommitMakesProgressWhileSwapTrottledAndActiveTreeNeedsFirstDraw) {
1454 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1455 // thread. This prevents the scheduler from receiving any pending swap acks.
1457 // Since we are simulating a long commit, set up a client with draw duration
1458 // estimates that prevent skipping main frames to get to low latency mode.
1459 SchedulerClientWithFixedEstimates* client =
1460 new SchedulerClientWithFixedEstimates(
1461 base::TimeDelta::FromMilliseconds(1),
1462 base::TimeDelta::FromMilliseconds(32),
1463 base::TimeDelta::FromMilliseconds(32));
1464 scheduler_settings_.use_external_begin_frame_source = true;
1465 scheduler_settings_.main_frame_while_swap_throttled_enabled = true;
1466 scheduler_settings_.impl_side_painting = true;
1467 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1469 // Disables automatic swap acks so this test can force swap ack throttling
1470 // to simulate a blocked Browser ui thread.
1471 scheduler_->SetMaxSwapsPending(1);
1472 client_->SetAutomaticSwapAck(false);
1474 // Get a new active tree in main-thread high latency mode and put us
1475 // in a swap throttled state.
1476 client_->Reset();
1477 EXPECT_FALSE(scheduler_->CommitPending());
1478 scheduler_->SetNeedsCommit();
1479 scheduler_->SetNeedsRedraw();
1480 EXPECT_SCOPED(AdvanceFrame());
1481 EXPECT_TRUE(scheduler_->CommitPending());
1482 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1483 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1484 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1485 scheduler_->NotifyBeginMainFrameStarted();
1486 scheduler_->NotifyReadyToCommit();
1487 scheduler_->NotifyReadyToActivate();
1488 EXPECT_FALSE(scheduler_->CommitPending());
1489 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 7);
1490 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 7);
1491 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 7);
1492 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 7);
1493 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 7);
1494 EXPECT_ACTION("ScheduledActionCommit", client_, 5, 7);
1495 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 6, 7);
1497 // Make sure that we can finish the next commit even while swap throttled.
1498 client_->Reset();
1499 EXPECT_FALSE(scheduler_->CommitPending());
1500 scheduler_->SetNeedsCommit();
1501 EXPECT_SCOPED(AdvanceFrame());
1502 scheduler_->NotifyBeginMainFrameStarted();
1503 scheduler_->NotifyReadyToCommit();
1504 scheduler_->NotifyReadyToActivate();
1505 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1506 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1507 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1508 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 5);
1509 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 5);
1510 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5);
1511 EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5);
1512 EXPECT_ACTION("ScheduledActionAnimate", client_, 4, 5);
1514 // Make sure we do not send a BeginMainFrame while swap throttled and
1515 // we have both a pending tree and an active tree.
1516 client_->Reset();
1517 EXPECT_FALSE(scheduler_->CommitPending());
1518 scheduler_->SetNeedsCommit();
1519 EXPECT_SCOPED(AdvanceFrame());
1520 EXPECT_FALSE(scheduler_->CommitPending());
1521 task_runner().RunPendingTasks(); // Run posted deadline.
1522 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1523 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1526 TEST_F(SchedulerTest,
1527 Deadlock_NoBeginMainFrameWhileSwapTrottledAndPipelineFull) {
1528 // NPAPI plugins on Windows block the Browser UI thread on the Renderer main
1529 // thread. This prevents the scheduler from receiving any pending swap acks.
1531 // This particular test makes sure we do not send a BeginMainFrame while
1532 // swap trottled and we have a pending tree and active tree that
1533 // still needs to be drawn for the first time.
1535 // Since we are simulating a long commit, set up a client with draw duration
1536 // estimates that prevent skipping main frames to get to low latency mode.
1537 SchedulerClientWithFixedEstimates* client =
1538 new SchedulerClientWithFixedEstimates(
1539 base::TimeDelta::FromMilliseconds(1),
1540 base::TimeDelta::FromMilliseconds(32),
1541 base::TimeDelta::FromMilliseconds(32));
1542 scheduler_settings_.use_external_begin_frame_source = true;
1543 scheduler_settings_.main_frame_while_swap_throttled_enabled = true;
1544 scheduler_settings_.main_frame_before_activation_enabled = true;
1545 scheduler_settings_.impl_side_painting = true;
1546 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1548 // Disables automatic swap acks so this test can force swap ack throttling
1549 // to simulate a blocked Browser ui thread.
1550 scheduler_->SetMaxSwapsPending(1);
1551 client_->SetAutomaticSwapAck(false);
1553 // Start a new commit in main-thread high latency mode and hold off on
1554 // activation.
1555 client_->Reset();
1556 EXPECT_FALSE(scheduler_->CommitPending());
1557 scheduler_->SetNeedsCommit();
1558 scheduler_->SetNeedsRedraw();
1559 EXPECT_SCOPED(AdvanceFrame());
1560 EXPECT_TRUE(scheduler_->CommitPending());
1561 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1562 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1563 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1564 scheduler_->DidSwapBuffersComplete();
1565 scheduler_->NotifyBeginMainFrameStarted();
1566 scheduler_->NotifyReadyToCommit();
1567 EXPECT_FALSE(scheduler_->CommitPending());
1568 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 6);
1569 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 6);
1570 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 6);
1571 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 6);
1572 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 6);
1573 EXPECT_ACTION("ScheduledActionCommit", client_, 5, 6);
1575 // Start another commit while we still have aa pending tree.
1576 // Enter a swap throttled state.
1577 client_->Reset();
1578 EXPECT_FALSE(scheduler_->CommitPending());
1579 scheduler_->SetNeedsCommit();
1580 scheduler_->SetNeedsRedraw();
1581 EXPECT_SCOPED(AdvanceFrame());
1582 EXPECT_TRUE(scheduler_->CommitPending());
1583 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1584 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1585 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1586 scheduler_->NotifyBeginMainFrameStarted();
1587 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4);
1588 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4);
1589 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4);
1590 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1592 // Can't commit yet because there's still a pending tree.
1593 client_->Reset();
1594 scheduler_->NotifyReadyToCommit();
1595 EXPECT_NO_ACTION(client_);
1597 // Activate the pending tree, which also unblocks the commit immediately.
1598 client_->Reset();
1599 scheduler_->NotifyReadyToActivate();
1600 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 2);
1601 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 2);
1603 // Make sure we do not send a BeginMainFrame while swap throttled and
1604 // we have both a pending tree and an active tree that still needs
1605 // it's first draw.
1606 client_->Reset();
1607 EXPECT_FALSE(scheduler_->CommitPending());
1608 scheduler_->SetNeedsCommit();
1609 EXPECT_SCOPED(AdvanceFrame());
1610 EXPECT_FALSE(scheduler_->CommitPending());
1611 task_runner().RunPendingTasks(); // Run posted deadline.
1612 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1613 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1616 TEST_F(
1617 SchedulerTest,
1618 CommitMakesProgressWhenIdleAndHasPendingTreeAndActiveTreeNeedsFirstDraw) {
1619 // This verifies we don't block commits longer than we need to
1620 // for performance reasons - not deadlock reasons.
1622 // Since we are simulating a long commit, set up a client with draw duration
1623 // estimates that prevent skipping main frames to get to low latency mode.
1624 SchedulerClientWithFixedEstimates* client =
1625 new SchedulerClientWithFixedEstimates(
1626 base::TimeDelta::FromMilliseconds(1),
1627 base::TimeDelta::FromMilliseconds(32),
1628 base::TimeDelta::FromMilliseconds(32));
1629 scheduler_settings_.use_external_begin_frame_source = true;
1630 scheduler_settings_.main_frame_while_swap_throttled_enabled = true;
1631 scheduler_settings_.main_frame_before_activation_enabled = true;
1632 scheduler_settings_.impl_side_painting = true;
1633 SetUpScheduler(make_scoped_ptr(client).Pass(), true);
1635 // Disables automatic swap acks so this test can force swap ack throttling
1636 // to simulate a blocked Browser ui thread.
1637 scheduler_->SetMaxSwapsPending(1);
1638 client_->SetAutomaticSwapAck(false);
1640 // Start a new commit in main-thread high latency mode and hold off on
1641 // activation.
1642 client_->Reset();
1643 EXPECT_FALSE(scheduler_->CommitPending());
1644 scheduler_->SetNeedsCommit();
1645 scheduler_->SetNeedsRedraw();
1646 EXPECT_SCOPED(AdvanceFrame());
1647 EXPECT_TRUE(scheduler_->CommitPending());
1648 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1649 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1650 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1651 scheduler_->DidSwapBuffersComplete();
1652 scheduler_->NotifyBeginMainFrameStarted();
1653 scheduler_->NotifyReadyToCommit();
1654 EXPECT_FALSE(scheduler_->CommitPending());
1655 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 6);
1656 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 6);
1657 EXPECT_ACTION("ScheduledActionAnimate", client_, 2, 6);
1658 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 3, 6);
1659 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 6);
1660 EXPECT_ACTION("ScheduledActionCommit", client_, 5, 6);
1662 // Start another commit while we still have an active tree.
1663 client_->Reset();
1664 EXPECT_FALSE(scheduler_->CommitPending());
1665 scheduler_->SetNeedsCommit();
1666 scheduler_->SetNeedsRedraw();
1667 EXPECT_SCOPED(AdvanceFrame());
1668 EXPECT_TRUE(scheduler_->CommitPending());
1669 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1670 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1671 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1672 scheduler_->DidSwapBuffersComplete();
1673 scheduler_->NotifyBeginMainFrameStarted();
1674 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4);
1675 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4);
1676 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4);
1677 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 4);
1679 // Can't commit yet because there's still a pending tree.
1680 client_->Reset();
1681 scheduler_->NotifyReadyToCommit();
1682 EXPECT_NO_ACTION(client_);
1684 // Activate the pending tree, which also unblocks the commit immediately
1685 // while we are in an idle state.
1686 client_->Reset();
1687 scheduler_->NotifyReadyToActivate();
1688 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 2);
1689 EXPECT_ACTION("ScheduledActionCommit", client_, 1, 2);
1692 TEST_F(SchedulerTest, BeginRetroFrame) {
1693 scheduler_settings_.use_external_begin_frame_source = true;
1694 SetUpScheduler(true);
1696 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1697 scheduler_->SetNeedsCommit();
1698 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1699 client_->Reset();
1701 // Create a BeginFrame with a long deadline to avoid race conditions.
1702 // This is the first BeginFrame, which will be handled immediately.
1703 BeginFrameArgs args =
1704 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
1705 args.deadline += base::TimeDelta::FromHours(1);
1706 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1707 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1708 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1709 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1710 EXPECT_TRUE(client_->needs_begin_frames());
1711 client_->Reset();
1713 // Queue BeginFrames while we are still handling the previous BeginFrame.
1714 args.frame_time += base::TimeDelta::FromSeconds(1);
1715 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1716 args.frame_time += base::TimeDelta::FromSeconds(1);
1717 fake_external_begin_frame_source()->TestOnBeginFrame(args);
1719 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1720 task_runner().RunPendingTasks(); // Run posted deadline.
1721 EXPECT_NO_ACTION(client_);
1722 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1723 EXPECT_TRUE(client_->needs_begin_frames());
1724 client_->Reset();
1726 // NotifyReadyToCommit should trigger the commit.
1727 scheduler_->NotifyBeginMainFrameStarted();
1728 scheduler_->NotifyReadyToCommit();
1729 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1730 EXPECT_TRUE(client_->needs_begin_frames());
1731 client_->Reset();
1733 // BeginImplFrame should prepare the draw.
1734 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1735 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1736 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1737 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1738 EXPECT_TRUE(client_->needs_begin_frames());
1739 client_->Reset();
1741 // BeginImplFrame deadline should draw.
1742 task_runner().RunPendingTasks(); // Run posted deadline.
1743 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
1744 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1745 EXPECT_TRUE(client_->needs_begin_frames());
1746 client_->Reset();
1748 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1749 // to avoid excessive toggles.
1750 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1751 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
1752 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1753 client_->Reset();
1755 task_runner().RunPendingTasks(); // Run posted deadline.
1756 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
1757 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
1758 client_->Reset();
1761 TEST_F(SchedulerTest, BeginRetroFrame_SwapThrottled) {
1762 scheduler_settings_.use_external_begin_frame_source = true;
1763 SetUpScheduler(true);
1765 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
1767 // To test swap ack throttling, this test disables automatic swap acks.
1768 scheduler_->SetMaxSwapsPending(1);
1769 client_->SetAutomaticSwapAck(false);
1771 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1772 client_->Reset();
1773 scheduler_->SetNeedsCommit();
1774 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1775 client_->Reset();
1777 EXPECT_SCOPED(AdvanceFrame());
1778 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1779 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1780 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1781 EXPECT_TRUE(client_->needs_begin_frames());
1782 client_->Reset();
1784 // Queue BeginFrame while we are still handling the previous BeginFrame.
1785 SendNextBeginFrame();
1786 EXPECT_NO_ACTION(client_);
1787 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1788 EXPECT_TRUE(client_->needs_begin_frames());
1789 client_->Reset();
1791 // NotifyReadyToCommit should trigger the pending commit and draw.
1792 scheduler_->NotifyBeginMainFrameStarted();
1793 scheduler_->NotifyReadyToCommit();
1794 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1795 EXPECT_TRUE(client_->needs_begin_frames());
1796 client_->Reset();
1798 // Swapping will put us into a swap throttled state.
1799 // Run posted deadline.
1800 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1801 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1802 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1803 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1804 EXPECT_TRUE(client_->needs_begin_frames());
1805 client_->Reset();
1807 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1808 // but not a BeginMainFrame or draw.
1809 scheduler_->SetNeedsCommit();
1810 scheduler_->SetNeedsRedraw();
1811 // Run posted BeginRetroFrame.
1812 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
1813 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1814 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1815 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1816 EXPECT_TRUE(client_->needs_begin_frames());
1817 client_->Reset();
1819 // Let time pass sufficiently beyond the regular deadline but not beyond the
1820 // late deadline.
1821 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
1822 base::TimeDelta::FromMicroseconds(1));
1823 task_runner().RunUntilTime(now_src()->Now());
1824 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1826 // Take us out of a swap throttled state.
1827 scheduler_->DidSwapBuffersComplete();
1828 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
1829 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1830 EXPECT_TRUE(client_->needs_begin_frames());
1831 client_->Reset();
1833 // Verify that the deadline was rescheduled.
1834 task_runner().RunUntilTime(now_src()->Now());
1835 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
1836 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1837 EXPECT_TRUE(client_->needs_begin_frames());
1838 client_->Reset();
1841 TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooEarly) {
1842 scheduler_settings_.use_external_begin_frame_source = true;
1843 SetUpScheduler(true);
1845 scheduler_->SetNeedsCommit();
1846 EXPECT_TRUE(client_->needs_begin_frames());
1847 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1849 client_->Reset();
1850 EXPECT_SCOPED(AdvanceFrame());
1851 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1852 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1853 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1855 client_->Reset();
1856 scheduler_->NotifyBeginMainFrameStarted();
1858 client_->Reset();
1859 BeginFrameArgs retro_frame_args = SendNextBeginFrame();
1860 // This BeginFrame is queued up as a retro frame.
1861 EXPECT_NO_ACTION(client_);
1862 // The previous deadline is still pending.
1863 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1865 client_->Reset();
1866 // This commit should schedule the (previous) deadline to trigger immediately.
1867 scheduler_->NotifyReadyToCommit();
1868 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1870 client_->Reset();
1871 // The deadline task should trigger causing a draw.
1872 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1873 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1874 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1875 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1877 // Keep animating.
1878 client_->Reset();
1879 scheduler_->SetNeedsAnimate();
1880 scheduler_->SetNeedsRedraw();
1881 EXPECT_NO_ACTION(client_);
1883 // Let's advance to the retro frame's deadline.
1884 now_src()->AdvanceNow(retro_frame_args.deadline - now_src()->Now());
1886 // The retro frame hasn't expired yet.
1887 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false));
1888 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1889 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
1890 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1892 // This is an immediate deadline case.
1893 client_->Reset();
1894 task_runner().RunPendingTasks();
1895 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1896 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
1899 TEST_F(SchedulerTest, RetroFrameExpiresOnTime) {
1900 scheduler_settings_.use_external_begin_frame_source = true;
1901 SetUpScheduler(true);
1903 scheduler_->SetNeedsCommit();
1904 EXPECT_TRUE(client_->needs_begin_frames());
1905 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1907 client_->Reset();
1908 EXPECT_SCOPED(AdvanceFrame());
1909 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1910 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1911 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1913 client_->Reset();
1914 scheduler_->NotifyBeginMainFrameStarted();
1916 client_->Reset();
1917 BeginFrameArgs retro_frame_args = SendNextBeginFrame();
1918 // This BeginFrame is queued up as a retro frame.
1919 EXPECT_NO_ACTION(client_);
1920 // The previous deadline is still pending.
1921 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1923 client_->Reset();
1924 // This commit should schedule the (previous) deadline to trigger immediately.
1925 scheduler_->NotifyReadyToCommit();
1926 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
1928 client_->Reset();
1929 // The deadline task should trigger causing a draw.
1930 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1931 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
1932 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
1933 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
1935 // Keep animating.
1936 client_->Reset();
1937 scheduler_->SetNeedsAnimate();
1938 scheduler_->SetNeedsRedraw();
1939 EXPECT_NO_ACTION(client_);
1941 // Let's advance sufficiently past the retro frame's deadline.
1942 now_src()->AdvanceNow(retro_frame_args.deadline - now_src()->Now() +
1943 base::TimeDelta::FromMicroseconds(1));
1945 // The retro frame should've expired.
1946 EXPECT_NO_ACTION(client_);
1949 TEST_F(SchedulerTest, MissedFrameDoesNotExpireTooEarly) {
1950 scheduler_settings_.use_external_begin_frame_source = true;
1951 SetUpScheduler(true);
1953 scheduler_->SetNeedsCommit();
1954 EXPECT_TRUE(client_->needs_begin_frames());
1955 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1957 BeginFrameArgs missed_frame_args =
1958 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
1959 missed_frame_args.type = BeginFrameArgs::MISSED;
1961 // Advance to the deadline.
1962 now_src()->AdvanceNow(missed_frame_args.deadline - now_src()->Now());
1964 // Missed frame is handled because it's on time.
1965 client_->Reset();
1966 fake_external_begin_frame_source_->TestOnBeginFrame(missed_frame_args);
1967 EXPECT_TRUE(
1968 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false)));
1969 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
1970 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
1971 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
1974 TEST_F(SchedulerTest, MissedFrameExpiresOnTime) {
1975 scheduler_settings_.use_external_begin_frame_source = true;
1976 SetUpScheduler(true);
1978 scheduler_->SetNeedsCommit();
1979 EXPECT_TRUE(client_->needs_begin_frames());
1980 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
1982 BeginFrameArgs missed_frame_args =
1983 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
1984 missed_frame_args.type = BeginFrameArgs::MISSED;
1986 // Advance sufficiently past the deadline.
1987 now_src()->AdvanceNow(missed_frame_args.deadline - now_src()->Now() +
1988 base::TimeDelta::FromMicroseconds(1));
1990 // Missed frame is dropped because it's too late.
1991 client_->Reset();
1992 fake_external_begin_frame_source_->TestOnBeginFrame(missed_frame_args);
1993 EXPECT_FALSE(
1994 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false)));
1995 EXPECT_NO_ACTION(client_);
1996 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
1999 void SchedulerTest::BeginFramesNotFromClient(
2000 bool use_external_begin_frame_source,
2001 bool throttle_frame_production) {
2002 scheduler_settings_.use_external_begin_frame_source =
2003 use_external_begin_frame_source;
2004 scheduler_settings_.throttle_frame_production = throttle_frame_production;
2005 SetUpScheduler(true);
2007 // SetNeedsCommit should begin the frame on the next BeginImplFrame
2008 // without calling SetNeedsBeginFrame.
2009 scheduler_->SetNeedsCommit();
2010 EXPECT_NO_ACTION(client_);
2011 client_->Reset();
2013 // When the client-driven BeginFrame are disabled, the scheduler posts it's
2014 // own BeginFrame tasks.
2015 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2016 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2017 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2018 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2019 client_->Reset();
2021 // If we don't swap on the deadline, we wait for the next BeginFrame.
2022 task_runner().RunPendingTasks(); // Run posted deadline.
2023 EXPECT_NO_ACTION(client_);
2024 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2025 client_->Reset();
2027 // NotifyReadyToCommit should trigger the commit.
2028 scheduler_->NotifyBeginMainFrameStarted();
2029 scheduler_->NotifyReadyToCommit();
2030 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2031 client_->Reset();
2033 // BeginImplFrame should prepare the draw.
2034 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2035 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2036 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2037 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2038 client_->Reset();
2040 // BeginImplFrame deadline should draw.
2041 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2042 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2043 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2044 client_->Reset();
2046 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2047 // to avoid excessive toggles.
2048 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2049 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
2050 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2051 client_->Reset();
2053 // Make sure SetNeedsBeginFrame isn't called on the client
2054 // when the BeginFrame is no longer needed.
2055 task_runner().RunPendingTasks(); // Run posted deadline.
2056 EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_);
2057 client_->Reset();
2060 TEST_F(SchedulerTest, SyntheticBeginFrames) {
2061 bool use_external_begin_frame_source = false;
2062 bool throttle_frame_production = true;
2063 BeginFramesNotFromClient(use_external_begin_frame_source,
2064 throttle_frame_production);
2067 TEST_F(SchedulerTest, VSyncThrottlingDisabled) {
2068 bool use_external_begin_frame_source = true;
2069 bool throttle_frame_production = false;
2070 BeginFramesNotFromClient(use_external_begin_frame_source,
2071 throttle_frame_production);
2074 TEST_F(SchedulerTest, SyntheticBeginFrames_And_VSyncThrottlingDisabled) {
2075 bool use_external_begin_frame_source = false;
2076 bool throttle_frame_production = false;
2077 BeginFramesNotFromClient(use_external_begin_frame_source,
2078 throttle_frame_production);
2081 void SchedulerTest::BeginFramesNotFromClient_SwapThrottled(
2082 bool use_external_begin_frame_source,
2083 bool throttle_frame_production) {
2084 scheduler_settings_.use_external_begin_frame_source =
2085 use_external_begin_frame_source;
2086 scheduler_settings_.throttle_frame_production = throttle_frame_production;
2087 SetUpScheduler(true);
2089 scheduler_->SetEstimatedParentDrawTime(base::TimeDelta::FromMicroseconds(1));
2091 // To test swap ack throttling, this test disables automatic swap acks.
2092 scheduler_->SetMaxSwapsPending(1);
2093 client_->SetAutomaticSwapAck(false);
2095 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2096 client_->Reset();
2097 scheduler_->SetNeedsCommit();
2098 EXPECT_NO_ACTION(client_);
2099 client_->Reset();
2101 // Trigger the first BeginImplFrame and BeginMainFrame
2102 EXPECT_SCOPED(AdvanceFrame());
2103 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2104 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2105 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2106 client_->Reset();
2108 // NotifyReadyToCommit should trigger the pending commit and draw.
2109 scheduler_->NotifyBeginMainFrameStarted();
2110 scheduler_->NotifyReadyToCommit();
2111 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2112 client_->Reset();
2114 // Swapping will put us into a swap throttled state.
2115 // Run posted deadline.
2116 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2117 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2118 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2119 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2120 client_->Reset();
2122 // While swap throttled, BeginFrames should trigger BeginImplFrames,
2123 // but not a BeginMainFrame or draw.
2124 scheduler_->SetNeedsCommit();
2125 scheduler_->SetNeedsRedraw();
2126 EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame.
2127 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2128 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2129 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2130 client_->Reset();
2132 // Let time pass sufficiently beyond the regular deadline but not beyond the
2133 // late deadline.
2134 now_src()->AdvanceNow(BeginFrameArgs::DefaultInterval() -
2135 base::TimeDelta::FromMicroseconds(1));
2136 task_runner().RunUntilTime(now_src()->Now());
2137 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2139 // Take us out of a swap throttled state.
2140 scheduler_->DidSwapBuffersComplete();
2141 EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_);
2142 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2143 client_->Reset();
2145 // Verify that the deadline was rescheduled.
2146 // We can't use RunUntilTime(now) here because the next frame is also
2147 // scheduled if throttle_frame_production = false.
2148 base::TimeTicks before_deadline = now_src()->Now();
2149 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2150 base::TimeTicks after_deadline = now_src()->Now();
2151 EXPECT_EQ(after_deadline, before_deadline);
2152 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2153 client_->Reset();
2156 TEST_F(SchedulerTest, SyntheticBeginFrames_SwapThrottled) {
2157 bool use_external_begin_frame_source = false;
2158 bool throttle_frame_production = true;
2159 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
2160 throttle_frame_production);
2163 TEST_F(SchedulerTest, VSyncThrottlingDisabled_SwapThrottled) {
2164 bool use_external_begin_frame_source = true;
2165 bool throttle_frame_production = false;
2166 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
2167 throttle_frame_production);
2170 TEST_F(SchedulerTest,
2171 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled) {
2172 bool use_external_begin_frame_source = false;
2173 bool throttle_frame_production = false;
2174 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
2175 throttle_frame_production);
2178 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized) {
2179 scheduler_settings_.use_external_begin_frame_source = true;
2180 SetUpScheduler(false);
2182 scheduler_->SetCanStart();
2183 scheduler_->SetVisible(true);
2184 scheduler_->SetCanDraw(true);
2186 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
2187 client_->Reset();
2188 scheduler_->DidCreateAndInitializeOutputSurface();
2189 EXPECT_NO_ACTION(client_);
2191 scheduler_->DidLoseOutputSurface();
2192 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_);
2195 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) {
2196 scheduler_settings_.use_external_begin_frame_source = true;
2197 SetUpScheduler(true);
2199 // SetNeedsCommit should begin the frame.
2200 scheduler_->SetNeedsCommit();
2201 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2203 client_->Reset();
2204 EXPECT_SCOPED(AdvanceFrame());
2205 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2206 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2207 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2209 client_->Reset();
2210 scheduler_->DidLoseOutputSurface();
2211 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2212 EXPECT_NO_ACTION(client_);
2214 client_->Reset();
2215 scheduler_->NotifyBeginMainFrameStarted();
2216 scheduler_->NotifyReadyToCommit();
2217 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 1);
2219 client_->Reset();
2220 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2221 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2222 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2223 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2226 void SchedulerTest::DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
2227 bool impl_side_painting) {
2228 scheduler_settings_.impl_side_painting = impl_side_painting;
2229 scheduler_settings_.use_external_begin_frame_source = true;
2230 SetUpScheduler(true);
2232 // SetNeedsCommit should begin the frame.
2233 scheduler_->SetNeedsCommit();
2234 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2236 client_->Reset();
2237 EXPECT_SCOPED(AdvanceFrame());
2238 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2239 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2240 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2242 client_->Reset();
2243 scheduler_->DidLoseOutputSurface();
2244 // Do nothing when impl frame is in deadine pending state.
2245 EXPECT_NO_ACTION(client_);
2247 client_->Reset();
2248 // Run posted deadline.
2249 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2250 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2251 // OnBeginImplFrameDeadline didn't schedule output surface creation because
2252 // main frame is not yet completed.
2253 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
2254 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2255 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2257 // BeginImplFrame is not started.
2258 client_->Reset();
2259 task_runner().RunUntilTime(now_src()->Now() +
2260 base::TimeDelta::FromMilliseconds(10));
2261 EXPECT_NO_ACTION(client_);
2262 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2264 client_->Reset();
2265 scheduler_->NotifyBeginMainFrameStarted();
2266 scheduler_->NotifyReadyToCommit();
2267 if (impl_side_painting) {
2268 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 3);
2269 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 3);
2270 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 2, 3);
2271 } else {
2272 EXPECT_ACTION("ScheduledActionCommit", client_, 0, 2);
2273 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 2);
2277 TEST_F(SchedulerTest,
2278 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) {
2279 bool impl_side_painting = false;
2280 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
2283 TEST_F(SchedulerTest,
2284 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint) {
2285 bool impl_side_painting = true;
2286 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
2289 void SchedulerTest::DidLoseOutputSurfaceAfterReadyToCommit(
2290 bool impl_side_painting) {
2291 scheduler_settings_.impl_side_painting = impl_side_painting;
2292 scheduler_settings_.use_external_begin_frame_source = true;
2293 SetUpScheduler(true);
2295 // SetNeedsCommit should begin the frame.
2296 scheduler_->SetNeedsCommit();
2297 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2299 client_->Reset();
2300 EXPECT_SCOPED(AdvanceFrame());
2301 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2302 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2303 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2305 client_->Reset();
2306 scheduler_->NotifyBeginMainFrameStarted();
2307 scheduler_->NotifyReadyToCommit();
2308 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2310 client_->Reset();
2311 scheduler_->DidLoseOutputSurface();
2312 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2313 if (impl_side_painting) {
2314 // Sync tree should be forced to activate.
2315 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2316 } else {
2317 EXPECT_NO_ACTION(client_);
2320 client_->Reset();
2321 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2322 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2323 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2324 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2327 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) {
2328 DidLoseOutputSurfaceAfterReadyToCommit(false);
2331 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting) {
2332 DidLoseOutputSurfaceAfterReadyToCommit(true);
2335 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles) {
2336 scheduler_settings_.use_external_begin_frame_source = true;
2337 SetUpScheduler(true);
2339 scheduler_->SetNeedsPrepareTiles();
2340 scheduler_->SetNeedsRedraw();
2341 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2343 client_->Reset();
2344 EXPECT_SCOPED(AdvanceFrame());
2345 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2346 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2347 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2349 client_->Reset();
2350 scheduler_->DidLoseOutputSurface();
2351 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2352 EXPECT_NO_ACTION(client_);
2354 client_->Reset();
2355 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2356 EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 0, 4);
2357 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 4);
2358 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 2, 4);
2359 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 3, 4);
2362 TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) {
2363 scheduler_settings_.use_external_begin_frame_source = true;
2364 SetUpScheduler(true);
2366 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2367 scheduler_->SetNeedsCommit();
2368 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2370 // Create a BeginFrame with a long deadline to avoid race conditions.
2371 // This is the first BeginFrame, which will be handled immediately.
2372 client_->Reset();
2373 BeginFrameArgs args =
2374 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2375 args.deadline += base::TimeDelta::FromHours(1);
2376 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2377 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2378 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2379 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2380 EXPECT_TRUE(client_->needs_begin_frames());
2382 // Queue BeginFrames while we are still handling the previous BeginFrame.
2383 args.frame_time += base::TimeDelta::FromSeconds(1);
2384 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2385 args.frame_time += base::TimeDelta::FromSeconds(1);
2386 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2388 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2389 client_->Reset();
2390 task_runner().RunPendingTasks(); // Run posted deadline.
2391 EXPECT_NO_ACTION(client_);
2392 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2393 EXPECT_TRUE(client_->needs_begin_frames());
2395 // NotifyReadyToCommit should trigger the commit.
2396 client_->Reset();
2397 scheduler_->NotifyBeginMainFrameStarted();
2398 scheduler_->NotifyReadyToCommit();
2399 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2400 EXPECT_TRUE(client_->needs_begin_frames());
2402 client_->Reset();
2403 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty());
2404 scheduler_->DidLoseOutputSurface();
2405 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2406 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2407 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2408 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty());
2410 // Posted BeginRetroFrame is aborted.
2411 client_->Reset();
2412 task_runner().RunPendingTasks();
2413 EXPECT_NO_ACTION(client_);
2416 TEST_F(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) {
2417 scheduler_settings_.use_external_begin_frame_source = true;
2418 SetUpScheduler(true);
2420 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2421 scheduler_->SetNeedsCommit();
2422 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2424 // Create a BeginFrame with a long deadline to avoid race conditions.
2425 // This is the first BeginFrame, which will be handled immediately.
2426 client_->Reset();
2427 BeginFrameArgs args =
2428 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src());
2429 args.deadline += base::TimeDelta::FromHours(1);
2430 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2431 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2432 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2433 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2434 EXPECT_TRUE(client_->needs_begin_frames());
2436 // Queue BeginFrames while we are still handling the previous BeginFrame.
2437 args.frame_time += base::TimeDelta::FromSeconds(1);
2438 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2439 args.frame_time += base::TimeDelta::FromSeconds(1);
2440 fake_external_begin_frame_source()->TestOnBeginFrame(args);
2442 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
2443 client_->Reset();
2444 task_runner().RunPendingTasks(); // Run posted deadline.
2445 EXPECT_NO_ACTION(client_);
2446 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2447 EXPECT_TRUE(client_->needs_begin_frames());
2449 // NotifyReadyToCommit should trigger the commit.
2450 client_->Reset();
2451 scheduler_->NotifyBeginMainFrameStarted();
2452 scheduler_->NotifyReadyToCommit();
2453 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2454 EXPECT_TRUE(client_->needs_begin_frames());
2456 // BeginImplFrame should prepare the draw.
2457 client_->Reset();
2458 task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
2459 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2460 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2461 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2462 EXPECT_TRUE(client_->needs_begin_frames());
2464 client_->Reset();
2465 EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty());
2466 scheduler_->DidLoseOutputSurface();
2467 EXPECT_NO_ACTION(client_);
2468 EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty());
2470 // BeginImplFrame deadline should abort drawing.
2471 client_->Reset();
2472 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2473 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2474 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2475 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2476 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2477 EXPECT_FALSE(client_->needs_begin_frames());
2479 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
2480 client_->Reset();
2481 task_runner().RunPendingTasks();
2482 EXPECT_NO_ACTION(client_);
2485 TEST_F(SchedulerTest, DidLoseOutputSurfaceWithSyntheticBeginFrameSource) {
2486 SetUpScheduler(true);
2488 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2489 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2490 scheduler_->SetNeedsCommit();
2491 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2493 client_->Reset();
2494 AdvanceFrame();
2495 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2496 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2497 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2498 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2500 // NotifyReadyToCommit should trigger the commit.
2501 client_->Reset();
2502 scheduler_->NotifyBeginMainFrameStarted();
2503 scheduler_->NotifyReadyToCommit();
2504 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2505 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2507 client_->Reset();
2508 scheduler_->DidLoseOutputSurface();
2509 // SetNeedsBeginFrames(false) is not called until the end of the frame.
2510 EXPECT_NO_ACTION(client_);
2511 EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames());
2513 client_->Reset();
2514 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2515 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 2);
2516 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2517 EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames());
2520 TEST_F(SchedulerTest, DidLoseOutputSurfaceWhenIdle) {
2521 scheduler_settings_.use_external_begin_frame_source = true;
2522 SetUpScheduler(true);
2524 // SetNeedsCommit should begin the frame.
2525 scheduler_->SetNeedsCommit();
2526 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2528 client_->Reset();
2529 EXPECT_SCOPED(AdvanceFrame());
2530 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2531 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2532 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2534 client_->Reset();
2535 scheduler_->NotifyBeginMainFrameStarted();
2536 scheduler_->NotifyReadyToCommit();
2537 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2539 client_->Reset();
2540 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2541 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2542 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2544 // Idle time between BeginFrames.
2545 client_->Reset();
2546 scheduler_->DidLoseOutputSurface();
2547 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3);
2548 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2549 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2552 TEST_F(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) {
2553 scheduler_settings_.impl_side_painting = true;
2554 scheduler_settings_.use_external_begin_frame_source = true;
2555 SetUpScheduler(true);
2557 // SetNeedsCommit should begin the frame.
2558 scheduler_->SetNeedsCommit();
2559 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2561 client_->Reset();
2562 EXPECT_SCOPED(AdvanceFrame());
2563 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2564 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2565 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2567 client_->Reset();
2568 scheduler_->NotifyBeginMainFrameStarted();
2569 scheduler_->NotifyReadyToCommit();
2570 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2571 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2573 client_->Reset();
2574 scheduler_->SetVisible(false);
2575 task_runner().RunPendingTasks(); // Run posted deadline.
2577 // Sync tree should be forced to activate.
2578 EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 3);
2579 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2580 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2583 // Tests to ensure frame sources can be successfully changed while drawing.
2584 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottled) {
2585 scheduler_settings_.use_external_begin_frame_source = true;
2586 SetUpScheduler(true);
2588 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2589 scheduler_->SetNeedsRedraw();
2590 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2591 client_->Reset();
2593 EXPECT_SCOPED(AdvanceFrame());
2594 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2595 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2596 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2597 EXPECT_TRUE(client_->needs_begin_frames());
2598 client_->Reset();
2599 task_runner().RunPendingTasks(); // Run posted deadline.
2600 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2601 scheduler_->SetNeedsRedraw();
2603 // Switch to an unthrottled frame source.
2604 scheduler_->SetThrottleFrameProduction(false);
2605 client_->Reset();
2607 // Unthrottled frame source will immediately begin a new frame.
2608 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2609 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2610 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2611 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2612 client_->Reset();
2614 // If we don't swap on the deadline, we wait for the next BeginFrame.
2615 task_runner().RunPendingTasks(); // Run posted deadline.
2616 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2617 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2618 client_->Reset();
2621 // Tests to ensure frame sources can be successfully changed while a frame
2622 // deadline is pending.
2623 TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottledBeforeDeadline) {
2624 scheduler_settings_.use_external_begin_frame_source = true;
2625 SetUpScheduler(true);
2627 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2628 scheduler_->SetNeedsRedraw();
2629 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2630 client_->Reset();
2632 EXPECT_SCOPED(AdvanceFrame());
2633 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2634 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2636 // Switch to an unthrottled frame source before the frame deadline is hit.
2637 scheduler_->SetThrottleFrameProduction(false);
2638 client_->Reset();
2640 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2641 EXPECT_TRUE(client_->needs_begin_frames());
2642 client_->Reset();
2644 task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame.
2645 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2);
2646 // Unthrottled frame source will immediately begin a new frame.
2647 EXPECT_ACTION("WillBeginImplFrame", client_, 1, 2);
2648 scheduler_->SetNeedsRedraw();
2649 client_->Reset();
2651 task_runner().RunPendingTasks(); // Run posted deadline.
2652 EXPECT_ACTION("ScheduledActionAnimate", client_, 0, 2);
2653 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2);
2654 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2655 client_->Reset();
2658 // Tests to ensure that the active frame source can successfully be changed from
2659 // unthrottled to throttled.
2660 TEST_F(SchedulerTest, SwitchFrameSourceToThrottled) {
2661 scheduler_settings_.throttle_frame_production = false;
2662 scheduler_settings_.use_external_begin_frame_source = true;
2663 SetUpScheduler(true);
2665 scheduler_->SetNeedsRedraw();
2666 EXPECT_NO_ACTION(client_);
2667 client_->Reset();
2669 task_runner().RunPendingTasks(); // Run posted BeginFrame.
2670 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2671 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2672 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2673 client_->Reset();
2675 task_runner().RunPendingTasks(); // Run posted deadline.
2676 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2677 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2678 client_->Reset();
2680 // Switch to a throttled frame source.
2681 scheduler_->SetThrottleFrameProduction(true);
2682 client_->Reset();
2684 // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
2685 scheduler_->SetNeedsRedraw();
2686 task_runner().RunPendingTasks();
2687 EXPECT_NO_ACTION(client_);
2688 client_->Reset();
2690 EXPECT_SCOPED(AdvanceFrame());
2691 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2692 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 2);
2693 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2694 EXPECT_TRUE(client_->needs_begin_frames());
2695 client_->Reset();
2696 task_runner().RunPendingTasks(); // Run posted deadline.
2697 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1);
2700 // Tests to ensure that we send a BeginMainFrameNotExpectedSoon when expected.
2701 TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon) {
2702 scheduler_settings_.use_external_begin_frame_source = true;
2703 SetUpScheduler(true);
2705 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
2706 scheduler_->SetNeedsCommit();
2707 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2708 client_->Reset();
2710 // Trigger a frame draw.
2711 EXPECT_SCOPED(AdvanceFrame());
2712 scheduler_->NotifyBeginMainFrameStarted();
2713 scheduler_->NotifyReadyToCommit();
2714 task_runner().RunPendingTasks();
2715 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 5);
2716 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 5);
2717 EXPECT_ACTION("ScheduledActionCommit", client_, 2, 5);
2718 EXPECT_ACTION("ScheduledActionAnimate", client_, 3, 5);
2719 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 4, 5);
2720 client_->Reset();
2722 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
2723 // and send a SendBeginMainFrameNotExpectedSoon.
2724 EXPECT_SCOPED(AdvanceFrame());
2725 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
2726 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
2727 client_->Reset();
2729 task_runner().RunPendingTasks(); // Run posted deadline.
2730 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
2731 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
2732 client_->Reset();
2735 TEST_F(SchedulerTest, SynchronousCompositorAnimation) {
2736 scheduler_settings_.using_synchronous_renderer_compositor = true;
2737 scheduler_settings_.use_external_begin_frame_source = true;
2738 scheduler_settings_.impl_side_painting = true;
2739 SetUpScheduler(true);
2741 scheduler_->SetNeedsAnimate();
2742 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2743 client_->Reset();
2745 // Next vsync.
2746 AdvanceFrame();
2747 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2748 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
2749 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
2750 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2751 client_->Reset();
2753 // Continue with animation.
2754 scheduler_->SetNeedsAnimate();
2755 EXPECT_NO_ACTION(client_);
2757 // Android onDraw.
2758 scheduler_->SetNeedsRedraw();
2759 scheduler_->OnDrawForOutputSurface();
2760 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
2761 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2762 client_->Reset();
2764 // Next vsync.
2765 AdvanceFrame();
2766 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2767 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
2768 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
2769 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2770 client_->Reset();
2772 // Android onDraw.
2773 scheduler_->SetNeedsRedraw();
2774 scheduler_->OnDrawForOutputSurface();
2775 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
2776 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2777 client_->Reset();
2779 // Idle on next vsync.
2780 AdvanceFrame();
2781 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2782 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2783 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2784 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2785 client_->Reset();
2788 TEST_F(SchedulerTest, SynchronousCompositorOnDrawDuringIdle) {
2789 scheduler_settings_.using_synchronous_renderer_compositor = true;
2790 scheduler_settings_.use_external_begin_frame_source = true;
2791 scheduler_settings_.impl_side_painting = true;
2792 SetUpScheduler(true);
2794 scheduler_->SetNeedsRedraw();
2795 scheduler_->OnDrawForOutputSurface();
2796 EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3);
2797 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
2798 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3);
2799 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2800 client_->Reset();
2802 // Idle on next vsync.
2803 AdvanceFrame();
2804 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2805 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2806 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2807 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2808 client_->Reset();
2811 TEST_F(SchedulerTest, SynchronousCompositorCommit) {
2812 scheduler_settings_.using_synchronous_renderer_compositor = true;
2813 scheduler_settings_.use_external_begin_frame_source = true;
2814 scheduler_settings_.impl_side_painting = true;
2815 SetUpScheduler(true);
2817 scheduler_->SetNeedsCommit();
2818 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2819 client_->Reset();
2821 // Next vsync.
2822 AdvanceFrame();
2823 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2824 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2825 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2826 client_->Reset();
2828 scheduler_->NotifyBeginMainFrameStarted();
2829 EXPECT_NO_ACTION(client_);
2831 // Next vsync.
2832 AdvanceFrame();
2833 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);
2834 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2835 client_->Reset();
2837 scheduler_->NotifyReadyToCommit();
2838 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2839 client_->Reset();
2841 scheduler_->NotifyReadyToActivate();
2842 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2843 client_->Reset();
2845 // Next vsync.
2846 AdvanceFrame();
2847 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2848 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 3);
2849 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3);
2850 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2851 client_->Reset();
2853 // Android onDraw.
2854 scheduler_->SetNeedsRedraw();
2855 scheduler_->OnDrawForOutputSurface();
2856 EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_);
2857 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2858 client_->Reset();
2860 // Idle on next vsync.
2861 AdvanceFrame();
2862 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3);
2863 EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3);
2864 EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3);
2865 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2866 client_->Reset();
2869 TEST_F(SchedulerTest, SynchronousCompositorDoubleCommitWithoutDraw) {
2870 scheduler_settings_.using_synchronous_renderer_compositor = true;
2871 scheduler_settings_.use_external_begin_frame_source = true;
2872 scheduler_settings_.impl_side_painting = true;
2873 SetUpScheduler(true);
2875 scheduler_->SetNeedsCommit();
2876 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
2877 client_->Reset();
2879 // Next vsync.
2880 AdvanceFrame();
2881 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2);
2882 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2);
2883 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2884 client_->Reset();
2886 scheduler_->NotifyBeginMainFrameStarted();
2887 EXPECT_NO_ACTION(client_);
2889 scheduler_->NotifyReadyToCommit();
2890 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2891 client_->Reset();
2893 scheduler_->NotifyReadyToActivate();
2894 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_);
2895 client_->Reset();
2897 // Ask for another commit.
2898 scheduler_->SetNeedsCommit();
2900 AdvanceFrame();
2901 EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4);
2902 EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4);
2903 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4);
2904 EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 3, 4);
2905 EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
2906 client_->Reset();
2908 scheduler_->NotifyBeginMainFrameStarted();
2909 EXPECT_NO_ACTION(client_);
2911 // Allow new commit even though previous commit hasn't been drawn.
2912 scheduler_->NotifyReadyToCommit();
2913 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_);
2914 client_->Reset();
2917 TEST_F(SchedulerTest, AuthoritativeVSyncInterval) {
2918 SetUpScheduler(true);
2919 base::TimeDelta initial_interval = scheduler_->BeginImplFrameInterval();
2920 base::TimeDelta authoritative_interval =
2921 base::TimeDelta::FromMilliseconds(33);
2923 scheduler_->SetNeedsCommit();
2924 EXPECT_SCOPED(AdvanceFrame());
2926 EXPECT_EQ(initial_interval, scheduler_->BeginImplFrameInterval());
2928 scheduler_->NotifyBeginMainFrameStarted();
2929 scheduler_->NotifyReadyToCommit();
2930 task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true));
2932 scheduler_->SetAuthoritativeVSyncInterval(authoritative_interval);
2934 EXPECT_SCOPED(AdvanceFrame());
2936 // At the next BeginFrame, authoritative interval is used instead of previous
2937 // interval.
2938 EXPECT_NE(initial_interval, scheduler_->BeginImplFrameInterval());
2939 EXPECT_EQ(authoritative_interval, scheduler_->BeginImplFrameInterval());
2942 } // namespace
2943 } // namespace cc