Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / cc / scheduler / scheduler_unittest.cc
blob7d61df36d3cc8692c7f9af50a27963a2e0e252ef
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/debug/trace_event.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/power_monitor/power_monitor.h"
15 #include "base/power_monitor/power_monitor_source.h"
16 #include "base/run_loop.h"
17 #include "base/time/time.h"
18 #include "cc/test/begin_frame_args_test.h"
19 #include "cc/test/ordered_simple_task_runner.h"
20 #include "cc/test/scheduler_test_common.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
25 do { \
26 EXPECT_EQ(expected_num_actions, client.num_actions_()); \
27 if (action_index >= 0) { \
28 ASSERT_LT(action_index, client.num_actions_()) << scheduler; \
29 EXPECT_STREQ(action, client.Action(action_index)); \
30 } \
31 for (int i = expected_num_actions; i < client.num_actions_(); ++i) \
32 ADD_FAILURE() << "Unexpected action: " << client.Action(i) \
33 << " with state:\n" << client.StateForAction(i); \
34 } while (false)
36 #define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0)
38 #define EXPECT_SINGLE_ACTION(action, client) \
39 EXPECT_ACTION(action, client, 0, 1)
41 namespace cc {
42 namespace {
44 class FakeSchedulerClient;
46 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler,
47 FakeSchedulerClient* client);
49 class FakeSchedulerClient : public SchedulerClient {
50 public:
51 class FakeExternalBeginFrameSource : public BeginFrameSourceMixIn {
52 public:
53 explicit FakeExternalBeginFrameSource(FakeSchedulerClient* client)
54 : client_(client) {}
55 virtual ~FakeExternalBeginFrameSource() {}
57 void OnNeedsBeginFramesChange(bool needs_begin_frames) override {
58 if (needs_begin_frames) {
59 client_->actions_.push_back("SetNeedsBeginFrames(true)");
60 } else {
61 client_->actions_.push_back("SetNeedsBeginFrames(false)");
63 client_->states_.push_back(client_->scheduler_->AsValue());
66 void TestOnBeginFrame(const BeginFrameArgs& args) {
67 return CallOnBeginFrame(args);
70 private:
71 FakeSchedulerClient* client_;
74 class FakePowerMonitorSource : public base::PowerMonitorSource {
75 public:
76 FakePowerMonitorSource() {}
77 ~FakePowerMonitorSource() override {}
78 void GeneratePowerStateEvent(bool on_battery_power) {
79 on_battery_power_impl_ = on_battery_power;
80 ProcessPowerEvent(POWER_STATE_EVENT);
81 base::MessageLoop::current()->RunUntilIdle();
83 bool IsOnBatteryPowerImpl() override { return on_battery_power_impl_; }
85 private:
86 bool on_battery_power_impl_;
89 FakeSchedulerClient()
90 : automatic_swap_ack_(true),
91 now_src_(TestNowSource::Create()),
92 task_runner_(new OrderedSimpleTaskRunner(now_src_, true)),
93 fake_external_begin_frame_source_(nullptr),
94 fake_power_monitor_source_(new FakePowerMonitorSource),
95 power_monitor_(make_scoped_ptr<base::PowerMonitorSource>(
96 fake_power_monitor_source_)),
97 scheduler_(nullptr) {
98 // A bunch of tests require Now() to be > BeginFrameArgs::DefaultInterval()
99 now_src_->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
100 // Fail if we need to run 100 tasks in a row.
101 task_runner_->SetRunTaskLimit(100);
102 Reset();
105 void Reset() {
106 actions_.clear();
107 states_.clear();
108 draw_will_happen_ = true;
109 swap_will_happen_if_draw_happens_ = true;
110 num_draws_ = 0;
111 log_anticipated_draw_time_change_ = false;
114 TestScheduler* CreateScheduler(const SchedulerSettings& settings) {
115 scoped_ptr<FakeExternalBeginFrameSource> fake_external_begin_frame_source;
116 if (settings.use_external_begin_frame_source &&
117 settings.throttle_frame_production) {
118 fake_external_begin_frame_source.reset(
119 new FakeExternalBeginFrameSource(this));
120 fake_external_begin_frame_source_ =
121 fake_external_begin_frame_source.get();
123 scheduler_ = TestScheduler::Create(now_src_,
124 this,
125 settings,
127 task_runner_,
128 &power_monitor_,
129 fake_external_begin_frame_source.Pass());
130 DCHECK(scheduler_);
131 return scheduler_.get();
134 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
135 // for tests that do.
136 void set_log_anticipated_draw_time_change(bool log) {
137 log_anticipated_draw_time_change_ = log;
139 bool needs_begin_frames() {
140 DCHECK(ExternalBeginFrame());
141 return fake_external_begin_frame_source_->NeedsBeginFrames();
143 int num_draws() const { return num_draws_; }
144 int num_actions_() const { return static_cast<int>(actions_.size()); }
145 const char* Action(int i) const { return actions_[i]; }
146 std::string StateForAction(int i) const { return states_[i]->ToString(); }
147 base::TimeTicks posted_begin_impl_frame_deadline() const {
148 return posted_begin_impl_frame_deadline_;
151 bool ExternalBeginFrame() {
152 return scheduler_->settings().use_external_begin_frame_source &&
153 scheduler_->settings().throttle_frame_production;
156 FakeExternalBeginFrameSource* fake_external_begin_frame_source() const {
157 return fake_external_begin_frame_source_;
160 base::PowerMonitor* PowerMonitor() { return &power_monitor_; }
162 FakePowerMonitorSource* PowerMonitorSource() {
163 return fake_power_monitor_source_;
166 void AdvanceFrame() {
167 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"),
168 "FakeSchedulerClient::AdvanceFrame");
169 if (ExternalBeginFrame()) {
170 // Creep the time forward so that any BeginFrameArgs is not equal to the
171 // last one otherwise we violate the BeginFrameSource contract.
172 now_src_->AdvanceNowMicroseconds(1);
173 fake_external_begin_frame_source_->TestOnBeginFrame(
174 CreateBeginFrameArgsForTesting(now_src_));
175 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
178 EXPECT_TRUE(task_runner().RunTasksWhile(ImplFrameDeadlinePending(false)));
179 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
182 OrderedSimpleTaskRunner& task_runner() { return *task_runner_; }
183 TestNowSource* now_src() { return now_src_.get(); }
185 int ActionIndex(const char* action) const {
186 for (size_t i = 0; i < actions_.size(); i++)
187 if (!strcmp(actions_[i], action))
188 return i;
189 return -1;
192 bool HasAction(const char* action) const {
193 return ActionIndex(action) >= 0;
196 void SetDrawWillHappen(bool draw_will_happen) {
197 draw_will_happen_ = draw_will_happen;
199 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
200 swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
202 void SetAutomaticSwapAck(bool automatic_swap_ack) {
203 automatic_swap_ack_ = automatic_swap_ack;
205 // SchedulerClient implementation.
206 void WillBeginImplFrame(const BeginFrameArgs& args) override {
207 actions_.push_back("WillBeginImplFrame");
208 states_.push_back(scheduler_->AsValue());
210 void ScheduledActionSendBeginMainFrame() override {
211 actions_.push_back("ScheduledActionSendBeginMainFrame");
212 states_.push_back(scheduler_->AsValue());
214 void ScheduledActionAnimate() override {
215 actions_.push_back("ScheduledActionAnimate");
216 states_.push_back(scheduler_->AsValue());
218 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
219 actions_.push_back("ScheduledActionDrawAndSwapIfPossible");
220 states_.push_back(scheduler_->AsValue());
221 num_draws_++;
222 DrawResult result =
223 draw_will_happen_ ? DRAW_SUCCESS : DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
224 bool swap_will_happen =
225 draw_will_happen_ && swap_will_happen_if_draw_happens_;
226 if (swap_will_happen) {
227 scheduler_->DidSwapBuffers();
229 if (automatic_swap_ack_)
230 scheduler_->DidSwapBuffersComplete();
232 return result;
234 DrawResult ScheduledActionDrawAndSwapForced() override {
235 actions_.push_back("ScheduledActionDrawAndSwapForced");
236 states_.push_back(scheduler_->AsValue());
237 return DRAW_SUCCESS;
239 void ScheduledActionCommit() override {
240 actions_.push_back("ScheduledActionCommit");
241 states_.push_back(scheduler_->AsValue());
243 void ScheduledActionActivateSyncTree() override {
244 actions_.push_back("ScheduledActionActivateSyncTree");
245 states_.push_back(scheduler_->AsValue());
247 void ScheduledActionBeginOutputSurfaceCreation() override {
248 actions_.push_back("ScheduledActionBeginOutputSurfaceCreation");
249 states_.push_back(scheduler_->AsValue());
251 void ScheduledActionManageTiles() override {
252 actions_.push_back("ScheduledActionManageTiles");
253 states_.push_back(scheduler_->AsValue());
255 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {
256 if (log_anticipated_draw_time_change_)
257 actions_.push_back("DidAnticipatedDrawTimeChange");
259 base::TimeDelta DrawDurationEstimate() override { return base::TimeDelta(); }
260 base::TimeDelta BeginMainFrameToCommitDurationEstimate() override {
261 return base::TimeDelta();
263 base::TimeDelta CommitToActivateDurationEstimate() override {
264 return base::TimeDelta();
267 void DidBeginImplFrameDeadline() override {}
269 base::Callback<bool(void)> ImplFrameDeadlinePending(bool state) {
270 return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback,
271 base::Unretained(this),
272 state);
275 protected:
276 bool ImplFrameDeadlinePendingCallback(bool state) {
277 return scheduler_->BeginImplFrameDeadlinePending() == state;
280 bool draw_will_happen_;
281 bool swap_will_happen_if_draw_happens_;
282 bool automatic_swap_ack_;
283 int num_draws_;
284 bool log_anticipated_draw_time_change_;
285 base::TimeTicks posted_begin_impl_frame_deadline_;
286 std::vector<const char*> actions_;
287 std::vector<scoped_refptr<base::debug::ConvertableToTraceFormat>> states_;
288 scoped_refptr<TestNowSource> now_src_;
289 scoped_refptr<OrderedSimpleTaskRunner> task_runner_;
290 FakeExternalBeginFrameSource* fake_external_begin_frame_source_;
291 FakePowerMonitorSource* fake_power_monitor_source_;
292 base::PowerMonitor power_monitor_;
293 scoped_ptr<TestScheduler> scheduler_;
296 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler,
297 FakeSchedulerClient* client) {
298 TRACE_EVENT0("cc",
299 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit");
301 scheduler->DidCreateAndInitializeOutputSurface();
302 scheduler->SetNeedsCommit();
303 scheduler->NotifyBeginMainFrameStarted();
304 scheduler->NotifyReadyToCommit();
305 if (scheduler->settings().impl_side_painting)
306 scheduler->NotifyReadyToActivate();
309 SCOPED_TRACE("Go through the motions to draw the commit");
310 client->AdvanceFrame();
313 // Run the posted deadline task.
314 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
315 client->task_runner().RunTasksWhile(client->ImplFrameDeadlinePending(true));
316 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
319 SCOPED_TRACE(
320 "We need another BeginImplFrame so Scheduler calls "
321 "SetNeedsBeginFrame(false).");
322 client->AdvanceFrame();
325 // Run the posted deadline task.
326 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
327 client->task_runner().RunTasksWhile(client->ImplFrameDeadlinePending(true));
328 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
331 TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) {
332 FakeSchedulerClient client;
333 SchedulerSettings scheduler_settings;
334 scheduler_settings.use_external_begin_frame_source = true;
335 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
336 scheduler->SetCanStart();
337 scheduler->SetVisible(true);
338 scheduler->SetCanDraw(true);
340 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
341 client.Reset();
342 scheduler->DidCreateAndInitializeOutputSurface();
343 EXPECT_NO_ACTION(client);
346 TEST(SchedulerTest, RequestCommit) {
347 FakeSchedulerClient client;
348 SchedulerSettings scheduler_settings;
349 scheduler_settings.use_external_begin_frame_source = true;
350 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
351 scheduler->SetCanStart();
352 scheduler->SetVisible(true);
353 scheduler->SetCanDraw(true);
355 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
356 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
358 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
359 client.Reset();
360 scheduler->SetNeedsCommit();
361 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
362 client.Reset();
364 client.AdvanceFrame();
365 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
366 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
367 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
368 EXPECT_TRUE(client.needs_begin_frames());
369 client.Reset();
371 // If we don't swap on the deadline, we wait for the next BeginFrame.
372 client.task_runner().RunPendingTasks(); // Run posted deadline.
373 EXPECT_NO_ACTION(client);
374 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
375 EXPECT_TRUE(client.needs_begin_frames());
376 client.Reset();
378 // NotifyReadyToCommit should trigger the commit.
379 scheduler->NotifyBeginMainFrameStarted();
380 scheduler->NotifyReadyToCommit();
381 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
382 EXPECT_TRUE(client.needs_begin_frames());
383 client.Reset();
385 // BeginImplFrame should prepare the draw.
386 client.AdvanceFrame();
387 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
388 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
389 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
390 EXPECT_TRUE(client.needs_begin_frames());
391 client.Reset();
393 // BeginImplFrame deadline should draw.
394 client.task_runner().RunPendingTasks(); // Run posted deadline.
395 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
396 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
397 EXPECT_TRUE(client.needs_begin_frames());
398 client.Reset();
400 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
401 // to avoid excessive toggles.
402 client.AdvanceFrame();
403 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
404 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
405 client.Reset();
407 client.task_runner().RunPendingTasks(); // Run posted deadline.
408 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client);
409 client.Reset();
412 TEST(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
413 FakeSchedulerClient client;
414 SchedulerSettings scheduler_settings;
415 scheduler_settings.use_external_begin_frame_source = true;
416 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
417 scheduler->SetCanStart();
418 scheduler->SetVisible(true);
419 scheduler->SetCanDraw(true);
421 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
422 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
423 client.Reset();
425 // SetNeedsCommit should begin the frame.
426 scheduler->SetNeedsCommit();
427 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
429 client.Reset();
430 client.AdvanceFrame();
431 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
432 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
433 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
435 EXPECT_TRUE(client.needs_begin_frames());
436 client.Reset();
438 // Now SetNeedsCommit again. Calling here means we need a second commit.
439 scheduler->SetNeedsCommit();
440 EXPECT_EQ(client.num_actions_(), 0);
441 client.Reset();
443 // Finish the first commit.
444 scheduler->NotifyBeginMainFrameStarted();
445 scheduler->NotifyReadyToCommit();
446 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
447 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
448 client.Reset();
449 client.task_runner().RunPendingTasks(); // Run posted deadline.
450 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
451 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
452 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
454 // Because we just swapped, the Scheduler should also request the next
455 // BeginImplFrame from the OutputSurface.
456 EXPECT_TRUE(client.needs_begin_frames());
457 client.Reset();
458 // Since another commit is needed, the next BeginImplFrame should initiate
459 // the second commit.
460 client.AdvanceFrame();
461 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
462 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
463 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
464 client.Reset();
466 // Finishing the commit before the deadline should post a new deadline task
467 // to trigger the deadline early.
468 scheduler->NotifyBeginMainFrameStarted();
469 scheduler->NotifyReadyToCommit();
470 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
471 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
472 client.Reset();
473 client.task_runner().RunPendingTasks(); // Run posted deadline.
474 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
475 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
476 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
477 EXPECT_TRUE(client.needs_begin_frames());
478 client.Reset();
480 // On the next BeginImplFrame, verify we go back to a quiescent state and
481 // no longer request BeginImplFrames.
482 client.AdvanceFrame();
483 client.task_runner().RunPendingTasks(); // Run posted deadline.
484 EXPECT_FALSE(client.needs_begin_frames());
485 client.Reset();
488 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
489 public:
490 void ScheduledActionSendBeginMainFrame() override {}
491 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
492 // Only SetNeedsRedraw the first time this is called
493 if (!num_draws_)
494 scheduler_->SetNeedsRedraw();
495 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
498 DrawResult ScheduledActionDrawAndSwapForced() override {
499 NOTREACHED();
500 return DRAW_SUCCESS;
503 void ScheduledActionCommit() override {}
504 void ScheduledActionBeginOutputSurfaceCreation() override {}
505 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {}
508 // Tests for two different situations:
509 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
510 // a ScheduledActionDrawAndSwap
511 // 2. the scheduler drawing twice inside a single tick
512 TEST(SchedulerTest, RequestRedrawInsideDraw) {
513 SchedulerClientThatsetNeedsDrawInsideDraw client;
514 SchedulerSettings scheduler_settings;
515 scheduler_settings.use_external_begin_frame_source = true;
516 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
517 scheduler->SetCanStart();
518 scheduler->SetVisible(true);
519 scheduler->SetCanDraw(true);
520 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
521 client.Reset();
523 scheduler->SetNeedsRedraw();
524 EXPECT_TRUE(scheduler->RedrawPending());
525 EXPECT_TRUE(client.needs_begin_frames());
526 EXPECT_EQ(0, client.num_draws());
528 client.AdvanceFrame();
529 client.task_runner().RunPendingTasks(); // Run posted deadline.
530 EXPECT_EQ(1, client.num_draws());
531 EXPECT_TRUE(scheduler->RedrawPending());
532 EXPECT_TRUE(client.needs_begin_frames());
534 client.AdvanceFrame();
535 client.task_runner().RunPendingTasks(); // Run posted deadline.
536 EXPECT_EQ(2, client.num_draws());
537 EXPECT_FALSE(scheduler->RedrawPending());
538 EXPECT_TRUE(client.needs_begin_frames());
540 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
541 // swap.
542 client.AdvanceFrame();
543 client.task_runner().RunPendingTasks(); // Run posted deadline.
544 EXPECT_EQ(2, client.num_draws());
545 EXPECT_FALSE(scheduler->RedrawPending());
546 EXPECT_FALSE(client.needs_begin_frames());
549 // Test that requesting redraw inside a failed draw doesn't lose the request.
550 TEST(SchedulerTest, RequestRedrawInsideFailedDraw) {
551 SchedulerClientThatsetNeedsDrawInsideDraw client;
552 SchedulerSettings scheduler_settings;
553 scheduler_settings.use_external_begin_frame_source = true;
554 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
555 scheduler->SetCanStart();
556 scheduler->SetVisible(true);
557 scheduler->SetCanDraw(true);
558 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
559 client.Reset();
561 client.SetDrawWillHappen(false);
563 scheduler->SetNeedsRedraw();
564 EXPECT_TRUE(scheduler->RedrawPending());
565 EXPECT_TRUE(client.needs_begin_frames());
566 EXPECT_EQ(0, client.num_draws());
568 // Fail the draw.
569 client.AdvanceFrame();
570 client.task_runner().RunPendingTasks(); // Run posted deadline.
571 EXPECT_EQ(1, client.num_draws());
573 // We have a commit pending and the draw failed, and we didn't lose the redraw
574 // request.
575 EXPECT_TRUE(scheduler->CommitPending());
576 EXPECT_TRUE(scheduler->RedrawPending());
577 EXPECT_TRUE(client.needs_begin_frames());
579 // Fail the draw again.
580 client.AdvanceFrame();
581 client.task_runner().RunPendingTasks(); // Run posted deadline.
582 EXPECT_EQ(2, client.num_draws());
583 EXPECT_TRUE(scheduler->CommitPending());
584 EXPECT_TRUE(scheduler->RedrawPending());
585 EXPECT_TRUE(client.needs_begin_frames());
587 // Draw successfully.
588 client.SetDrawWillHappen(true);
589 client.AdvanceFrame();
590 client.task_runner().RunPendingTasks(); // Run posted deadline.
591 EXPECT_EQ(3, client.num_draws());
592 EXPECT_TRUE(scheduler->CommitPending());
593 EXPECT_FALSE(scheduler->RedrawPending());
594 EXPECT_TRUE(client.needs_begin_frames());
597 class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
598 public:
599 SchedulerClientThatSetNeedsCommitInsideDraw()
600 : set_needs_commit_on_next_draw_(false) {}
602 void ScheduledActionSendBeginMainFrame() override {}
603 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
604 // Only SetNeedsCommit the first time this is called
605 if (set_needs_commit_on_next_draw_) {
606 scheduler_->SetNeedsCommit();
607 set_needs_commit_on_next_draw_ = false;
609 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
612 DrawResult ScheduledActionDrawAndSwapForced() override {
613 NOTREACHED();
614 return DRAW_SUCCESS;
617 void ScheduledActionCommit() override {}
618 void ScheduledActionBeginOutputSurfaceCreation() override {}
619 void DidAnticipatedDrawTimeChange(base::TimeTicks) override {}
621 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; }
623 private:
624 bool set_needs_commit_on_next_draw_;
627 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
628 // happen inside a ScheduledActionDrawAndSwap
629 TEST(SchedulerTest, RequestCommitInsideDraw) {
630 SchedulerClientThatSetNeedsCommitInsideDraw client;
631 SchedulerSettings scheduler_settings;
632 scheduler_settings.use_external_begin_frame_source = true;
633 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
634 scheduler->SetCanStart();
635 scheduler->SetVisible(true);
636 scheduler->SetCanDraw(true);
637 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
638 client.Reset();
640 EXPECT_FALSE(client.needs_begin_frames());
641 scheduler->SetNeedsRedraw();
642 EXPECT_TRUE(scheduler->RedrawPending());
643 EXPECT_EQ(0, client.num_draws());
644 EXPECT_TRUE(client.needs_begin_frames());
646 client.SetNeedsCommitOnNextDraw();
647 client.AdvanceFrame();
648 client.SetNeedsCommitOnNextDraw();
649 client.task_runner().RunPendingTasks(); // Run posted deadline.
650 EXPECT_EQ(1, client.num_draws());
651 EXPECT_TRUE(scheduler->CommitPending());
652 EXPECT_TRUE(client.needs_begin_frames());
653 scheduler->NotifyBeginMainFrameStarted();
654 scheduler->NotifyReadyToCommit();
656 client.AdvanceFrame();
657 client.task_runner().RunPendingTasks(); // Run posted deadline.
658 EXPECT_EQ(2, client.num_draws());
660 EXPECT_FALSE(scheduler->RedrawPending());
661 EXPECT_FALSE(scheduler->CommitPending());
662 EXPECT_TRUE(client.needs_begin_frames());
664 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
665 // swap.
666 client.AdvanceFrame();
667 client.task_runner().RunPendingTasks(); // Run posted deadline.
668 EXPECT_EQ(2, client.num_draws());
669 EXPECT_FALSE(scheduler->RedrawPending());
670 EXPECT_FALSE(scheduler->CommitPending());
671 EXPECT_FALSE(client.needs_begin_frames());
674 // Tests that when a draw fails then the pending commit should not be dropped.
675 TEST(SchedulerTest, RequestCommitInsideFailedDraw) {
676 SchedulerClientThatsetNeedsDrawInsideDraw client;
677 SchedulerSettings scheduler_settings;
678 scheduler_settings.use_external_begin_frame_source = true;
679 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
680 scheduler->SetCanStart();
681 scheduler->SetVisible(true);
682 scheduler->SetCanDraw(true);
683 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
684 client.Reset();
686 client.SetDrawWillHappen(false);
688 scheduler->SetNeedsRedraw();
689 EXPECT_TRUE(scheduler->RedrawPending());
690 EXPECT_TRUE(client.needs_begin_frames());
691 EXPECT_EQ(0, client.num_draws());
693 // Fail the draw.
694 client.AdvanceFrame();
695 client.task_runner().RunPendingTasks(); // Run posted deadline.
696 EXPECT_EQ(1, client.num_draws());
698 // We have a commit pending and the draw failed, and we didn't lose the commit
699 // request.
700 EXPECT_TRUE(scheduler->CommitPending());
701 EXPECT_TRUE(scheduler->RedrawPending());
702 EXPECT_TRUE(client.needs_begin_frames());
704 // Fail the draw again.
705 client.AdvanceFrame();
707 client.task_runner().RunPendingTasks(); // Run posted deadline.
708 EXPECT_EQ(2, client.num_draws());
709 EXPECT_TRUE(scheduler->CommitPending());
710 EXPECT_TRUE(scheduler->RedrawPending());
711 EXPECT_TRUE(client.needs_begin_frames());
713 // Draw successfully.
714 client.SetDrawWillHappen(true);
715 client.AdvanceFrame();
716 client.task_runner().RunPendingTasks(); // Run posted deadline.
717 EXPECT_EQ(3, client.num_draws());
718 EXPECT_TRUE(scheduler->CommitPending());
719 EXPECT_FALSE(scheduler->RedrawPending());
720 EXPECT_TRUE(client.needs_begin_frames());
723 TEST(SchedulerTest, NoSwapWhenDrawFails) {
724 SchedulerClientThatSetNeedsCommitInsideDraw client;
725 SchedulerSettings scheduler_settings;
726 scheduler_settings.use_external_begin_frame_source = true;
727 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
728 scheduler->SetCanStart();
729 scheduler->SetVisible(true);
730 scheduler->SetCanDraw(true);
731 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
732 client.Reset();
734 scheduler->SetNeedsRedraw();
735 EXPECT_TRUE(scheduler->RedrawPending());
736 EXPECT_TRUE(client.needs_begin_frames());
737 EXPECT_EQ(0, client.num_draws());
739 // Draw successfully, this starts a new frame.
740 client.SetNeedsCommitOnNextDraw();
741 client.AdvanceFrame();
742 client.task_runner().RunPendingTasks(); // Run posted deadline.
743 EXPECT_EQ(1, client.num_draws());
745 scheduler->SetNeedsRedraw();
746 EXPECT_TRUE(scheduler->RedrawPending());
747 EXPECT_TRUE(client.needs_begin_frames());
749 // Fail to draw, this should not start a frame.
750 client.SetDrawWillHappen(false);
751 client.SetNeedsCommitOnNextDraw();
752 client.AdvanceFrame();
753 client.task_runner().RunPendingTasks(); // Run posted deadline.
754 EXPECT_EQ(2, client.num_draws());
757 class SchedulerClientNeedsManageTilesInDraw : public FakeSchedulerClient {
758 public:
759 DrawResult ScheduledActionDrawAndSwapIfPossible() override {
760 scheduler_->SetNeedsManageTiles();
761 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
765 // Test manage tiles is independant of draws.
766 TEST(SchedulerTest, ManageTiles) {
767 SchedulerClientNeedsManageTilesInDraw client;
768 SchedulerSettings scheduler_settings;
769 scheduler_settings.use_external_begin_frame_source = true;
770 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
771 scheduler->SetCanStart();
772 scheduler->SetVisible(true);
773 scheduler->SetCanDraw(true);
774 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
776 // Request both draw and manage tiles. ManageTiles shouldn't
777 // be trigged until BeginImplFrame.
778 client.Reset();
779 scheduler->SetNeedsManageTiles();
780 scheduler->SetNeedsRedraw();
781 EXPECT_TRUE(scheduler->RedrawPending());
782 EXPECT_TRUE(scheduler->ManageTilesPending());
783 EXPECT_TRUE(client.needs_begin_frames());
784 EXPECT_EQ(0, client.num_draws());
785 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
786 EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
788 // We have no immediate actions to perform, so the BeginImplFrame should post
789 // the deadline task.
790 client.Reset();
791 client.AdvanceFrame();
792 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
793 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
794 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
796 // On the deadline, he actions should have occured in the right order.
797 client.Reset();
798 client.task_runner().RunPendingTasks(); // Run posted deadline.
799 EXPECT_EQ(1, client.num_draws());
800 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
801 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
802 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
803 client.ActionIndex("ScheduledActionManageTiles"));
804 EXPECT_FALSE(scheduler->RedrawPending());
805 EXPECT_FALSE(scheduler->ManageTilesPending());
806 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
808 // Request a draw. We don't need a ManageTiles yet.
809 client.Reset();
810 scheduler->SetNeedsRedraw();
811 EXPECT_TRUE(scheduler->RedrawPending());
812 EXPECT_FALSE(scheduler->ManageTilesPending());
813 EXPECT_TRUE(client.needs_begin_frames());
814 EXPECT_EQ(0, client.num_draws());
816 // We have no immediate actions to perform, so the BeginImplFrame should post
817 // the deadline task.
818 client.Reset();
819 client.AdvanceFrame();
820 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
821 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
822 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
824 // Draw. The draw will trigger SetNeedsManageTiles, and
825 // then the ManageTiles action will be triggered after the Draw.
826 // Afterwards, neither a draw nor ManageTiles are pending.
827 client.Reset();
828 client.task_runner().RunPendingTasks(); // Run posted deadline.
829 EXPECT_EQ(1, client.num_draws());
830 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
831 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
832 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
833 client.ActionIndex("ScheduledActionManageTiles"));
834 EXPECT_FALSE(scheduler->RedrawPending());
835 EXPECT_FALSE(scheduler->ManageTilesPending());
836 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
838 // We need a BeginImplFrame where we don't swap to go idle.
839 client.Reset();
840 client.AdvanceFrame();
841 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
842 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
843 client.Reset();
844 client.task_runner().RunPendingTasks(); // Run posted deadline.
845 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client);
846 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
847 EXPECT_EQ(0, client.num_draws());
849 // Now trigger a ManageTiles outside of a draw. We will then need
850 // a begin-frame for the ManageTiles, but we don't need a draw.
851 client.Reset();
852 EXPECT_FALSE(client.needs_begin_frames());
853 scheduler->SetNeedsManageTiles();
854 EXPECT_TRUE(client.needs_begin_frames());
855 EXPECT_TRUE(scheduler->ManageTilesPending());
856 EXPECT_FALSE(scheduler->RedrawPending());
858 // BeginImplFrame. There will be no draw, only ManageTiles.
859 client.Reset();
860 client.AdvanceFrame();
861 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
862 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
863 client.Reset();
864 client.task_runner().RunPendingTasks(); // Run posted deadline.
865 EXPECT_EQ(0, client.num_draws());
866 EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
867 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
868 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
871 // Test that ManageTiles only happens once per frame. If an external caller
872 // initiates it, then the state machine should not ManageTiles on that frame.
873 TEST(SchedulerTest, ManageTilesOncePerFrame) {
874 FakeSchedulerClient client;
875 SchedulerSettings scheduler_settings;
876 scheduler_settings.use_external_begin_frame_source = true;
877 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
878 scheduler->SetCanStart();
879 scheduler->SetVisible(true);
880 scheduler->SetCanDraw(true);
881 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
883 // If DidManageTiles during a frame, then ManageTiles should not occur again.
884 scheduler->SetNeedsManageTiles();
885 scheduler->SetNeedsRedraw();
886 client.Reset();
887 client.AdvanceFrame();
888 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
889 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
890 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
892 EXPECT_TRUE(scheduler->ManageTilesPending());
893 scheduler->DidManageTiles(); // An explicit ManageTiles.
894 EXPECT_FALSE(scheduler->ManageTilesPending());
896 client.Reset();
897 client.task_runner().RunPendingTasks(); // Run posted deadline.
898 EXPECT_EQ(1, client.num_draws());
899 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
900 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
901 EXPECT_FALSE(scheduler->RedrawPending());
902 EXPECT_FALSE(scheduler->ManageTilesPending());
903 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
905 // Next frame without DidManageTiles should ManageTiles with draw.
906 scheduler->SetNeedsManageTiles();
907 scheduler->SetNeedsRedraw();
908 client.Reset();
909 client.AdvanceFrame();
910 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
911 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
912 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
914 client.Reset();
915 client.task_runner().RunPendingTasks(); // Run posted deadline.
916 EXPECT_EQ(1, client.num_draws());
917 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
918 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
919 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
920 client.ActionIndex("ScheduledActionManageTiles"));
921 EXPECT_FALSE(scheduler->RedrawPending());
922 EXPECT_FALSE(scheduler->ManageTilesPending());
923 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
924 scheduler->DidManageTiles(); // Corresponds to ScheduledActionManageTiles
926 // If we get another DidManageTiles within the same frame, we should
927 // not ManageTiles on the next frame.
928 scheduler->DidManageTiles(); // An explicit ManageTiles.
929 scheduler->SetNeedsManageTiles();
930 scheduler->SetNeedsRedraw();
931 client.Reset();
932 client.AdvanceFrame();
933 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
934 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
935 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
937 EXPECT_TRUE(scheduler->ManageTilesPending());
939 client.Reset();
940 client.task_runner().RunPendingTasks(); // Run posted deadline.
941 EXPECT_EQ(1, client.num_draws());
942 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
943 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
944 EXPECT_FALSE(scheduler->RedrawPending());
945 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
947 // If we get another DidManageTiles, we should not ManageTiles on the next
948 // frame. This verifies we don't alternate calling ManageTiles once and twice.
949 EXPECT_TRUE(scheduler->ManageTilesPending());
950 scheduler->DidManageTiles(); // An explicit ManageTiles.
951 EXPECT_FALSE(scheduler->ManageTilesPending());
952 scheduler->SetNeedsManageTiles();
953 scheduler->SetNeedsRedraw();
954 client.Reset();
955 client.AdvanceFrame();
956 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
957 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
958 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
960 EXPECT_TRUE(scheduler->ManageTilesPending());
962 client.Reset();
963 client.task_runner().RunPendingTasks(); // Run posted deadline.
964 EXPECT_EQ(1, client.num_draws());
965 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
966 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
967 EXPECT_FALSE(scheduler->RedrawPending());
968 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
970 // Next frame without DidManageTiles should ManageTiles with draw.
971 scheduler->SetNeedsManageTiles();
972 scheduler->SetNeedsRedraw();
973 client.Reset();
974 client.AdvanceFrame();
975 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
976 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
977 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
979 client.Reset();
980 client.task_runner().RunPendingTasks(); // Run posted deadline.
981 EXPECT_EQ(1, client.num_draws());
982 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
983 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
984 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
985 client.ActionIndex("ScheduledActionManageTiles"));
986 EXPECT_FALSE(scheduler->RedrawPending());
987 EXPECT_FALSE(scheduler->ManageTilesPending());
988 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
989 scheduler->DidManageTiles(); // Corresponds to ScheduledActionManageTiles
992 TEST(SchedulerTest, TriggerBeginFrameDeadlineEarly) {
993 SchedulerClientNeedsManageTilesInDraw client;
994 SchedulerSettings scheduler_settings;
995 scheduler_settings.use_external_begin_frame_source = true;
996 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
997 scheduler->SetCanStart();
998 scheduler->SetVisible(true);
999 scheduler->SetCanDraw(true);
1000 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1002 client.Reset();
1003 scheduler->SetNeedsRedraw();
1004 client.AdvanceFrame();
1006 // The deadline should be zero since there is no work other than drawing
1007 // pending.
1008 EXPECT_EQ(base::TimeTicks(), client.posted_begin_impl_frame_deadline());
1011 class SchedulerClientWithFixedEstimates : public FakeSchedulerClient {
1012 public:
1013 SchedulerClientWithFixedEstimates(
1014 base::TimeDelta draw_duration,
1015 base::TimeDelta begin_main_frame_to_commit_duration,
1016 base::TimeDelta commit_to_activate_duration)
1017 : draw_duration_(draw_duration),
1018 begin_main_frame_to_commit_duration_(
1019 begin_main_frame_to_commit_duration),
1020 commit_to_activate_duration_(commit_to_activate_duration) {}
1022 base::TimeDelta DrawDurationEstimate() override { return draw_duration_; }
1023 base::TimeDelta BeginMainFrameToCommitDurationEstimate() override {
1024 return begin_main_frame_to_commit_duration_;
1026 base::TimeDelta CommitToActivateDurationEstimate() override {
1027 return commit_to_activate_duration_;
1030 private:
1031 base::TimeDelta draw_duration_;
1032 base::TimeDelta begin_main_frame_to_commit_duration_;
1033 base::TimeDelta commit_to_activate_duration_;
1036 void MainFrameInHighLatencyMode(int64 begin_main_frame_to_commit_estimate_in_ms,
1037 int64 commit_to_activate_estimate_in_ms,
1038 bool impl_latency_takes_priority,
1039 bool should_send_begin_main_frame) {
1040 // Set up client with specified estimates (draw duration is set to 1).
1041 SchedulerClientWithFixedEstimates client(
1042 base::TimeDelta::FromMilliseconds(1),
1043 base::TimeDelta::FromMilliseconds(
1044 begin_main_frame_to_commit_estimate_in_ms),
1045 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms));
1046 SchedulerSettings scheduler_settings;
1047 scheduler_settings.use_external_begin_frame_source = true;
1048 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1049 scheduler->SetCanStart();
1050 scheduler->SetVisible(true);
1051 scheduler->SetCanDraw(true);
1052 scheduler->SetImplLatencyTakesPriority(impl_latency_takes_priority);
1053 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1055 // Impl thread hits deadline before commit finishes.
1056 client.Reset();
1057 scheduler->SetNeedsCommit();
1058 EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode());
1059 client.AdvanceFrame();
1060 EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode());
1061 client.task_runner().RunPendingTasks(); // Run posted deadline.
1062 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
1063 scheduler->NotifyBeginMainFrameStarted();
1064 scheduler->NotifyReadyToCommit();
1065 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
1066 EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
1068 client.Reset();
1069 scheduler->SetNeedsCommit();
1070 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
1071 client.AdvanceFrame();
1072 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
1073 client.task_runner().RunPendingTasks(); // Run posted deadline.
1074 EXPECT_EQ(scheduler->MainThreadIsInHighLatencyMode(),
1075 should_send_begin_main_frame);
1076 EXPECT_EQ(client.HasAction("ScheduledActionSendBeginMainFrame"),
1077 should_send_begin_main_frame);
1080 TEST(SchedulerTest,
1081 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) {
1082 // Set up client so that estimates indicate that we can commit and activate
1083 // before the deadline (~8ms by default).
1084 MainFrameInHighLatencyMode(1, 1, false, false);
1087 TEST(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) {
1088 // Set up client so that estimates indicate that the commit cannot finish
1089 // before the deadline (~8ms by default).
1090 MainFrameInHighLatencyMode(10, 1, false, true);
1093 TEST(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) {
1094 // Set up client so that estimates indicate that the activate cannot finish
1095 // before the deadline (~8ms by default).
1096 MainFrameInHighLatencyMode(1, 10, false, true);
1099 TEST(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) {
1100 // Set up client so that estimates indicate that we can commit and activate
1101 // before the deadline (~8ms by default), but also enable impl latency takes
1102 // priority mode.
1103 MainFrameInHighLatencyMode(1, 1, true, true);
1106 TEST(SchedulerTest, PollForCommitCompletion) {
1107 // Since we are simulating a long commit, set up a client with draw duration
1108 // estimates that prevent skipping main frames to get to low latency mode.
1109 SchedulerClientWithFixedEstimates client(
1110 base::TimeDelta::FromMilliseconds(1),
1111 base::TimeDelta::FromMilliseconds(32),
1112 base::TimeDelta::FromMilliseconds(32));
1113 client.set_log_anticipated_draw_time_change(true);
1114 SchedulerSettings scheduler_settings;
1115 scheduler_settings.use_external_begin_frame_source = true;
1116 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1118 scheduler->SetCanDraw(true);
1119 scheduler->SetCanStart();
1120 scheduler->SetVisible(true);
1121 scheduler->DidCreateAndInitializeOutputSurface();
1123 scheduler->SetNeedsCommit();
1124 EXPECT_TRUE(scheduler->CommitPending());
1125 scheduler->NotifyBeginMainFrameStarted();
1126 scheduler->NotifyReadyToCommit();
1127 scheduler->SetNeedsRedraw();
1129 BeginFrameArgs frame_args = CreateBeginFrameArgsForTesting(client.now_src());
1130 frame_args.interval = base::TimeDelta::FromMilliseconds(1000);
1131 client.fake_external_begin_frame_source()->TestOnBeginFrame(frame_args);
1133 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1134 client.task_runner().RunPendingTasks(); // Run posted deadline.
1135 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1137 scheduler->DidSwapBuffers();
1138 scheduler->DidSwapBuffersComplete();
1140 // At this point, we've drawn a frame. Start another commit, but hold off on
1141 // the NotifyReadyToCommit for now.
1142 EXPECT_FALSE(scheduler->CommitPending());
1143 scheduler->SetNeedsCommit();
1144 client.fake_external_begin_frame_source()->TestOnBeginFrame(frame_args);
1145 EXPECT_TRUE(scheduler->CommitPending());
1147 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1148 // blocking on the renderer.
1149 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1150 client.task_runner().RunPendingTasks(); // Run posted deadline.
1151 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1152 scheduler->DidSwapBuffers();
1154 // Spin the event loop a few times and make sure we get more
1155 // DidAnticipateDrawTimeChange calls every time.
1156 int actions_so_far = client.num_actions_();
1158 // Does three iterations to make sure that the timer is properly repeating.
1159 for (int i = 0; i < 3; ++i) {
1160 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1161 client.task_runner().DelayToNextTaskTime().InMicroseconds())
1162 << scheduler->AsValue()->ToString();
1163 client.task_runner().RunPendingTasks();
1164 EXPECT_GT(client.num_actions_(), actions_so_far);
1165 EXPECT_STREQ(client.Action(client.num_actions_() - 1),
1166 "DidAnticipatedDrawTimeChange");
1167 actions_so_far = client.num_actions_();
1170 // Do the same thing after BeginMainFrame starts but still before activation.
1171 scheduler->NotifyBeginMainFrameStarted();
1172 for (int i = 0; i < 3; ++i) {
1173 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1174 client.task_runner().DelayToNextTaskTime().InMicroseconds())
1175 << scheduler->AsValue()->ToString();
1176 client.task_runner().RunPendingTasks();
1177 EXPECT_GT(client.num_actions_(), actions_so_far);
1178 EXPECT_STREQ(client.Action(client.num_actions_() - 1),
1179 "DidAnticipatedDrawTimeChange");
1180 actions_so_far = client.num_actions_();
1184 TEST(SchedulerTest, BeginRetroFrame) {
1185 FakeSchedulerClient client;
1186 SchedulerSettings scheduler_settings;
1187 scheduler_settings.use_external_begin_frame_source = true;
1188 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1189 scheduler->SetCanStart();
1190 scheduler->SetVisible(true);
1191 scheduler->SetCanDraw(true);
1192 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1194 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1195 client.Reset();
1196 scheduler->SetNeedsCommit();
1197 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1198 client.Reset();
1200 // Create a BeginFrame with a long deadline to avoid race conditions.
1201 // This is the first BeginFrame, which will be handled immediately.
1202 BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src());
1203 args.deadline += base::TimeDelta::FromHours(1);
1204 client.fake_external_begin_frame_source()->TestOnBeginFrame(args);
1205 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1206 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1207 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1208 EXPECT_TRUE(client.needs_begin_frames());
1209 client.Reset();
1211 // Queue BeginFrames while we are still handling the previous BeginFrame.
1212 args.frame_time += base::TimeDelta::FromSeconds(1);
1213 client.fake_external_begin_frame_source()->TestOnBeginFrame(args);
1214 args.frame_time += base::TimeDelta::FromSeconds(1);
1215 client.fake_external_begin_frame_source()->TestOnBeginFrame(args);
1217 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1218 client.task_runner().RunPendingTasks(); // Run posted deadline.
1219 EXPECT_NO_ACTION(client);
1220 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1221 EXPECT_TRUE(client.needs_begin_frames());
1222 client.Reset();
1224 // NotifyReadyToCommit should trigger the commit.
1225 scheduler->NotifyBeginMainFrameStarted();
1226 scheduler->NotifyReadyToCommit();
1227 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1228 EXPECT_TRUE(client.needs_begin_frames());
1229 client.Reset();
1231 // BeginImplFrame should prepare the draw.
1232 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1233 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1234 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1235 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1236 EXPECT_TRUE(client.needs_begin_frames());
1237 client.Reset();
1239 // BeginImplFrame deadline should draw.
1240 client.task_runner().RunPendingTasks(); // Run posted deadline.
1241 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
1242 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1243 EXPECT_TRUE(client.needs_begin_frames());
1244 client.Reset();
1246 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1247 // to avoid excessive toggles.
1248 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1249 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1250 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1251 client.Reset();
1253 client.task_runner().RunPendingTasks(); // Run posted deadline.
1254 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client);
1255 client.Reset();
1258 TEST(SchedulerTest, BeginRetroFrame_SwapThrottled) {
1259 FakeSchedulerClient client;
1260 SchedulerSettings scheduler_settings;
1261 scheduler_settings.use_external_begin_frame_source = true;
1262 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1263 scheduler->SetCanStart();
1264 scheduler->SetVisible(true);
1265 scheduler->SetCanDraw(true);
1266 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1268 // To test swap ack throttling, this test disables automatic swap acks.
1269 scheduler->SetMaxSwapsPending(1);
1270 client.SetAutomaticSwapAck(false);
1272 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1273 client.Reset();
1274 scheduler->SetNeedsCommit();
1275 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1276 client.Reset();
1278 // Create a BeginFrame with a long deadline to avoid race conditions.
1279 // This is the first BeginFrame, which will be handled immediately.
1280 BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src());
1281 args.deadline += base::TimeDelta::FromHours(1);
1282 client.fake_external_begin_frame_source()->TestOnBeginFrame(args);
1283 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1284 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1285 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1286 EXPECT_TRUE(client.needs_begin_frames());
1287 client.Reset();
1289 // Queue BeginFrame while we are still handling the previous BeginFrame.
1290 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1291 args.frame_time += base::TimeDelta::FromSeconds(1);
1292 client.fake_external_begin_frame_source()->TestOnBeginFrame(args);
1293 EXPECT_NO_ACTION(client);
1294 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1295 client.Reset();
1297 // NotifyReadyToCommit should trigger the pending commit and draw.
1298 scheduler->NotifyBeginMainFrameStarted();
1299 scheduler->NotifyReadyToCommit();
1300 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1301 EXPECT_TRUE(client.needs_begin_frames());
1302 client.Reset();
1304 // Swapping will put us into a swap throttled state.
1305 client.task_runner().RunPendingTasks(); // Run posted deadline.
1306 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
1307 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
1308 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1309 EXPECT_TRUE(client.needs_begin_frames());
1310 client.Reset();
1312 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1313 // but not a BeginMainFrame or draw.
1314 scheduler->SetNeedsCommit();
1315 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1316 EXPECT_ACTION("WillBeginImplFrame", client, 0, 1);
1317 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1318 EXPECT_TRUE(client.needs_begin_frames());
1319 client.Reset();
1321 // Queue BeginFrame while we are still handling the previous BeginFrame.
1322 args.frame_time += base::TimeDelta::FromSeconds(1);
1323 client.fake_external_begin_frame_source()->TestOnBeginFrame(args);
1324 EXPECT_NO_ACTION(client);
1325 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1326 EXPECT_TRUE(client.needs_begin_frames());
1327 client.Reset();
1329 // Take us out of a swap throttled state.
1330 scheduler->DidSwapBuffersComplete();
1331 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 1);
1332 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1333 EXPECT_TRUE(client.needs_begin_frames());
1334 client.Reset();
1336 // BeginImplFrame deadline should draw.
1337 scheduler->SetNeedsRedraw();
1339 EXPECT_TRUE(client.task_runner().RunTasksWhile(
1340 client.ImplFrameDeadlinePending(true)));
1342 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
1343 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
1344 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1345 EXPECT_TRUE(client.needs_begin_frames());
1346 client.Reset();
1349 void BeginFramesNotFromClient(bool use_external_begin_frame_source,
1350 bool throttle_frame_production) {
1351 FakeSchedulerClient client;
1352 SchedulerSettings scheduler_settings;
1353 scheduler_settings.use_external_begin_frame_source =
1354 use_external_begin_frame_source;
1355 scheduler_settings.throttle_frame_production = throttle_frame_production;
1356 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1357 scheduler->SetCanStart();
1358 scheduler->SetVisible(true);
1359 scheduler->SetCanDraw(true);
1360 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1362 DCHECK(!client.fake_external_begin_frame_source());
1364 // SetNeedsCommit should begin the frame on the next BeginImplFrame
1365 // without calling SetNeedsBeginFrame.
1366 client.Reset();
1367 scheduler->SetNeedsCommit();
1368 EXPECT_NO_ACTION(client);
1369 client.Reset();
1371 // When the client-driven BeginFrame are disabled, the scheduler posts it's
1372 // own BeginFrame tasks.
1373 client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1374 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1375 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1376 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1377 client.Reset();
1379 // If we don't swap on the deadline, we wait for the next BeginFrame.
1380 client.task_runner().RunPendingTasks(); // Run posted deadline.
1381 EXPECT_NO_ACTION(client);
1382 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1383 client.Reset();
1385 // NotifyReadyToCommit should trigger the commit.
1386 scheduler->NotifyBeginMainFrameStarted();
1387 scheduler->NotifyReadyToCommit();
1388 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1389 client.Reset();
1391 // BeginImplFrame should prepare the draw.
1392 client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1393 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1394 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1395 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1396 client.Reset();
1398 // BeginImplFrame deadline should draw.
1399 client.task_runner().RunTasksWhile(client.ImplFrameDeadlinePending(true));
1400 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
1401 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1402 client.Reset();
1404 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1405 // to avoid excessive toggles.
1406 client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1407 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1408 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1409 client.Reset();
1411 // Make sure SetNeedsBeginFrame isn't called on the client
1412 // when the BeginFrame is no longer needed.
1413 client.task_runner().RunPendingTasks(); // Run posted deadline.
1414 EXPECT_NO_ACTION(client);
1415 client.Reset();
1418 TEST(SchedulerTest, SyntheticBeginFrames) {
1419 bool use_external_begin_frame_source = false;
1420 bool throttle_frame_production = true;
1421 BeginFramesNotFromClient(use_external_begin_frame_source,
1422 throttle_frame_production);
1425 TEST(SchedulerTest, VSyncThrottlingDisabled) {
1426 bool use_external_begin_frame_source = true;
1427 bool throttle_frame_production = false;
1428 BeginFramesNotFromClient(use_external_begin_frame_source,
1429 throttle_frame_production);
1432 TEST(SchedulerTest, SyntheticBeginFrames_And_VSyncThrottlingDisabled) {
1433 bool use_external_begin_frame_source = false;
1434 bool throttle_frame_production = false;
1435 BeginFramesNotFromClient(use_external_begin_frame_source,
1436 throttle_frame_production);
1439 void BeginFramesNotFromClient_SwapThrottled(
1440 bool use_external_begin_frame_source,
1441 bool throttle_frame_production) {
1442 FakeSchedulerClient client;
1443 SchedulerSettings scheduler_settings;
1444 scheduler_settings.use_external_begin_frame_source =
1445 use_external_begin_frame_source;
1446 scheduler_settings.throttle_frame_production = throttle_frame_production;
1447 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1448 scheduler->SetCanStart();
1449 scheduler->SetVisible(true);
1450 scheduler->SetCanDraw(true);
1451 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1453 DCHECK(!client.fake_external_begin_frame_source());
1455 // To test swap ack throttling, this test disables automatic swap acks.
1456 scheduler->SetMaxSwapsPending(1);
1457 client.SetAutomaticSwapAck(false);
1459 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1460 client.Reset();
1461 scheduler->SetNeedsCommit();
1462 EXPECT_NO_ACTION(client);
1463 client.Reset();
1465 // Trigger the first BeginImplFrame and BeginMainFrame
1466 client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1467 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1468 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1469 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1470 client.Reset();
1472 // NotifyReadyToCommit should trigger the pending commit and draw.
1473 scheduler->NotifyBeginMainFrameStarted();
1474 scheduler->NotifyReadyToCommit();
1475 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1476 client.Reset();
1478 // Swapping will put us into a swap throttled state.
1479 client.task_runner().RunPendingTasks(); // Run posted deadline.
1480 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
1481 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
1482 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1483 client.Reset();
1485 // While swap throttled, BeginFrames should trigger BeginImplFrames,
1486 // but not a BeginMainFrame or draw.
1487 scheduler->SetNeedsCommit();
1488 client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1489 EXPECT_ACTION("WillBeginImplFrame", client, 0, 1);
1490 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1491 client.Reset();
1493 // Take us out of a swap throttled state.
1494 scheduler->DidSwapBuffersComplete();
1495 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 1);
1496 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1497 client.Reset();
1499 // BeginImplFrame deadline should draw.
1500 scheduler->SetNeedsRedraw();
1501 client.task_runner().RunPendingTasks(); // Run posted deadline.
1502 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
1503 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
1504 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1505 client.Reset();
1508 TEST(SchedulerTest, SyntheticBeginFrames_SwapThrottled) {
1509 bool use_external_begin_frame_source = false;
1510 bool throttle_frame_production = true;
1511 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
1512 throttle_frame_production);
1515 TEST(SchedulerTest, VSyncThrottlingDisabled_SwapThrottled) {
1516 bool use_external_begin_frame_source = true;
1517 bool throttle_frame_production = false;
1518 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
1519 throttle_frame_production);
1522 TEST(SchedulerTest,
1523 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled) {
1524 bool use_external_begin_frame_source = false;
1525 bool throttle_frame_production = false;
1526 BeginFramesNotFromClient_SwapThrottled(use_external_begin_frame_source,
1527 throttle_frame_production);
1530 TEST(SchedulerTest, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized) {
1531 FakeSchedulerClient client;
1532 SchedulerSettings scheduler_settings;
1533 scheduler_settings.use_external_begin_frame_source = true;
1534 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1535 scheduler->SetCanStart();
1536 scheduler->SetVisible(true);
1537 scheduler->SetCanDraw(true);
1539 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1540 client.Reset();
1541 scheduler->DidCreateAndInitializeOutputSurface();
1542 EXPECT_NO_ACTION(client);
1544 scheduler->DidLoseOutputSurface();
1545 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1548 TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) {
1549 FakeSchedulerClient client;
1550 SchedulerSettings scheduler_settings;
1551 scheduler_settings.use_external_begin_frame_source = true;
1552 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1553 scheduler->SetCanStart();
1554 scheduler->SetVisible(true);
1555 scheduler->SetCanDraw(true);
1557 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1558 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1559 // SetNeedsCommit should begin the frame.
1560 client.Reset();
1561 scheduler->SetNeedsCommit();
1562 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1564 client.Reset();
1565 client.AdvanceFrame();
1566 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1567 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1568 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1570 client.Reset();
1571 scheduler->DidLoseOutputSurface();
1572 // Do nothing when impl frame is in deadine pending state.
1573 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client);
1575 client.Reset();
1576 scheduler->NotifyBeginMainFrameStarted();
1577 scheduler->NotifyReadyToCommit();
1578 EXPECT_ACTION("ScheduledActionCommit", client, 0, 1);
1580 client.Reset();
1581 client.task_runner().RunPendingTasks(); // Run posted deadline.
1582 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1585 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
1586 bool impl_side_painting) {
1587 FakeSchedulerClient client;
1588 SchedulerSettings scheduler_settings;
1589 scheduler_settings.impl_side_painting = impl_side_painting;
1590 scheduler_settings.use_external_begin_frame_source = true;
1591 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1592 scheduler->SetCanStart();
1593 scheduler->SetVisible(true);
1594 scheduler->SetCanDraw(true);
1596 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1597 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1599 // SetNeedsCommit should begin the frame.
1600 client.Reset();
1601 scheduler->SetNeedsCommit();
1602 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1604 client.Reset();
1605 client.AdvanceFrame();
1606 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1607 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1608 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1610 client.Reset();
1611 scheduler->DidLoseOutputSurface();
1612 // Do nothing when impl frame is in deadine pending state.
1613 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client);
1615 client.Reset();
1616 // Run posted deadline.
1617 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1618 client.task_runner().RunTasksWhile(client.ImplFrameDeadlinePending(true));
1619 // OnBeginImplFrameDeadline didn't schedule any actions because main frame is
1620 // not yet completed.
1621 EXPECT_NO_ACTION(client);
1622 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1624 // BeginImplFrame is not started.
1625 client.task_runner().RunUntilTime(client.now_src()->Now() +
1626 base::TimeDelta::FromMilliseconds(10));
1627 EXPECT_NO_ACTION(client);
1628 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1630 client.Reset();
1631 scheduler->NotifyBeginMainFrameStarted();
1632 scheduler->NotifyReadyToCommit();
1633 if (impl_side_painting) {
1634 EXPECT_ACTION("ScheduledActionCommit", client, 0, 3);
1635 EXPECT_ACTION("ScheduledActionActivateSyncTree", client, 1, 3);
1636 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 2, 3);
1637 } else {
1638 EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
1639 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 1, 2);
1643 TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) {
1644 bool impl_side_painting = false;
1645 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
1648 TEST(SchedulerTest,
1649 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint) {
1650 bool impl_side_painting = true;
1651 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
1654 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting) {
1655 FakeSchedulerClient client;
1656 SchedulerSettings scheduler_settings;
1657 scheduler_settings.impl_side_painting = impl_side_painting;
1658 scheduler_settings.use_external_begin_frame_source = true;
1659 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1660 scheduler->SetCanStart();
1661 scheduler->SetVisible(true);
1662 scheduler->SetCanDraw(true);
1664 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1665 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1667 // SetNeedsCommit should begin the frame.
1668 client.Reset();
1669 scheduler->SetNeedsCommit();
1670 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1672 client.Reset();
1673 client.AdvanceFrame();
1674 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1675 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1676 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1678 client.Reset();
1679 scheduler->NotifyBeginMainFrameStarted();
1680 scheduler->NotifyReadyToCommit();
1681 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1683 client.Reset();
1684 scheduler->DidLoseOutputSurface();
1685 if (impl_side_painting) {
1686 // Sync tree should be forced to activate.
1687 EXPECT_ACTION("SetNeedsBeginFrames(false)", client, 0, 2);
1688 EXPECT_ACTION("ScheduledActionActivateSyncTree", client, 1, 2);
1689 } else {
1690 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client);
1693 client.Reset();
1694 client.task_runner().RunPendingTasks(); // Run posted deadline.
1695 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1698 TEST(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) {
1699 DidLoseOutputSurfaceAfterReadyToCommit(false);
1702 TEST(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting) {
1703 DidLoseOutputSurfaceAfterReadyToCommit(true);
1706 TEST(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsManageTiles) {
1707 FakeSchedulerClient client;
1708 SchedulerSettings scheduler_settings;
1709 scheduler_settings.use_external_begin_frame_source = true;
1710 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1711 scheduler->SetCanStart();
1712 scheduler->SetVisible(true);
1713 scheduler->SetCanDraw(true);
1714 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1716 client.Reset();
1717 scheduler->SetNeedsManageTiles();
1718 scheduler->SetNeedsRedraw();
1719 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1721 client.Reset();
1722 client.AdvanceFrame();
1723 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1724 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1725 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1727 client.Reset();
1728 scheduler->DidLoseOutputSurface();
1729 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client);
1731 client.Reset();
1732 client.task_runner().RunPendingTasks(); // Run posted deadline.
1733 EXPECT_ACTION("ScheduledActionManageTiles", client, 0, 2);
1734 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 1, 2);
1737 TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) {
1738 FakeSchedulerClient client;
1739 SchedulerSettings scheduler_settings;
1740 scheduler_settings.use_external_begin_frame_source = true;
1741 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1742 scheduler->SetCanStart();
1743 scheduler->SetVisible(true);
1744 scheduler->SetCanDraw(true);
1745 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1747 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1748 client.Reset();
1749 scheduler->SetNeedsCommit();
1750 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1752 // Create a BeginFrame with a long deadline to avoid race conditions.
1753 // This is the first BeginFrame, which will be handled immediately.
1754 client.Reset();
1755 BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src());
1756 args.deadline += base::TimeDelta::FromHours(1);
1757 client.fake_external_begin_frame_source()->TestOnBeginFrame(args);
1758 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1759 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1760 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1761 EXPECT_TRUE(client.needs_begin_frames());
1763 // Queue BeginFrames while we are still handling the previous BeginFrame.
1764 args.frame_time += base::TimeDelta::FromSeconds(1);
1765 client.fake_external_begin_frame_source()->TestOnBeginFrame(args);
1766 args.frame_time += base::TimeDelta::FromSeconds(1);
1767 client.fake_external_begin_frame_source()->TestOnBeginFrame(args);
1769 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1770 client.Reset();
1771 client.task_runner().RunPendingTasks(); // Run posted deadline.
1772 EXPECT_NO_ACTION(client);
1773 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1774 EXPECT_TRUE(client.needs_begin_frames());
1776 // NotifyReadyToCommit should trigger the commit.
1777 client.Reset();
1778 scheduler->NotifyBeginMainFrameStarted();
1779 scheduler->NotifyReadyToCommit();
1780 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1781 EXPECT_TRUE(client.needs_begin_frames());
1783 client.Reset();
1784 EXPECT_FALSE(scheduler->IsBeginRetroFrameArgsEmpty());
1785 scheduler->DidLoseOutputSurface();
1786 EXPECT_ACTION("SetNeedsBeginFrames(false)", client, 0, 2);
1787 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 1, 2);
1788 EXPECT_TRUE(scheduler->IsBeginRetroFrameArgsEmpty());
1790 // Posted BeginRetroFrame is aborted.
1791 client.Reset();
1792 client.task_runner().RunPendingTasks();
1793 EXPECT_NO_ACTION(client);
1796 TEST(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) {
1797 FakeSchedulerClient client;
1798 SchedulerSettings scheduler_settings;
1799 scheduler_settings.use_external_begin_frame_source = true;
1800 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1801 scheduler->SetCanStart();
1802 scheduler->SetVisible(true);
1803 scheduler->SetCanDraw(true);
1804 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1806 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1807 client.Reset();
1808 scheduler->SetNeedsCommit();
1809 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1811 // Create a BeginFrame with a long deadline to avoid race conditions.
1812 // This is the first BeginFrame, which will be handled immediately.
1813 client.Reset();
1814 BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src());
1815 args.deadline += base::TimeDelta::FromHours(1);
1816 client.fake_external_begin_frame_source()->TestOnBeginFrame(args);
1817 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1818 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1819 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1820 EXPECT_TRUE(client.needs_begin_frames());
1822 // Queue BeginFrames while we are still handling the previous BeginFrame.
1823 args.frame_time += base::TimeDelta::FromSeconds(1);
1824 client.fake_external_begin_frame_source()->TestOnBeginFrame(args);
1825 args.frame_time += base::TimeDelta::FromSeconds(1);
1826 client.fake_external_begin_frame_source()->TestOnBeginFrame(args);
1828 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1829 client.Reset();
1830 client.task_runner().RunPendingTasks(); // Run posted deadline.
1831 EXPECT_NO_ACTION(client);
1832 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1833 EXPECT_TRUE(client.needs_begin_frames());
1835 // NotifyReadyToCommit should trigger the commit.
1836 client.Reset();
1837 scheduler->NotifyBeginMainFrameStarted();
1838 scheduler->NotifyReadyToCommit();
1839 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1840 EXPECT_TRUE(client.needs_begin_frames());
1842 // BeginImplFrame should prepare the draw.
1843 client.Reset();
1844 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1845 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1846 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1847 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1848 EXPECT_TRUE(client.needs_begin_frames());
1850 client.Reset();
1851 EXPECT_FALSE(scheduler->IsBeginRetroFrameArgsEmpty());
1852 scheduler->DidLoseOutputSurface();
1853 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(false)", client);
1854 EXPECT_TRUE(scheduler->IsBeginRetroFrameArgsEmpty());
1856 // BeginImplFrame deadline should abort drawing.
1857 client.Reset();
1858 client.task_runner().RunPendingTasks(); // Run posted deadline.
1859 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1860 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1861 EXPECT_FALSE(client.needs_begin_frames());
1863 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
1864 client.Reset();
1865 client.task_runner().RunPendingTasks();
1866 EXPECT_NO_ACTION(client);
1869 TEST(SchedulerTest,
1870 StopBeginFrameAfterDidLoseOutputSurfaceWithSyntheticBeginFrameSource) {
1871 FakeSchedulerClient client;
1872 SchedulerSettings scheduler_settings;
1873 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1874 scheduler->SetCanStart();
1875 scheduler->SetVisible(true);
1876 scheduler->SetCanDraw(true);
1877 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1879 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1880 client.Reset();
1881 EXPECT_FALSE(scheduler->frame_source().NeedsBeginFrames());
1882 scheduler->SetNeedsCommit();
1883 EXPECT_TRUE(scheduler->frame_source().NeedsBeginFrames());
1885 client.Reset();
1886 client.task_runner().RunPendingTasks(); // Run posted Tick.
1887 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1888 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1889 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1890 EXPECT_TRUE(scheduler->frame_source().NeedsBeginFrames());
1892 // NotifyReadyToCommit should trigger the commit.
1893 client.Reset();
1894 scheduler->NotifyBeginMainFrameStarted();
1895 scheduler->NotifyReadyToCommit();
1896 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1897 EXPECT_TRUE(scheduler->frame_source().NeedsBeginFrames());
1899 client.Reset();
1900 scheduler->DidLoseOutputSurface();
1901 EXPECT_NO_ACTION(client);
1902 EXPECT_FALSE(scheduler->frame_source().NeedsBeginFrames());
1904 client.Reset();
1905 client.task_runner().RunPendingTasks(); // Run posted deadline.
1906 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1907 EXPECT_FALSE(scheduler->frame_source().NeedsBeginFrames());
1910 TEST(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) {
1911 FakeSchedulerClient client;
1912 SchedulerSettings scheduler_settings;
1913 scheduler_settings.impl_side_painting = true;
1914 scheduler_settings.use_external_begin_frame_source = true;
1915 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1916 scheduler->SetCanStart();
1917 scheduler->SetVisible(true);
1918 scheduler->SetCanDraw(true);
1920 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1921 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1923 // SetNeedsCommit should begin the frame.
1924 client.Reset();
1925 scheduler->SetNeedsCommit();
1926 EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client);
1928 client.Reset();
1929 client.AdvanceFrame();
1930 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1931 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1932 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1934 client.Reset();
1935 scheduler->NotifyBeginMainFrameStarted();
1936 scheduler->NotifyReadyToCommit();
1937 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1939 client.Reset();
1940 scheduler->SetVisible(false);
1941 // Sync tree should be forced to activate.
1942 EXPECT_ACTION("SetNeedsBeginFrames(false)", client, 0, 2);
1943 EXPECT_ACTION("ScheduledActionActivateSyncTree", client, 1, 2);
1946 TEST(SchedulerTest, SchedulerPowerMonitoring) {
1947 FakeSchedulerClient client;
1948 SchedulerSettings settings;
1949 settings.disable_hi_res_timer_tasks_on_battery = true;
1950 TestScheduler* scheduler = client.CreateScheduler(settings);
1952 base::TimeTicks before_deadline, after_deadline;
1954 scheduler->SetCanStart();
1955 scheduler->SetVisible(true);
1956 scheduler->SetCanDraw(true);
1958 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1960 scheduler->SetNeedsCommit();
1961 scheduler->SetNeedsRedraw();
1962 client.Reset();
1964 // On non-battery power
1965 EXPECT_FALSE(client.PowerMonitor()->IsOnBatteryPower());
1967 client.AdvanceFrame();
1968 client.Reset();
1970 before_deadline = client.now_src()->Now();
1971 EXPECT_TRUE(client.task_runner().RunTasksWhile(
1972 client.ImplFrameDeadlinePending(true)));
1973 after_deadline = client.now_src()->Now();
1975 // We post a non-zero deadline task when not on battery
1976 EXPECT_LT(before_deadline, after_deadline);
1978 // Switch to battery power
1979 client.PowerMonitorSource()->GeneratePowerStateEvent(true);
1980 EXPECT_TRUE(client.PowerMonitor()->IsOnBatteryPower());
1982 client.AdvanceFrame();
1983 scheduler->SetNeedsCommit();
1984 scheduler->SetNeedsRedraw();
1985 client.Reset();
1987 before_deadline = client.now_src()->Now();
1988 EXPECT_TRUE(client.task_runner().RunTasksWhile(
1989 client.ImplFrameDeadlinePending(true)));
1990 after_deadline = client.now_src()->Now();
1992 // We post a zero deadline task when on battery
1993 EXPECT_EQ(before_deadline, after_deadline);
1995 // Switch to non-battery power
1996 client.PowerMonitorSource()->GeneratePowerStateEvent(false);
1997 EXPECT_FALSE(client.PowerMonitor()->IsOnBatteryPower());
1999 client.AdvanceFrame();
2000 scheduler->SetNeedsCommit();
2001 scheduler->SetNeedsRedraw();
2002 client.Reset();
2004 // Same as before
2005 before_deadline = client.now_src()->Now();
2006 EXPECT_TRUE(client.task_runner().RunTasksWhile(
2007 client.ImplFrameDeadlinePending(true)));
2008 after_deadline = client.now_src()->Now();
2011 TEST(SchedulerTest,
2012 SimulateWindowsLowResolutionTimerOnBattery_PrioritizeImplLatencyOff) {
2013 FakeSchedulerClient client;
2014 SchedulerSettings settings;
2015 settings.use_external_begin_frame_source = true;
2016 TestScheduler* scheduler = client.CreateScheduler(settings);
2018 scheduler->SetCanStart();
2019 scheduler->SetVisible(true);
2020 scheduler->SetCanDraw(true);
2022 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
2024 // Set needs commit so that the scheduler tries to wait for the main thread
2025 scheduler->SetNeedsCommit();
2026 // Set needs redraw so that the scheduler doesn't wait too long
2027 scheduler->SetNeedsRedraw();
2028 client.Reset();
2030 // Switch to battery power
2031 client.PowerMonitorSource()->GeneratePowerStateEvent(true);
2032 EXPECT_TRUE(client.PowerMonitor()->IsOnBatteryPower());
2034 client.AdvanceFrame();
2035 scheduler->SetNeedsCommit();
2036 scheduler->SetNeedsRedraw();
2037 client.Reset();
2039 // Disable auto-advancing of now_src
2040 client.task_runner().SetAutoAdvanceNowToPendingTasks(false);
2042 // Deadline task is pending
2043 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
2044 client.task_runner().RunPendingTasks();
2045 // Deadline task is still pending
2046 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
2048 // Advance now by 15 ms - same as windows low res timer
2049 client.now_src()->AdvanceNowMicroseconds(15000);
2050 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
2051 client.task_runner().RunPendingTasks();
2052 // Deadline task finally completes
2053 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
2056 TEST(SchedulerTest,
2057 SimulateWindowsLowResolutionTimerOnBattery_PrioritizeImplLatencyOn) {
2058 FakeSchedulerClient client;
2059 SchedulerSettings settings;
2060 settings.disable_hi_res_timer_tasks_on_battery = true;
2061 settings.use_external_begin_frame_source = true;
2062 TestScheduler* scheduler = client.CreateScheduler(settings);
2064 scheduler->SetCanStart();
2065 scheduler->SetVisible(true);
2066 scheduler->SetCanDraw(true);
2068 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
2070 // Set needs commit so that the scheduler tries to wait for the main thread
2071 scheduler->SetNeedsCommit();
2072 // Set needs redraw so that the scheduler doesn't wait too long
2073 scheduler->SetNeedsRedraw();
2074 client.Reset();
2076 // Switch to battery power
2077 client.PowerMonitorSource()->GeneratePowerStateEvent(true);
2078 EXPECT_TRUE(client.PowerMonitor()->IsOnBatteryPower());
2080 client.AdvanceFrame();
2081 scheduler->SetNeedsCommit();
2082 scheduler->SetNeedsRedraw();
2083 client.Reset();
2085 // Disable auto-advancing of now_src
2086 client.task_runner().SetAutoAdvanceNowToPendingTasks(false);
2088 // Deadline task is pending
2089 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
2090 client.task_runner().RunPendingTasks();
2091 // Deadline task runs immediately
2092 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
2095 } // namespace
2096 } // namespace cc