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.
4 #include "cc/scheduler/scheduler.h"
5
6 #include <string>
7 #include <vector>
8
9 #include "base/debug/trace_event.h"
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 "cc/test/begin_frame_args_test.h"
16 #include "cc/test/ordered_simple_task_runner.h"
17 #include "cc/test/scheduler_test_common.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
22 do { \
23 EXPECT_EQ(expected_num_actions, client.num_actions_()); \
24 if (action_index >= 0) { \
25 ASSERT_LT(action_index, client.num_actions_()) << scheduler; \
26 EXPECT_STREQ(action, client.Action(action_index)); \
27 } \
28 for (int i = expected_num_actions; i < client.num_actions_(); ++i) \
29 ADD_FAILURE() << "Unexpected action: " << client.Action(i) \
30 << " with state:\n" << client.StateForAction(i); \
31 } while (false)
32
33 #define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0)
34
35 #define EXPECT_SINGLE_ACTION(action, client) \
36 EXPECT_ACTION(action, client, 0, 1)
37
38 namespace cc {
39 namespace {
40
41 class FakeSchedulerClient;
42
43 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler,
44 FakeSchedulerClient* client);
45
46 class FakeSchedulerClient : public SchedulerClient {
47 public:
FakeSchedulerClient()48 FakeSchedulerClient()
49 : needs_begin_frame_(false),
50 automatic_swap_ack_(true),
51 swap_contains_incomplete_tile_(false),
52 redraw_will_happen_if_update_visible_tiles_happens_(false),
53 now_src_(TestNowSource::Create()) {
54 Reset();
55 }
56
Reset()57 void Reset() {
58 actions_.clear();
59 states_.clear();
60 draw_will_happen_ = true;
61 swap_will_happen_if_draw_happens_ = true;
62 num_draws_ = 0;
63 log_anticipated_draw_time_change_ = false;
64 }
65
CreateScheduler(const SchedulerSettings & settings)66 TestScheduler* CreateScheduler(const SchedulerSettings& settings) {
67 scheduler_ = TestScheduler::Create(now_src_, this, settings, 0);
68 // Fail if we need to run 100 tasks in a row.
69 task_runner().SetRunTaskLimit(100);
70 return scheduler_.get();
71 }
72
73 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
74 // for tests that do.
set_log_anticipated_draw_time_change(bool log)75 void set_log_anticipated_draw_time_change(bool log) {
76 log_anticipated_draw_time_change_ = log;
77 }
needs_begin_frame()78 bool needs_begin_frame() { return needs_begin_frame_; }
num_draws() const79 int num_draws() const { return num_draws_; }
num_actions_() const80 int num_actions_() const { return static_cast<int>(actions_.size()); }
Action(int i) const81 const char* Action(int i) const { return actions_[i]; }
StateForAction(int i) const82 std::string StateForAction(int i) const { return states_[i]->ToString(); }
posted_begin_impl_frame_deadline() const83 base::TimeTicks posted_begin_impl_frame_deadline() const {
84 return posted_begin_impl_frame_deadline_;
85 }
86
AdvanceFrame()87 void AdvanceFrame() {
88 bool external_begin_frame =
89 scheduler_->settings().begin_frame_scheduling_enabled &&
90 scheduler_->settings().throttle_frame_production;
91
92 if (external_begin_frame) {
93 scheduler_->BeginFrame(CreateBeginFrameArgsForTesting(now_src_));
94 }
95
96 EXPECT_TRUE(task_runner().RunTasksWhile(ImplFrameDeadlinePending(false)));
97 EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
98 }
99
task_runner()100 OrderedSimpleTaskRunner& task_runner() { return scheduler_->task_runner(); }
now_src()101 TestNowSource* now_src() { return now_src_.get(); }
102
ActionIndex(const char * action) const103 int ActionIndex(const char* action) const {
104 for (size_t i = 0; i < actions_.size(); i++)
105 if (!strcmp(actions_[i], action))
106 return i;
107 return -1;
108 }
109
SetSwapContainsIncompleteTile(bool contain)110 void SetSwapContainsIncompleteTile(bool contain) {
111 swap_contains_incomplete_tile_ = contain;
112 }
113
HasAction(const char * action) const114 bool HasAction(const char* action) const {
115 return ActionIndex(action) >= 0;
116 }
117
SetDrawWillHappen(bool draw_will_happen)118 void SetDrawWillHappen(bool draw_will_happen) {
119 draw_will_happen_ = draw_will_happen;
120 }
SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens)121 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
122 swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
123 }
SetAutomaticSwapAck(bool automatic_swap_ack)124 void SetAutomaticSwapAck(bool automatic_swap_ack) {
125 automatic_swap_ack_ = automatic_swap_ack;
126 }
SetRedrawWillHappenIfUpdateVisibleTilesHappens(bool redraw)127 void SetRedrawWillHappenIfUpdateVisibleTilesHappens(bool redraw) {
128 redraw_will_happen_if_update_visible_tiles_happens_ = redraw;
129 }
130 // SchedulerClient implementation.
SetNeedsBeginFrame(bool enable)131 virtual void SetNeedsBeginFrame(bool enable) OVERRIDE {
132 actions_.push_back("SetNeedsBeginFrame");
133 states_.push_back(scheduler_->AsValue());
134 needs_begin_frame_ = enable;
135 }
WillBeginImplFrame(const BeginFrameArgs & args)136 virtual void WillBeginImplFrame(const BeginFrameArgs& args) OVERRIDE {
137 actions_.push_back("WillBeginImplFrame");
138 states_.push_back(scheduler_->AsValue());
139 }
ScheduledActionSendBeginMainFrame()140 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {
141 actions_.push_back("ScheduledActionSendBeginMainFrame");
142 states_.push_back(scheduler_->AsValue());
143 }
ScheduledActionAnimate()144 virtual void ScheduledActionAnimate() OVERRIDE {
145 actions_.push_back("ScheduledActionAnimate");
146 states_.push_back(scheduler_->AsValue());
147 }
ScheduledActionDrawAndSwapIfPossible()148 virtual DrawResult ScheduledActionDrawAndSwapIfPossible() OVERRIDE {
149 actions_.push_back("ScheduledActionDrawAndSwapIfPossible");
150 states_.push_back(scheduler_->AsValue());
151 num_draws_++;
152 DrawResult result =
153 draw_will_happen_ ? DRAW_SUCCESS : DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
154 bool swap_will_happen =
155 draw_will_happen_ && swap_will_happen_if_draw_happens_;
156 if (swap_will_happen) {
157 scheduler_->DidSwapBuffers();
158 if (swap_contains_incomplete_tile_) {
159 scheduler_->SetSwapUsedIncompleteTile(true);
160 swap_contains_incomplete_tile_ = false;
161 } else {
162 scheduler_->SetSwapUsedIncompleteTile(false);
163 }
164
165 if (automatic_swap_ack_)
166 scheduler_->DidSwapBuffersComplete();
167 }
168 return result;
169 }
ScheduledActionDrawAndSwapForced()170 virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE {
171 actions_.push_back("ScheduledActionDrawAndSwapForced");
172 states_.push_back(scheduler_->AsValue());
173 return DRAW_SUCCESS;
174 }
ScheduledActionCommit()175 virtual void ScheduledActionCommit() OVERRIDE {
176 actions_.push_back("ScheduledActionCommit");
177 states_.push_back(scheduler_->AsValue());
178 }
ScheduledActionUpdateVisibleTiles()179 virtual void ScheduledActionUpdateVisibleTiles() OVERRIDE {
180 actions_.push_back("ScheduledActionUpdateVisibleTiles");
181 states_.push_back(scheduler_->AsValue());
182 if (redraw_will_happen_if_update_visible_tiles_happens_)
183 scheduler_->SetNeedsRedraw();
184 }
ScheduledActionActivateSyncTree()185 virtual void ScheduledActionActivateSyncTree() OVERRIDE {
186 actions_.push_back("ScheduledActionActivateSyncTree");
187 states_.push_back(scheduler_->AsValue());
188 }
ScheduledActionBeginOutputSurfaceCreation()189 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {
190 actions_.push_back("ScheduledActionBeginOutputSurfaceCreation");
191 states_.push_back(scheduler_->AsValue());
192 }
ScheduledActionManageTiles()193 virtual void ScheduledActionManageTiles() OVERRIDE {
194 actions_.push_back("ScheduledActionManageTiles");
195 states_.push_back(scheduler_->AsValue());
196 }
DidAnticipatedDrawTimeChange(base::TimeTicks)197 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {
198 if (log_anticipated_draw_time_change_)
199 actions_.push_back("DidAnticipatedDrawTimeChange");
200 }
DrawDurationEstimate()201 virtual base::TimeDelta DrawDurationEstimate() OVERRIDE {
202 return base::TimeDelta();
203 }
BeginMainFrameToCommitDurationEstimate()204 virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE {
205 return base::TimeDelta();
206 }
CommitToActivateDurationEstimate()207 virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE {
208 return base::TimeDelta();
209 }
210
DidBeginImplFrameDeadline()211 virtual void DidBeginImplFrameDeadline() OVERRIDE {}
212
ImplFrameDeadlinePending(bool state)213 base::Callback<bool(void)> ImplFrameDeadlinePending(bool state) {
214 return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback,
215 base::Unretained(this),
216 state);
217 }
218
219 protected:
ImplFrameDeadlinePendingCallback(bool state)220 bool ImplFrameDeadlinePendingCallback(bool state) {
221 return scheduler_->BeginImplFrameDeadlinePending() == state;
222 }
223
224 bool needs_begin_frame_;
225 bool draw_will_happen_;
226 bool swap_will_happen_if_draw_happens_;
227 bool automatic_swap_ack_;
228 int num_draws_;
229 bool log_anticipated_draw_time_change_;
230 bool swap_contains_incomplete_tile_;
231 bool redraw_will_happen_if_update_visible_tiles_happens_;
232 base::TimeTicks posted_begin_impl_frame_deadline_;
233 std::vector<const char*> actions_;
234 std::vector<scoped_refptr<base::debug::ConvertableToTraceFormat> > states_;
235 scoped_ptr<TestScheduler> scheduler_;
236 scoped_refptr<TestNowSource> now_src_;
237 };
238
InitializeOutputSurfaceAndFirstCommit(Scheduler * scheduler,FakeSchedulerClient * client)239 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler,
240 FakeSchedulerClient* client) {
241 TRACE_EVENT0("cc",
242 "SchedulerUnitTest::InitializeOutputSurfaceAndFirstCommit");
243
244 scheduler->DidCreateAndInitializeOutputSurface();
245 scheduler->SetNeedsCommit();
246 scheduler->NotifyBeginMainFrameStarted();
247 scheduler->NotifyReadyToCommit();
248 if (scheduler->settings().impl_side_painting)
249 scheduler->NotifyReadyToActivate();
250
251 // Go through the motions to draw the commit.
252 client->AdvanceFrame();
253
254 // Run the posted deadline task.
255 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
256 client->task_runner().RunTasksWhile(client->ImplFrameDeadlinePending(true));
257 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
258
259 // We need another BeginImplFrame so Scheduler calls
260 // SetNeedsBeginFrame(false).
261 client->AdvanceFrame();
262
263 // Run the posted deadline task.
264 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
265 client->task_runner().RunTasksWhile(client->ImplFrameDeadlinePending(true));
266 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
267 }
268
TEST(SchedulerTest,InitializeOutputSurfaceDoesNotBeginImplFrame)269 TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) {
270 FakeSchedulerClient client;
271 SchedulerSettings default_scheduler_settings;
272 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
273 scheduler->SetCanStart();
274 scheduler->SetVisible(true);
275 scheduler->SetCanDraw(true);
276
277 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
278 client.Reset();
279 scheduler->DidCreateAndInitializeOutputSurface();
280 EXPECT_NO_ACTION(client);
281 }
282
TEST(SchedulerTest,RequestCommit)283 TEST(SchedulerTest, RequestCommit) {
284 FakeSchedulerClient client;
285 SchedulerSettings scheduler_settings;
286 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
287 scheduler->SetCanStart();
288 scheduler->SetVisible(true);
289 scheduler->SetCanDraw(true);
290
291 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
292 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
293
294 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
295 client.Reset();
296 scheduler->SetNeedsCommit();
297 EXPECT_TRUE(client.needs_begin_frame());
298 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
299 client.Reset();
300
301 client.AdvanceFrame();
302 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
303 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
304 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
305 EXPECT_TRUE(client.needs_begin_frame());
306 client.Reset();
307
308 // If we don't swap on the deadline, we wait for the next BeginFrame.
309 client.task_runner().RunPendingTasks(); // Run posted deadline.
310 EXPECT_NO_ACTION(client);
311 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
312 EXPECT_TRUE(client.needs_begin_frame());
313 client.Reset();
314
315 // NotifyReadyToCommit should trigger the commit.
316 scheduler->NotifyBeginMainFrameStarted();
317 scheduler->NotifyReadyToCommit();
318 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
319 EXPECT_TRUE(client.needs_begin_frame());
320 client.Reset();
321
322 // BeginImplFrame should prepare the draw.
323 client.AdvanceFrame();
324 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
325 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
326 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
327 EXPECT_TRUE(client.needs_begin_frame());
328 client.Reset();
329
330 // BeginImplFrame deadline should draw.
331 client.task_runner().RunPendingTasks(); // Run posted deadline.
332 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
333 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
334 EXPECT_TRUE(client.needs_begin_frame());
335 client.Reset();
336
337 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
338 // to avoid excessive toggles.
339 client.AdvanceFrame();
340 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
341 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
342 client.Reset();
343
344 client.task_runner().RunPendingTasks(); // Run posted deadline.
345 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
346 EXPECT_FALSE(client.needs_begin_frame());
347 client.Reset();
348 }
349
TEST(SchedulerTest,RequestCommitAfterBeginMainFrameSent)350 TEST(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
351 FakeSchedulerClient client;
352 SchedulerSettings scheduler_settings;
353 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
354 scheduler->SetCanStart();
355 scheduler->SetVisible(true);
356 scheduler->SetCanDraw(true);
357
358 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
359 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
360 client.Reset();
361
362 // SetNeedsCommit should begin the frame.
363 scheduler->SetNeedsCommit();
364 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
365
366 client.Reset();
367 client.AdvanceFrame();
368 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
369 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
370 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
371
372 EXPECT_TRUE(client.needs_begin_frame());
373 client.Reset();
374
375 // Now SetNeedsCommit again. Calling here means we need a second commit.
376 scheduler->SetNeedsCommit();
377 EXPECT_EQ(client.num_actions_(), 0);
378 client.Reset();
379
380 // Finish the first commit.
381 scheduler->NotifyBeginMainFrameStarted();
382 scheduler->NotifyReadyToCommit();
383 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
384 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
385 client.Reset();
386 client.task_runner().RunPendingTasks(); // Run posted deadline.
387 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
388 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
389 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
390
391 // Because we just swapped, the Scheduler should also request the next
392 // BeginImplFrame from the OutputSurface.
393 EXPECT_TRUE(client.needs_begin_frame());
394 client.Reset();
395 // Since another commit is needed, the next BeginImplFrame should initiate
396 // the second commit.
397 client.AdvanceFrame();
398 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
399 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
400 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
401 client.Reset();
402
403 // Finishing the commit before the deadline should post a new deadline task
404 // to trigger the deadline early.
405 scheduler->NotifyBeginMainFrameStarted();
406 scheduler->NotifyReadyToCommit();
407 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
408 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
409 client.Reset();
410 client.task_runner().RunPendingTasks(); // Run posted deadline.
411 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
412 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
413 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
414 EXPECT_TRUE(client.needs_begin_frame());
415 client.Reset();
416
417 // On the next BeginImplFrame, verify we go back to a quiescent state and
418 // no longer request BeginImplFrames.
419 client.AdvanceFrame();
420 client.task_runner().RunPendingTasks(); // Run posted deadline.
421 EXPECT_FALSE(client.needs_begin_frame());
422 client.Reset();
423 }
424
425 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
426 public:
ScheduledActionSendBeginMainFrame()427 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
ScheduledActionDrawAndSwapIfPossible()428 virtual DrawResult ScheduledActionDrawAndSwapIfPossible()
429 OVERRIDE {
430 // Only SetNeedsRedraw the first time this is called
431 if (!num_draws_)
432 scheduler_->SetNeedsRedraw();
433 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
434 }
435
ScheduledActionDrawAndSwapForced()436 virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE {
437 NOTREACHED();
438 return DRAW_SUCCESS;
439 }
440
ScheduledActionCommit()441 virtual void ScheduledActionCommit() OVERRIDE {}
ScheduledActionBeginOutputSurfaceCreation()442 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {}
DidAnticipatedDrawTimeChange(base::TimeTicks)443 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
444 };
445
446 // Tests for two different situations:
447 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
448 // a ScheduledActionDrawAndSwap
449 // 2. the scheduler drawing twice inside a single tick
TEST(SchedulerTest,RequestRedrawInsideDraw)450 TEST(SchedulerTest, RequestRedrawInsideDraw) {
451 SchedulerClientThatsetNeedsDrawInsideDraw client;
452 SchedulerSettings default_scheduler_settings;
453 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
454 scheduler->SetCanStart();
455 scheduler->SetVisible(true);
456 scheduler->SetCanDraw(true);
457 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
458 client.Reset();
459
460 scheduler->SetNeedsRedraw();
461 EXPECT_TRUE(scheduler->RedrawPending());
462 EXPECT_TRUE(client.needs_begin_frame());
463 EXPECT_EQ(0, client.num_draws());
464
465 client.AdvanceFrame();
466 client.task_runner().RunPendingTasks(); // Run posted deadline.
467 EXPECT_EQ(1, client.num_draws());
468 EXPECT_TRUE(scheduler->RedrawPending());
469 EXPECT_TRUE(client.needs_begin_frame());
470
471 client.AdvanceFrame();
472 client.task_runner().RunPendingTasks(); // Run posted deadline.
473 EXPECT_EQ(2, client.num_draws());
474 EXPECT_FALSE(scheduler->RedrawPending());
475 EXPECT_TRUE(client.needs_begin_frame());
476
477 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
478 // swap.
479 client.AdvanceFrame();
480 client.task_runner().RunPendingTasks(); // Run posted deadline.
481 EXPECT_EQ(2, client.num_draws());
482 EXPECT_FALSE(scheduler->RedrawPending());
483 EXPECT_FALSE(client.needs_begin_frame());
484 }
485
486 // Test that requesting redraw inside a failed draw doesn't lose the request.
TEST(SchedulerTest,RequestRedrawInsideFailedDraw)487 TEST(SchedulerTest, RequestRedrawInsideFailedDraw) {
488 SchedulerClientThatsetNeedsDrawInsideDraw client;
489 SchedulerSettings default_scheduler_settings;
490 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
491 scheduler->SetCanStart();
492 scheduler->SetVisible(true);
493 scheduler->SetCanDraw(true);
494 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
495 client.Reset();
496
497 client.SetDrawWillHappen(false);
498
499 scheduler->SetNeedsRedraw();
500 EXPECT_TRUE(scheduler->RedrawPending());
501 EXPECT_TRUE(client.needs_begin_frame());
502 EXPECT_EQ(0, client.num_draws());
503
504 // Fail the draw.
505 client.AdvanceFrame();
506 client.task_runner().RunPendingTasks(); // Run posted deadline.
507 EXPECT_EQ(1, client.num_draws());
508
509 // We have a commit pending and the draw failed, and we didn't lose the redraw
510 // request.
511 EXPECT_TRUE(scheduler->CommitPending());
512 EXPECT_TRUE(scheduler->RedrawPending());
513 EXPECT_TRUE(client.needs_begin_frame());
514
515 // Fail the draw again.
516 client.AdvanceFrame();
517 client.task_runner().RunPendingTasks(); // Run posted deadline.
518 EXPECT_EQ(2, client.num_draws());
519 EXPECT_TRUE(scheduler->CommitPending());
520 EXPECT_TRUE(scheduler->RedrawPending());
521 EXPECT_TRUE(client.needs_begin_frame());
522
523 // Draw successfully.
524 client.SetDrawWillHappen(true);
525 client.AdvanceFrame();
526 client.task_runner().RunPendingTasks(); // Run posted deadline.
527 EXPECT_EQ(3, client.num_draws());
528 EXPECT_TRUE(scheduler->CommitPending());
529 EXPECT_FALSE(scheduler->RedrawPending());
530 EXPECT_TRUE(client.needs_begin_frame());
531 }
532
533 class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
534 public:
SchedulerClientThatSetNeedsCommitInsideDraw()535 SchedulerClientThatSetNeedsCommitInsideDraw()
536 : set_needs_commit_on_next_draw_(false) {}
537
ScheduledActionSendBeginMainFrame()538 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
ScheduledActionDrawAndSwapIfPossible()539 virtual DrawResult ScheduledActionDrawAndSwapIfPossible()
540 OVERRIDE {
541 // Only SetNeedsCommit the first time this is called
542 if (set_needs_commit_on_next_draw_) {
543 scheduler_->SetNeedsCommit();
544 set_needs_commit_on_next_draw_ = false;
545 }
546 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
547 }
548
ScheduledActionDrawAndSwapForced()549 virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE {
550 NOTREACHED();
551 return DRAW_SUCCESS;
552 }
553
ScheduledActionCommit()554 virtual void ScheduledActionCommit() OVERRIDE {}
ScheduledActionBeginOutputSurfaceCreation()555 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {}
DidAnticipatedDrawTimeChange(base::TimeTicks)556 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
557
SetNeedsCommitOnNextDraw()558 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; }
559
560 private:
561 bool set_needs_commit_on_next_draw_;
562 };
563
564 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
565 // happen inside a ScheduledActionDrawAndSwap
TEST(SchedulerTest,RequestCommitInsideDraw)566 TEST(SchedulerTest, RequestCommitInsideDraw) {
567 SchedulerClientThatSetNeedsCommitInsideDraw client;
568 SchedulerSettings default_scheduler_settings;
569 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
570 scheduler->SetCanStart();
571 scheduler->SetVisible(true);
572 scheduler->SetCanDraw(true);
573 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
574 client.Reset();
575
576 EXPECT_FALSE(client.needs_begin_frame());
577 scheduler->SetNeedsRedraw();
578 EXPECT_TRUE(scheduler->RedrawPending());
579 EXPECT_EQ(0, client.num_draws());
580 EXPECT_TRUE(client.needs_begin_frame());
581
582 client.SetNeedsCommitOnNextDraw();
583 client.AdvanceFrame();
584 client.SetNeedsCommitOnNextDraw();
585 client.task_runner().RunPendingTasks(); // Run posted deadline.
586 EXPECT_EQ(1, client.num_draws());
587 EXPECT_TRUE(scheduler->CommitPending());
588 EXPECT_TRUE(client.needs_begin_frame());
589 scheduler->NotifyBeginMainFrameStarted();
590 scheduler->NotifyReadyToCommit();
591
592 client.AdvanceFrame();
593 client.task_runner().RunPendingTasks(); // Run posted deadline.
594 EXPECT_EQ(2, client.num_draws());
595
596 EXPECT_FALSE(scheduler->RedrawPending());
597 EXPECT_FALSE(scheduler->CommitPending());
598 EXPECT_TRUE(client.needs_begin_frame());
599
600 // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
601 // swap.
602 client.AdvanceFrame();
603 client.task_runner().RunPendingTasks(); // Run posted deadline.
604 EXPECT_EQ(2, client.num_draws());
605 EXPECT_FALSE(scheduler->RedrawPending());
606 EXPECT_FALSE(scheduler->CommitPending());
607 EXPECT_FALSE(client.needs_begin_frame());
608 }
609
610 // Tests that when a draw fails then the pending commit should not be dropped.
TEST(SchedulerTest,RequestCommitInsideFailedDraw)611 TEST(SchedulerTest, RequestCommitInsideFailedDraw) {
612 SchedulerClientThatsetNeedsDrawInsideDraw client;
613 SchedulerSettings default_scheduler_settings;
614 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
615 scheduler->SetCanStart();
616 scheduler->SetVisible(true);
617 scheduler->SetCanDraw(true);
618 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
619 client.Reset();
620
621 client.SetDrawWillHappen(false);
622
623 scheduler->SetNeedsRedraw();
624 EXPECT_TRUE(scheduler->RedrawPending());
625 EXPECT_TRUE(client.needs_begin_frame());
626 EXPECT_EQ(0, client.num_draws());
627
628 // Fail the draw.
629 client.AdvanceFrame();
630 client.task_runner().RunPendingTasks(); // Run posted deadline.
631 EXPECT_EQ(1, client.num_draws());
632
633 // We have a commit pending and the draw failed, and we didn't lose the commit
634 // request.
635 EXPECT_TRUE(scheduler->CommitPending());
636 EXPECT_TRUE(scheduler->RedrawPending());
637 EXPECT_TRUE(client.needs_begin_frame());
638
639 // Fail the draw again.
640 client.AdvanceFrame();
641
642 client.task_runner().RunPendingTasks(); // Run posted deadline.
643 EXPECT_EQ(2, client.num_draws());
644 EXPECT_TRUE(scheduler->CommitPending());
645 EXPECT_TRUE(scheduler->RedrawPending());
646 EXPECT_TRUE(client.needs_begin_frame());
647
648 // Draw successfully.
649 client.SetDrawWillHappen(true);
650 client.AdvanceFrame();
651 client.task_runner().RunPendingTasks(); // Run posted deadline.
652 EXPECT_EQ(3, client.num_draws());
653 EXPECT_TRUE(scheduler->CommitPending());
654 EXPECT_FALSE(scheduler->RedrawPending());
655 EXPECT_TRUE(client.needs_begin_frame());
656 }
657
TEST(SchedulerTest,NoSwapWhenDrawFails)658 TEST(SchedulerTest, NoSwapWhenDrawFails) {
659 SchedulerClientThatSetNeedsCommitInsideDraw client;
660 SchedulerSettings default_scheduler_settings;
661 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
662 scheduler->SetCanStart();
663 scheduler->SetVisible(true);
664 scheduler->SetCanDraw(true);
665 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
666 client.Reset();
667
668 scheduler->SetNeedsRedraw();
669 EXPECT_TRUE(scheduler->RedrawPending());
670 EXPECT_TRUE(client.needs_begin_frame());
671 EXPECT_EQ(0, client.num_draws());
672
673 // Draw successfully, this starts a new frame.
674 client.SetNeedsCommitOnNextDraw();
675 client.AdvanceFrame();
676 client.task_runner().RunPendingTasks(); // Run posted deadline.
677 EXPECT_EQ(1, client.num_draws());
678
679 scheduler->SetNeedsRedraw();
680 EXPECT_TRUE(scheduler->RedrawPending());
681 EXPECT_TRUE(client.needs_begin_frame());
682
683 // Fail to draw, this should not start a frame.
684 client.SetDrawWillHappen(false);
685 client.SetNeedsCommitOnNextDraw();
686 client.AdvanceFrame();
687 client.task_runner().RunPendingTasks(); // Run posted deadline.
688 EXPECT_EQ(2, client.num_draws());
689 }
690
691 class SchedulerClientNeedsManageTilesInDraw : public FakeSchedulerClient {
692 public:
ScheduledActionDrawAndSwapIfPossible()693 virtual DrawResult ScheduledActionDrawAndSwapIfPossible()
694 OVERRIDE {
695 scheduler_->SetNeedsManageTiles();
696 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
697 }
698 };
699
700 // Test manage tiles is independant of draws.
TEST(SchedulerTest,ManageTiles)701 TEST(SchedulerTest, ManageTiles) {
702 SchedulerClientNeedsManageTilesInDraw client;
703 SchedulerSettings default_scheduler_settings;
704 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
705 scheduler->SetCanStart();
706 scheduler->SetVisible(true);
707 scheduler->SetCanDraw(true);
708 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
709
710 // Request both draw and manage tiles. ManageTiles shouldn't
711 // be trigged until BeginImplFrame.
712 client.Reset();
713 scheduler->SetNeedsManageTiles();
714 scheduler->SetNeedsRedraw();
715 EXPECT_TRUE(scheduler->RedrawPending());
716 EXPECT_TRUE(scheduler->ManageTilesPending());
717 EXPECT_TRUE(client.needs_begin_frame());
718 EXPECT_EQ(0, client.num_draws());
719 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
720 EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
721
722 // We have no immediate actions to perform, so the BeginImplFrame should post
723 // the deadline task.
724 client.Reset();
725 client.AdvanceFrame();
726 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
727 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
728 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
729
730 // On the deadline, he actions should have occured in the right order.
731 client.Reset();
732 client.task_runner().RunPendingTasks(); // Run posted deadline.
733 EXPECT_EQ(1, client.num_draws());
734 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
735 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
736 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
737 client.ActionIndex("ScheduledActionManageTiles"));
738 EXPECT_FALSE(scheduler->RedrawPending());
739 EXPECT_FALSE(scheduler->ManageTilesPending());
740 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
741
742 // Request a draw. We don't need a ManageTiles yet.
743 client.Reset();
744 scheduler->SetNeedsRedraw();
745 EXPECT_TRUE(scheduler->RedrawPending());
746 EXPECT_FALSE(scheduler->ManageTilesPending());
747 EXPECT_TRUE(client.needs_begin_frame());
748 EXPECT_EQ(0, client.num_draws());
749
750 // We have no immediate actions to perform, so the BeginImplFrame should post
751 // the deadline task.
752 client.Reset();
753 client.AdvanceFrame();
754 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
755 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
756 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
757
758 // Draw. The draw will trigger SetNeedsManageTiles, and
759 // then the ManageTiles action will be triggered after the Draw.
760 // Afterwards, neither a draw nor ManageTiles are pending.
761 client.Reset();
762 client.task_runner().RunPendingTasks(); // Run posted deadline.
763 EXPECT_EQ(1, client.num_draws());
764 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
765 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
766 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
767 client.ActionIndex("ScheduledActionManageTiles"));
768 EXPECT_FALSE(scheduler->RedrawPending());
769 EXPECT_FALSE(scheduler->ManageTilesPending());
770 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
771
772 // We need a BeginImplFrame where we don't swap to go idle.
773 client.Reset();
774 client.AdvanceFrame();
775 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
776 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
777 client.Reset();
778 client.task_runner().RunPendingTasks(); // Run posted deadline.
779 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
780 EXPECT_FALSE(client.needs_begin_frame());
781 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
782 EXPECT_EQ(0, client.num_draws());
783
784 // Now trigger a ManageTiles outside of a draw. We will then need
785 // a begin-frame for the ManageTiles, but we don't need a draw.
786 client.Reset();
787 EXPECT_FALSE(client.needs_begin_frame());
788 scheduler->SetNeedsManageTiles();
789 EXPECT_TRUE(client.needs_begin_frame());
790 EXPECT_TRUE(scheduler->ManageTilesPending());
791 EXPECT_FALSE(scheduler->RedrawPending());
792
793 // BeginImplFrame. There will be no draw, only ManageTiles.
794 client.Reset();
795 client.AdvanceFrame();
796 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
797 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
798 client.Reset();
799 client.task_runner().RunPendingTasks(); // Run posted deadline.
800 EXPECT_EQ(0, client.num_draws());
801 EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
802 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
803 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
804 }
805
806 // Test that ManageTiles only happens once per frame. If an external caller
807 // initiates it, then the state machine should not ManageTiles on that frame.
TEST(SchedulerTest,ManageTilesOncePerFrame)808 TEST(SchedulerTest, ManageTilesOncePerFrame) {
809 FakeSchedulerClient client;
810 SchedulerSettings default_scheduler_settings;
811 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
812 scheduler->SetCanStart();
813 scheduler->SetVisible(true);
814 scheduler->SetCanDraw(true);
815 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
816
817 // If DidManageTiles during a frame, then ManageTiles should not occur again.
818 scheduler->SetNeedsManageTiles();
819 scheduler->SetNeedsRedraw();
820 client.Reset();
821 client.AdvanceFrame();
822 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
823 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
824 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
825
826 EXPECT_TRUE(scheduler->ManageTilesPending());
827 scheduler->DidManageTiles(); // An explicit ManageTiles.
828 EXPECT_FALSE(scheduler->ManageTilesPending());
829
830 client.Reset();
831 client.task_runner().RunPendingTasks(); // Run posted deadline.
832 EXPECT_EQ(1, client.num_draws());
833 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
834 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
835 EXPECT_FALSE(scheduler->RedrawPending());
836 EXPECT_FALSE(scheduler->ManageTilesPending());
837 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
838
839 // Next frame without DidManageTiles should ManageTiles with draw.
840 scheduler->SetNeedsManageTiles();
841 scheduler->SetNeedsRedraw();
842 client.Reset();
843 client.AdvanceFrame();
844 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
845 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
846 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
847
848 client.Reset();
849 client.task_runner().RunPendingTasks(); // Run posted deadline.
850 EXPECT_EQ(1, client.num_draws());
851 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
852 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
853 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
854 client.ActionIndex("ScheduledActionManageTiles"));
855 EXPECT_FALSE(scheduler->RedrawPending());
856 EXPECT_FALSE(scheduler->ManageTilesPending());
857 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
858 scheduler->DidManageTiles(); // Corresponds to ScheduledActionManageTiles
859
860 // If we get another DidManageTiles within the same frame, we should
861 // not ManageTiles on the next frame.
862 scheduler->DidManageTiles(); // An explicit ManageTiles.
863 scheduler->SetNeedsManageTiles();
864 scheduler->SetNeedsRedraw();
865 client.Reset();
866 client.AdvanceFrame();
867 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
868 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
869 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
870
871 EXPECT_TRUE(scheduler->ManageTilesPending());
872
873 client.Reset();
874 client.task_runner().RunPendingTasks(); // Run posted deadline.
875 EXPECT_EQ(1, client.num_draws());
876 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
877 EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
878 EXPECT_FALSE(scheduler->RedrawPending());
879 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
880
881 // If we get another DidManageTiles, we should not ManageTiles on the next
882 // frame. This verifies we don't alternate calling ManageTiles once and twice.
883 EXPECT_TRUE(scheduler->ManageTilesPending());
884 scheduler->DidManageTiles(); // An explicit ManageTiles.
885 EXPECT_FALSE(scheduler->ManageTilesPending());
886 scheduler->SetNeedsManageTiles();
887 scheduler->SetNeedsRedraw();
888 client.Reset();
889 client.AdvanceFrame();
890 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
891 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
892 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
893
894 EXPECT_TRUE(scheduler->ManageTilesPending());
895
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->BeginImplFrameDeadlinePending());
903
904 // Next frame without DidManageTiles should ManageTiles with draw.
905 scheduler->SetNeedsManageTiles();
906 scheduler->SetNeedsRedraw();
907 client.Reset();
908 client.AdvanceFrame();
909 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
910 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
911 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
912
913 client.Reset();
914 client.task_runner().RunPendingTasks(); // Run posted deadline.
915 EXPECT_EQ(1, client.num_draws());
916 EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
917 EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
918 EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
919 client.ActionIndex("ScheduledActionManageTiles"));
920 EXPECT_FALSE(scheduler->RedrawPending());
921 EXPECT_FALSE(scheduler->ManageTilesPending());
922 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
923 scheduler->DidManageTiles(); // Corresponds to ScheduledActionManageTiles
924 }
925
TEST(SchedulerTest,ShouldUpdateVisibleTiles)926 TEST(SchedulerTest, ShouldUpdateVisibleTiles) {
927 FakeSchedulerClient client;
928 SchedulerSettings scheduler_settings;
929 scheduler_settings.impl_side_painting = true;
930 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
931 scheduler->SetCanStart();
932 scheduler->SetVisible(true);
933 scheduler->SetCanDraw(true);
934 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
935
936 client.SetRedrawWillHappenIfUpdateVisibleTilesHappens(true);
937
938 // SetNeedsCommit should begin the frame.
939 client.Reset();
940 scheduler->SetNeedsCommit();
941 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
942
943 client.Reset();
944 client.AdvanceFrame();
945 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
946 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
947 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
948
949 client.Reset();
950 scheduler->NotifyBeginMainFrameStarted();
951 scheduler->NotifyReadyToCommit();
952 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
953
954 client.Reset();
955 scheduler->NotifyReadyToActivate();
956 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client);
957
958 client.Reset();
959 client.SetSwapContainsIncompleteTile(true);
960 client.task_runner().RunPendingTasks(); // Run posted deadline.
961 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
962 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
963 EXPECT_FALSE(scheduler->RedrawPending());
964
965 client.Reset();
966 client.AdvanceFrame();
967 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
968 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
969
970 client.Reset();
971 client.task_runner().RunPendingTasks(); // Run posted deadline.
972 EXPECT_ACTION("ScheduledActionUpdateVisibleTiles", client, 0, 3);
973 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 3);
974 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 2, 3);
975
976 client.Reset();
977 client.AdvanceFrame();
978 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
979 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
980
981 // No more UpdateVisibleTiles().
982 client.Reset();
983 client.task_runner().RunPendingTasks(); // Run posted deadline.
984 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
985 EXPECT_FALSE(client.needs_begin_frame());
986 }
987
TEST(SchedulerTest,TriggerBeginFrameDeadlineEarly)988 TEST(SchedulerTest, TriggerBeginFrameDeadlineEarly) {
989 SchedulerClientNeedsManageTilesInDraw client;
990 SchedulerSettings default_scheduler_settings;
991 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
992 scheduler->SetCanStart();
993 scheduler->SetVisible(true);
994 scheduler->SetCanDraw(true);
995 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
996
997 client.Reset();
998 scheduler->SetNeedsRedraw();
999 client.AdvanceFrame();
1000
1001 // The deadline should be zero since there is no work other than drawing
1002 // pending.
1003 EXPECT_EQ(base::TimeTicks(), client.posted_begin_impl_frame_deadline());
1004 }
1005
1006 class SchedulerClientWithFixedEstimates : public FakeSchedulerClient {
1007 public:
SchedulerClientWithFixedEstimates(base::TimeDelta draw_duration,base::TimeDelta begin_main_frame_to_commit_duration,base::TimeDelta commit_to_activate_duration)1008 SchedulerClientWithFixedEstimates(
1009 base::TimeDelta draw_duration,
1010 base::TimeDelta begin_main_frame_to_commit_duration,
1011 base::TimeDelta commit_to_activate_duration)
1012 : draw_duration_(draw_duration),
1013 begin_main_frame_to_commit_duration_(
1014 begin_main_frame_to_commit_duration),
1015 commit_to_activate_duration_(commit_to_activate_duration) {}
1016
DrawDurationEstimate()1017 virtual base::TimeDelta DrawDurationEstimate() OVERRIDE {
1018 return draw_duration_;
1019 }
BeginMainFrameToCommitDurationEstimate()1020 virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE {
1021 return begin_main_frame_to_commit_duration_;
1022 }
CommitToActivateDurationEstimate()1023 virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE {
1024 return commit_to_activate_duration_;
1025 }
1026
1027 private:
1028 base::TimeDelta draw_duration_;
1029 base::TimeDelta begin_main_frame_to_commit_duration_;
1030 base::TimeDelta commit_to_activate_duration_;
1031 };
1032
MainFrameInHighLatencyMode(int64 begin_main_frame_to_commit_estimate_in_ms,int64 commit_to_activate_estimate_in_ms,bool impl_latency_takes_priority,bool should_send_begin_main_frame)1033 void MainFrameInHighLatencyMode(int64 begin_main_frame_to_commit_estimate_in_ms,
1034 int64 commit_to_activate_estimate_in_ms,
1035 bool impl_latency_takes_priority,
1036 bool should_send_begin_main_frame) {
1037 // Set up client with specified estimates (draw duration is set to 1).
1038 SchedulerClientWithFixedEstimates client(
1039 base::TimeDelta::FromMilliseconds(1),
1040 base::TimeDelta::FromMilliseconds(
1041 begin_main_frame_to_commit_estimate_in_ms),
1042 base::TimeDelta::FromMilliseconds(commit_to_activate_estimate_in_ms));
1043 SchedulerSettings default_scheduler_settings;
1044 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
1045 scheduler->SetCanStart();
1046 scheduler->SetVisible(true);
1047 scheduler->SetCanDraw(true);
1048 scheduler->SetImplLatencyTakesPriority(impl_latency_takes_priority);
1049 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1050
1051 // Impl thread hits deadline before commit finishes.
1052 client.Reset();
1053 scheduler->SetNeedsCommit();
1054 EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode());
1055 client.AdvanceFrame();
1056 EXPECT_FALSE(scheduler->MainThreadIsInHighLatencyMode());
1057 client.task_runner().RunPendingTasks(); // Run posted deadline.
1058 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
1059 scheduler->NotifyBeginMainFrameStarted();
1060 scheduler->NotifyReadyToCommit();
1061 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
1062 EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
1063
1064 client.Reset();
1065 scheduler->SetNeedsCommit();
1066 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
1067 client.AdvanceFrame();
1068 EXPECT_TRUE(scheduler->MainThreadIsInHighLatencyMode());
1069 client.task_runner().RunPendingTasks(); // Run posted deadline.
1070 EXPECT_EQ(scheduler->MainThreadIsInHighLatencyMode(),
1071 should_send_begin_main_frame);
1072 EXPECT_EQ(client.HasAction("ScheduledActionSendBeginMainFrame"),
1073 should_send_begin_main_frame);
1074 }
1075
TEST(SchedulerTest,SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline)1076 TEST(SchedulerTest,
1077 SkipMainFrameIfHighLatencyAndCanCommitAndActivateBeforeDeadline) {
1078 // Set up client so that estimates indicate that we can commit and activate
1079 // before the deadline (~8ms by default).
1080 MainFrameInHighLatencyMode(1, 1, false, false);
1081 }
1082
TEST(SchedulerTest,NotSkipMainFrameIfHighLatencyAndCanCommitTooLong)1083 TEST(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanCommitTooLong) {
1084 // Set up client so that estimates indicate that the commit cannot finish
1085 // before the deadline (~8ms by default).
1086 MainFrameInHighLatencyMode(10, 1, false, true);
1087 }
1088
TEST(SchedulerTest,NotSkipMainFrameIfHighLatencyAndCanActivateTooLong)1089 TEST(SchedulerTest, NotSkipMainFrameIfHighLatencyAndCanActivateTooLong) {
1090 // Set up client so that estimates indicate that the activate cannot finish
1091 // before the deadline (~8ms by default).
1092 MainFrameInHighLatencyMode(1, 10, false, true);
1093 }
1094
TEST(SchedulerTest,NotSkipMainFrameInPreferImplLatencyMode)1095 TEST(SchedulerTest, NotSkipMainFrameInPreferImplLatencyMode) {
1096 // Set up client so that estimates indicate that we can commit and activate
1097 // before the deadline (~8ms by default), but also enable impl latency takes
1098 // priority mode.
1099 MainFrameInHighLatencyMode(1, 1, true, true);
1100 }
1101
TEST(SchedulerTest,PollForCommitCompletion)1102 TEST(SchedulerTest, PollForCommitCompletion) {
1103 // Since we are simulating a long commit, set up a client with draw duration
1104 // estimates that prevent skipping main frames to get to low latency mode.
1105 SchedulerClientWithFixedEstimates client(
1106 base::TimeDelta::FromMilliseconds(1),
1107 base::TimeDelta::FromMilliseconds(32),
1108 base::TimeDelta::FromMilliseconds(32));
1109 client.set_log_anticipated_draw_time_change(true);
1110 SchedulerSettings default_scheduler_settings;
1111 TestScheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
1112
1113 scheduler->SetCanDraw(true);
1114 scheduler->SetCanStart();
1115 scheduler->SetVisible(true);
1116 scheduler->DidCreateAndInitializeOutputSurface();
1117
1118 scheduler->SetNeedsCommit();
1119 EXPECT_TRUE(scheduler->CommitPending());
1120 scheduler->NotifyBeginMainFrameStarted();
1121 scheduler->NotifyReadyToCommit();
1122 scheduler->SetNeedsRedraw();
1123
1124 BeginFrameArgs frame_args = CreateBeginFrameArgsForTesting(client.now_src());
1125 frame_args.interval = base::TimeDelta::FromMilliseconds(1000);
1126 scheduler->BeginFrame(frame_args);
1127
1128 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1129 client.task_runner().RunPendingTasks(); // Run posted deadline.
1130 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1131
1132 scheduler->DidSwapBuffers();
1133 scheduler->DidSwapBuffersComplete();
1134
1135 // At this point, we've drawn a frame. Start another commit, but hold off on
1136 // the NotifyReadyToCommit for now.
1137 EXPECT_FALSE(scheduler->CommitPending());
1138 scheduler->SetNeedsCommit();
1139 scheduler->BeginFrame(frame_args);
1140 EXPECT_TRUE(scheduler->CommitPending());
1141
1142 // Draw and swap the frame, but don't ack the swap to simulate the Browser
1143 // blocking on the renderer.
1144 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1145 client.task_runner().RunPendingTasks(); // Run posted deadline.
1146 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1147 scheduler->DidSwapBuffers();
1148
1149 // Spin the event loop a few times and make sure we get more
1150 // DidAnticipateDrawTimeChange calls every time.
1151 int actions_so_far = client.num_actions_();
1152
1153 // Does three iterations to make sure that the timer is properly repeating.
1154 for (int i = 0; i < 3; ++i) {
1155 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1156 client.task_runner().DelayToNextTaskTime().InMicroseconds())
1157 << scheduler->AsValue()->ToString();
1158 client.task_runner().RunPendingTasks();
1159 EXPECT_GT(client.num_actions_(), actions_so_far);
1160 EXPECT_STREQ(client.Action(client.num_actions_() - 1),
1161 "DidAnticipatedDrawTimeChange");
1162 actions_so_far = client.num_actions_();
1163 }
1164
1165 // Do the same thing after BeginMainFrame starts but still before activation.
1166 scheduler->NotifyBeginMainFrameStarted();
1167 for (int i = 0; i < 3; ++i) {
1168 EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
1169 client.task_runner().DelayToNextTaskTime().InMicroseconds())
1170 << scheduler->AsValue()->ToString();
1171 client.task_runner().RunPendingTasks();
1172 EXPECT_GT(client.num_actions_(), actions_so_far);
1173 EXPECT_STREQ(client.Action(client.num_actions_() - 1),
1174 "DidAnticipatedDrawTimeChange");
1175 actions_so_far = client.num_actions_();
1176 }
1177 }
1178
TEST(SchedulerTest,BeginRetroFrame)1179 TEST(SchedulerTest, BeginRetroFrame) {
1180 FakeSchedulerClient client;
1181 SchedulerSettings scheduler_settings;
1182 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1183 scheduler->SetCanStart();
1184 scheduler->SetVisible(true);
1185 scheduler->SetCanDraw(true);
1186 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1187
1188 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1189 client.Reset();
1190 scheduler->SetNeedsCommit();
1191 EXPECT_TRUE(client.needs_begin_frame());
1192 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1193 client.Reset();
1194
1195 // Create a BeginFrame with a long deadline to avoid race conditions.
1196 // This is the first BeginFrame, which will be handled immediately.
1197 BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src());
1198 args.deadline += base::TimeDelta::FromHours(1);
1199 scheduler->BeginFrame(args);
1200 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1201 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1202 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1203 EXPECT_TRUE(client.needs_begin_frame());
1204 client.Reset();
1205
1206 // Queue BeginFrames while we are still handling the previous BeginFrame.
1207 args.frame_time += base::TimeDelta::FromSeconds(1);
1208 scheduler->BeginFrame(args);
1209 args.frame_time += base::TimeDelta::FromSeconds(1);
1210 scheduler->BeginFrame(args);
1211
1212 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1213 client.task_runner().RunPendingTasks(); // Run posted deadline.
1214 EXPECT_NO_ACTION(client);
1215 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1216 EXPECT_TRUE(client.needs_begin_frame());
1217 client.Reset();
1218
1219 // NotifyReadyToCommit should trigger the commit.
1220 scheduler->NotifyBeginMainFrameStarted();
1221 scheduler->NotifyReadyToCommit();
1222 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1223 EXPECT_TRUE(client.needs_begin_frame());
1224 client.Reset();
1225
1226 // BeginImplFrame should prepare the draw.
1227 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1228 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1229 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1230 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1231 EXPECT_TRUE(client.needs_begin_frame());
1232 client.Reset();
1233
1234 // BeginImplFrame deadline should draw.
1235 client.task_runner().RunPendingTasks(); // Run posted deadline.
1236 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
1237 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1238 EXPECT_TRUE(client.needs_begin_frame());
1239 client.Reset();
1240
1241 // The following BeginImplFrame deadline should SetNeedsBeginFrame(false)
1242 // to avoid excessive toggles.
1243 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1244 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
1245 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1246 client.Reset();
1247
1248 client.task_runner().RunPendingTasks(); // Run posted deadline.
1249 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1250 EXPECT_FALSE(client.needs_begin_frame());
1251 client.Reset();
1252 }
1253
TEST(SchedulerTest,BeginRetroFrame_SwapThrottled)1254 TEST(SchedulerTest, BeginRetroFrame_SwapThrottled) {
1255 FakeSchedulerClient client;
1256 SchedulerSettings scheduler_settings;
1257 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1258 scheduler->SetCanStart();
1259 scheduler->SetVisible(true);
1260 scheduler->SetCanDraw(true);
1261 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1262
1263 // To test swap ack throttling, this test disables automatic swap acks.
1264 scheduler->SetMaxSwapsPending(1);
1265 client.SetAutomaticSwapAck(false);
1266
1267 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1268 client.Reset();
1269 scheduler->SetNeedsCommit();
1270 EXPECT_TRUE(client.needs_begin_frame());
1271 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1272 client.Reset();
1273
1274 // Create a BeginFrame with a long deadline to avoid race conditions.
1275 // This is the first BeginFrame, which will be handled immediately.
1276 BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src());
1277 args.deadline += base::TimeDelta::FromHours(1);
1278 scheduler->BeginFrame(args);
1279 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1280 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1281 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1282 EXPECT_TRUE(client.needs_begin_frame());
1283 client.Reset();
1284
1285 // Queue BeginFrame while we are still handling the previous BeginFrame.
1286 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1287 args.frame_time += base::TimeDelta::FromSeconds(1);
1288 scheduler->BeginFrame(args);
1289 EXPECT_NO_ACTION(client);
1290 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1291 client.Reset();
1292
1293 // NotifyReadyToCommit should trigger the pending commit and draw.
1294 scheduler->NotifyBeginMainFrameStarted();
1295 scheduler->NotifyReadyToCommit();
1296 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1297 EXPECT_TRUE(client.needs_begin_frame());
1298 client.Reset();
1299
1300 // Swapping will put us into a swap throttled state.
1301 client.task_runner().RunPendingTasks(); // Run posted deadline.
1302 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
1303 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
1304 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1305 EXPECT_TRUE(client.needs_begin_frame());
1306 client.Reset();
1307
1308 // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
1309 // but not a BeginMainFrame or draw.
1310 scheduler->SetNeedsCommit();
1311 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1312 EXPECT_ACTION("WillBeginImplFrame", client, 0, 1);
1313 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1314 EXPECT_TRUE(client.needs_begin_frame());
1315 client.Reset();
1316
1317 // Queue BeginFrame while we are still handling the previous BeginFrame.
1318 args.frame_time += base::TimeDelta::FromSeconds(1);
1319 scheduler->BeginFrame(args);
1320 EXPECT_NO_ACTION(client);
1321 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1322 EXPECT_TRUE(client.needs_begin_frame());
1323 client.Reset();
1324
1325 // Take us out of a swap throttled state.
1326 scheduler->DidSwapBuffersComplete();
1327 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 1);
1328 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1329 EXPECT_TRUE(client.needs_begin_frame());
1330 client.Reset();
1331
1332 // BeginImplFrame deadline should draw.
1333 scheduler->SetNeedsRedraw();
1334
1335 EXPECT_TRUE(client.task_runner().RunTasksWhile(
1336 client.ImplFrameDeadlinePending(true)));
1337
1338 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
1339 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
1340 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1341 EXPECT_TRUE(client.needs_begin_frame());
1342 client.Reset();
1343 }
1344
BeginFramesNotFromClient(bool begin_frame_scheduling_enabled,bool throttle_frame_production)1345 void BeginFramesNotFromClient(bool begin_frame_scheduling_enabled,
1346 bool throttle_frame_production) {
1347 FakeSchedulerClient client;
1348 SchedulerSettings scheduler_settings;
1349 scheduler_settings.begin_frame_scheduling_enabled =
1350 begin_frame_scheduling_enabled;
1351 scheduler_settings.throttle_frame_production = throttle_frame_production;
1352 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1353 scheduler->SetCanStart();
1354 scheduler->SetVisible(true);
1355 scheduler->SetCanDraw(true);
1356 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1357
1358 // SetNeedsCommit should begin the frame on the next BeginImplFrame
1359 // without calling SetNeedsBeginFrame.
1360 client.Reset();
1361 scheduler->SetNeedsCommit();
1362 EXPECT_FALSE(client.needs_begin_frame());
1363 EXPECT_NO_ACTION(client);
1364 client.Reset();
1365
1366 // When the client-driven BeginFrame are disabled, the scheduler posts it's
1367 // own BeginFrame tasks.
1368 client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1369 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1370 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1371 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1372 EXPECT_FALSE(client.needs_begin_frame());
1373 client.Reset();
1374
1375 // If we don't swap on the deadline, we wait for the next BeginFrame.
1376 client.task_runner().RunPendingTasks(); // Run posted deadline.
1377 EXPECT_NO_ACTION(client);
1378 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1379 EXPECT_FALSE(client.needs_begin_frame());
1380 client.Reset();
1381
1382 // NotifyReadyToCommit should trigger the commit.
1383 scheduler->NotifyBeginMainFrameStarted();
1384 scheduler->NotifyReadyToCommit();
1385 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1386 EXPECT_FALSE(client.needs_begin_frame());
1387 client.Reset();
1388
1389 // BeginImplFrame should prepare the draw.
1390 client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1391 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1392 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1393 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1394 EXPECT_FALSE(client.needs_begin_frame());
1395 client.Reset();
1396
1397 // BeginImplFrame deadline should draw.
1398 client.task_runner().RunTasksWhile(client.ImplFrameDeadlinePending(true));
1399 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
1400 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1401 EXPECT_FALSE(client.needs_begin_frame());
1402 client.Reset();
1403
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();
1410
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 EXPECT_FALSE(client.needs_begin_frame());
1416 client.Reset();
1417 }
1418
TEST(SchedulerTest,SyntheticBeginFrames)1419 TEST(SchedulerTest, SyntheticBeginFrames) {
1420 bool begin_frame_scheduling_enabled = false;
1421 bool throttle_frame_production = true;
1422 BeginFramesNotFromClient(begin_frame_scheduling_enabled,
1423 throttle_frame_production);
1424 }
1425
TEST(SchedulerTest,VSyncThrottlingDisabled)1426 TEST(SchedulerTest, VSyncThrottlingDisabled) {
1427 bool begin_frame_scheduling_enabled = true;
1428 bool throttle_frame_production = false;
1429 BeginFramesNotFromClient(begin_frame_scheduling_enabled,
1430 throttle_frame_production);
1431 }
1432
TEST(SchedulerTest,SyntheticBeginFrames_And_VSyncThrottlingDisabled)1433 TEST(SchedulerTest, SyntheticBeginFrames_And_VSyncThrottlingDisabled) {
1434 bool begin_frame_scheduling_enabled = false;
1435 bool throttle_frame_production = false;
1436 BeginFramesNotFromClient(begin_frame_scheduling_enabled,
1437 throttle_frame_production);
1438 }
1439
BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled,bool throttle_frame_production)1440 void BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled,
1441 bool throttle_frame_production) {
1442 FakeSchedulerClient client;
1443 SchedulerSettings scheduler_settings;
1444 scheduler_settings.begin_frame_scheduling_enabled =
1445 begin_frame_scheduling_enabled;
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);
1452
1453 // To test swap ack throttling, this test disables automatic swap acks.
1454 scheduler->SetMaxSwapsPending(1);
1455 client.SetAutomaticSwapAck(false);
1456
1457 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1458 client.Reset();
1459 scheduler->SetNeedsCommit();
1460 EXPECT_FALSE(client.needs_begin_frame());
1461 EXPECT_NO_ACTION(client);
1462 client.Reset();
1463
1464 // Trigger the first BeginImplFrame and BeginMainFrame
1465 client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1466 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1467 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1468 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1469 EXPECT_FALSE(client.needs_begin_frame());
1470 client.Reset();
1471
1472 // NotifyReadyToCommit should trigger the pending commit and draw.
1473 scheduler->NotifyBeginMainFrameStarted();
1474 scheduler->NotifyReadyToCommit();
1475 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1476 EXPECT_FALSE(client.needs_begin_frame());
1477 client.Reset();
1478
1479 // Swapping will put us into a swap throttled state.
1480 client.task_runner().RunPendingTasks(); // Run posted deadline.
1481 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
1482 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
1483 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1484 EXPECT_FALSE(client.needs_begin_frame());
1485 client.Reset();
1486
1487 // While swap throttled, BeginFrames should trigger BeginImplFrames,
1488 // but not a BeginMainFrame or draw.
1489 scheduler->SetNeedsCommit();
1490 client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1491 EXPECT_ACTION("WillBeginImplFrame", client, 0, 1);
1492 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1493 EXPECT_FALSE(client.needs_begin_frame());
1494 client.Reset();
1495
1496 // Take us out of a swap throttled state.
1497 scheduler->DidSwapBuffersComplete();
1498 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 1);
1499 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1500 EXPECT_FALSE(client.needs_begin_frame());
1501 client.Reset();
1502
1503 // BeginImplFrame deadline should draw.
1504 scheduler->SetNeedsRedraw();
1505 client.task_runner().RunPendingTasks(); // Run posted deadline.
1506 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
1507 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
1508 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1509 EXPECT_FALSE(client.needs_begin_frame());
1510 client.Reset();
1511 }
1512
TEST(SchedulerTest,SyntheticBeginFrames_SwapThrottled)1513 TEST(SchedulerTest, SyntheticBeginFrames_SwapThrottled) {
1514 bool begin_frame_scheduling_enabled = false;
1515 bool throttle_frame_production = true;
1516 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled,
1517 throttle_frame_production);
1518 }
1519
TEST(SchedulerTest,VSyncThrottlingDisabled_SwapThrottled)1520 TEST(SchedulerTest, VSyncThrottlingDisabled_SwapThrottled) {
1521 bool begin_frame_scheduling_enabled = true;
1522 bool throttle_frame_production = false;
1523 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled,
1524 throttle_frame_production);
1525 }
1526
TEST(SchedulerTest,SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled)1527 TEST(SchedulerTest,
1528 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled) {
1529 bool begin_frame_scheduling_enabled = false;
1530 bool throttle_frame_production = false;
1531 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled,
1532 throttle_frame_production);
1533 }
1534
TEST(SchedulerTest,DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized)1535 TEST(SchedulerTest, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized) {
1536 FakeSchedulerClient client;
1537 SchedulerSettings scheduler_settings;
1538 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1539 scheduler->SetCanStart();
1540 scheduler->SetVisible(true);
1541 scheduler->SetCanDraw(true);
1542
1543 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1544 client.Reset();
1545 scheduler->DidCreateAndInitializeOutputSurface();
1546 EXPECT_NO_ACTION(client);
1547
1548 scheduler->DidLoseOutputSurface();
1549 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1550 }
1551
TEST(SchedulerTest,DidLoseOutputSurfaceAfterBeginFrameStarted)1552 TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) {
1553 FakeSchedulerClient client;
1554 SchedulerSettings scheduler_settings;
1555 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1556 scheduler->SetCanStart();
1557 scheduler->SetVisible(true);
1558 scheduler->SetCanDraw(true);
1559
1560 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1561 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1562 // SetNeedsCommit should begin the frame.
1563 client.Reset();
1564 scheduler->SetNeedsCommit();
1565 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1566
1567 client.Reset();
1568 client.AdvanceFrame();
1569 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1570 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1571 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1572
1573 client.Reset();
1574 scheduler->DidLoseOutputSurface();
1575 // Do nothing when impl frame is in deadine pending state.
1576 EXPECT_NO_ACTION(client);
1577
1578 client.Reset();
1579 scheduler->NotifyBeginMainFrameStarted();
1580 scheduler->NotifyReadyToCommit();
1581 EXPECT_ACTION("ScheduledActionCommit", client, 0, 1);
1582
1583 client.Reset();
1584 client.task_runner().RunPendingTasks(); // Run posted deadline.
1585 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1586 }
1587
DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(bool impl_side_painting)1588 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
1589 bool impl_side_painting) {
1590 FakeSchedulerClient client;
1591 SchedulerSettings scheduler_settings;
1592 scheduler_settings.impl_side_painting = impl_side_painting;
1593 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1594 scheduler->SetCanStart();
1595 scheduler->SetVisible(true);
1596 scheduler->SetCanDraw(true);
1597
1598 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1599 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1600
1601 // SetNeedsCommit should begin the frame.
1602 client.Reset();
1603 scheduler->SetNeedsCommit();
1604 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1605
1606 client.Reset();
1607 client.AdvanceFrame();
1608 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1609 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1610 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1611
1612 client.Reset();
1613 scheduler->DidLoseOutputSurface();
1614 // Do nothing when impl frame is in deadine pending state.
1615 EXPECT_NO_ACTION(client);
1616
1617 client.Reset();
1618 // Run posted deadline.
1619 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1620 client.task_runner().RunTasksWhile(client.ImplFrameDeadlinePending(true));
1621 // OnBeginImplFrameDeadline didn't schedule any actions because main frame is
1622 // not yet completed.
1623 EXPECT_NO_ACTION(client);
1624 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1625
1626 // BeginImplFrame is not started.
1627 client.task_runner().RunUntilTime(client.now_src()->Now() +
1628 base::TimeDelta::FromMilliseconds(10));
1629 EXPECT_NO_ACTION(client);
1630 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1631
1632 client.Reset();
1633 scheduler->NotifyBeginMainFrameStarted();
1634 scheduler->NotifyReadyToCommit();
1635 if (impl_side_painting) {
1636 EXPECT_ACTION("ScheduledActionCommit", client, 0, 3);
1637 EXPECT_ACTION("ScheduledActionActivateSyncTree", client, 1, 3);
1638 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 2, 3);
1639 } else {
1640 EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
1641 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 1, 2);
1642 }
1643 }
1644
TEST(SchedulerTest,DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency)1645 TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) {
1646 bool impl_side_painting = false;
1647 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
1648 }
1649
TEST(SchedulerTest,DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint)1650 TEST(SchedulerTest,
1651 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint) {
1652 bool impl_side_painting = true;
1653 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
1654 }
1655
DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting)1656 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting) {
1657 FakeSchedulerClient client;
1658 SchedulerSettings scheduler_settings;
1659 scheduler_settings.impl_side_painting = impl_side_painting;
1660 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1661 scheduler->SetCanStart();
1662 scheduler->SetVisible(true);
1663 scheduler->SetCanDraw(true);
1664
1665 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1666 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1667
1668 // SetNeedsCommit should begin the frame.
1669 client.Reset();
1670 scheduler->SetNeedsCommit();
1671 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1672
1673 client.Reset();
1674 client.AdvanceFrame();
1675 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1676 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1677 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1678
1679 client.Reset();
1680 scheduler->NotifyBeginMainFrameStarted();
1681 scheduler->NotifyReadyToCommit();
1682 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1683
1684 client.Reset();
1685 scheduler->DidLoseOutputSurface();
1686 if (impl_side_painting) {
1687 // Sync tree should be forced to activate.
1688 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client);
1689 } else {
1690 // Do nothing when impl frame is in deadine pending state.
1691 EXPECT_NO_ACTION(client);
1692 }
1693
1694 client.Reset();
1695 client.task_runner().RunPendingTasks(); // Run posted deadline.
1696 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1697 }
1698
TEST(SchedulerTest,DidLoseOutputSurfaceAfterReadyToCommit)1699 TEST(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) {
1700 DidLoseOutputSurfaceAfterReadyToCommit(false);
1701 }
1702
TEST(SchedulerTest,DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting)1703 TEST(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting) {
1704 DidLoseOutputSurfaceAfterReadyToCommit(true);
1705 }
1706
TEST(SchedulerTest,DidLoseOutputSurfaceAfterSetNeedsManageTiles)1707 TEST(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsManageTiles) {
1708 FakeSchedulerClient client;
1709 SchedulerSettings scheduler_settings;
1710 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1711 scheduler->SetCanStart();
1712 scheduler->SetVisible(true);
1713 scheduler->SetCanDraw(true);
1714 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1715
1716 client.Reset();
1717 scheduler->SetNeedsManageTiles();
1718 scheduler->SetNeedsRedraw();
1719 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1720 EXPECT_TRUE(client.needs_begin_frame());
1721
1722 client.Reset();
1723 client.AdvanceFrame();
1724 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1725 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1726 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1727
1728 client.Reset();
1729 scheduler->DidLoseOutputSurface();
1730 EXPECT_NO_ACTION(client);
1731
1732 client.Reset();
1733 client.task_runner().RunPendingTasks(); // Run posted deadline.
1734 EXPECT_ACTION("ScheduledActionManageTiles", client, 0, 2);
1735 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 1, 2);
1736 }
1737
TEST(SchedulerTest,DidLoseOutputSurfaceAfterBeginRetroFramePosted)1738 TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) {
1739 FakeSchedulerClient client;
1740 SchedulerSettings scheduler_settings;
1741 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1742 scheduler->SetCanStart();
1743 scheduler->SetVisible(true);
1744 scheduler->SetCanDraw(true);
1745 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1746
1747 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1748 client.Reset();
1749 scheduler->SetNeedsCommit();
1750 EXPECT_TRUE(client.needs_begin_frame());
1751 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1752
1753 // Create a BeginFrame with a long deadline to avoid race conditions.
1754 // This is the first BeginFrame, which will be handled immediately.
1755 client.Reset();
1756 BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src());
1757 args.deadline += base::TimeDelta::FromHours(1);
1758 scheduler->BeginFrame(args);
1759 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1760 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1761 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1762 EXPECT_TRUE(client.needs_begin_frame());
1763
1764 // Queue BeginFrames while we are still handling the previous BeginFrame.
1765 args.frame_time += base::TimeDelta::FromSeconds(1);
1766 scheduler->BeginFrame(args);
1767 args.frame_time += base::TimeDelta::FromSeconds(1);
1768 scheduler->BeginFrame(args);
1769
1770 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1771 client.Reset();
1772 client.task_runner().RunPendingTasks(); // Run posted deadline.
1773 EXPECT_NO_ACTION(client);
1774 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1775 EXPECT_TRUE(client.needs_begin_frame());
1776
1777 // NotifyReadyToCommit should trigger the commit.
1778 client.Reset();
1779 scheduler->NotifyBeginMainFrameStarted();
1780 scheduler->NotifyReadyToCommit();
1781 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1782 EXPECT_TRUE(client.needs_begin_frame());
1783
1784 client.Reset();
1785 EXPECT_FALSE(scheduler->IsBeginRetroFrameArgsEmpty());
1786 scheduler->DidLoseOutputSurface();
1787 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1788 EXPECT_TRUE(client.needs_begin_frame());
1789 EXPECT_TRUE(scheduler->IsBeginRetroFrameArgsEmpty());
1790
1791 // Posted BeginRetroFrame is aborted.
1792 client.Reset();
1793 client.task_runner().RunPendingTasks();
1794 EXPECT_NO_ACTION(client);
1795 }
1796
TEST(SchedulerTest,DidLoseOutputSurfaceDuringBeginRetroFrameRunning)1797 TEST(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) {
1798 FakeSchedulerClient client;
1799 SchedulerSettings scheduler_settings;
1800 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1801 scheduler->SetCanStart();
1802 scheduler->SetVisible(true);
1803 scheduler->SetCanDraw(true);
1804 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1805
1806 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1807 client.Reset();
1808 scheduler->SetNeedsCommit();
1809 EXPECT_TRUE(client.needs_begin_frame());
1810 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1811
1812 // Create a BeginFrame with a long deadline to avoid race conditions.
1813 // This is the first BeginFrame, which will be handled immediately.
1814 client.Reset();
1815 BeginFrameArgs args = CreateBeginFrameArgsForTesting(client.now_src());
1816 args.deadline += base::TimeDelta::FromHours(1);
1817 scheduler->BeginFrame(args);
1818 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1819 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1820 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1821 EXPECT_TRUE(client.needs_begin_frame());
1822
1823 // Queue BeginFrames while we are still handling the previous BeginFrame.
1824 args.frame_time += base::TimeDelta::FromSeconds(1);
1825 scheduler->BeginFrame(args);
1826 args.frame_time += base::TimeDelta::FromSeconds(1);
1827 scheduler->BeginFrame(args);
1828
1829 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1830 client.Reset();
1831 client.task_runner().RunPendingTasks(); // Run posted deadline.
1832 EXPECT_NO_ACTION(client);
1833 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1834 EXPECT_TRUE(client.needs_begin_frame());
1835
1836 // NotifyReadyToCommit should trigger the commit.
1837 client.Reset();
1838 scheduler->NotifyBeginMainFrameStarted();
1839 scheduler->NotifyReadyToCommit();
1840 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1841 EXPECT_TRUE(client.needs_begin_frame());
1842
1843 // BeginImplFrame should prepare the draw.
1844 client.Reset();
1845 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1846 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1847 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1848 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1849 EXPECT_TRUE(client.needs_begin_frame());
1850
1851 client.Reset();
1852 EXPECT_FALSE(scheduler->IsBeginRetroFrameArgsEmpty());
1853 scheduler->DidLoseOutputSurface();
1854 EXPECT_NO_ACTION(client);
1855 EXPECT_TRUE(scheduler->IsBeginRetroFrameArgsEmpty());
1856
1857 // BeginImplFrame deadline should abort drawing.
1858 client.Reset();
1859 client.task_runner().RunPendingTasks(); // Run posted deadline.
1860 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1861 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1862 EXPECT_TRUE(client.needs_begin_frame());
1863
1864 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
1865 client.Reset();
1866 client.task_runner().RunPendingTasks();
1867 EXPECT_NO_ACTION(client);
1868 }
1869
TEST(SchedulerTest,StopBeginFrameAfterDidLoseOutputSurfaceWithSyntheticBeginFrameSource)1870 TEST(SchedulerTest,
1871 StopBeginFrameAfterDidLoseOutputSurfaceWithSyntheticBeginFrameSource) {
1872 FakeSchedulerClient client;
1873 SchedulerSettings scheduler_settings;
1874 scheduler_settings.begin_frame_scheduling_enabled = false;
1875 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1876 scheduler->SetCanStart();
1877 scheduler->SetVisible(true);
1878 scheduler->SetCanDraw(true);
1879 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1880
1881 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1882 client.Reset();
1883 EXPECT_FALSE(scheduler->IsSyntheticBeginFrameSourceActive());
1884 scheduler->SetNeedsCommit();
1885 EXPECT_TRUE(scheduler->IsSyntheticBeginFrameSourceActive());
1886
1887 client.Reset();
1888 client.task_runner().RunPendingTasks(); // Run posted Tick.
1889 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1890 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1891 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1892 EXPECT_TRUE(scheduler->IsSyntheticBeginFrameSourceActive());
1893
1894 // NotifyReadyToCommit should trigger the commit.
1895 client.Reset();
1896 scheduler->NotifyBeginMainFrameStarted();
1897 scheduler->NotifyReadyToCommit();
1898 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1899 EXPECT_TRUE(scheduler->IsSyntheticBeginFrameSourceActive());
1900
1901 client.Reset();
1902 scheduler->DidLoseOutputSurface();
1903 EXPECT_EQ(0, client.num_actions_());
1904 EXPECT_FALSE(scheduler->IsSyntheticBeginFrameSourceActive());
1905
1906 client.Reset();
1907 client.task_runner().RunPendingTasks(); // Run posted deadline.
1908 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1909 EXPECT_FALSE(scheduler->IsSyntheticBeginFrameSourceActive());
1910 }
1911
TEST(SchedulerTest,ScheduledActionActivateAfterBecomingInvisible)1912 TEST(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) {
1913 FakeSchedulerClient client;
1914 SchedulerSettings scheduler_settings;
1915 scheduler_settings.impl_side_painting = true;
1916 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1917 scheduler->SetCanStart();
1918 scheduler->SetVisible(true);
1919 scheduler->SetCanDraw(true);
1920
1921 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1922 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1923
1924 // SetNeedsCommit should begin the frame.
1925 client.Reset();
1926 scheduler->SetNeedsCommit();
1927 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1928
1929 client.Reset();
1930 client.AdvanceFrame();
1931 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1932 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1933 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1934
1935 client.Reset();
1936 scheduler->NotifyBeginMainFrameStarted();
1937 scheduler->NotifyReadyToCommit();
1938 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1939
1940 client.Reset();
1941 scheduler->SetVisible(false);
1942 // Sync tree should be forced to activate.
1943 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client);
1944 }
1945
1946 } // namespace
1947 } // namespace cc
1948