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