Make content_shell.exe a console app in ASan/Win builds
[chromium-blink-merge.git] / cc / scheduler / scheduler_unittest.cc
blobaa61af73e884bde064647b08281406ca41df2511
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"
6 #include <string>
7 #include <vector>
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"
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)
32 #define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0)
34 #define EXPECT_SINGLE_ACTION(action, client) \
35 EXPECT_ACTION(action, client, 0, 1)
37 namespace cc {
38 namespace {
40 class FakeSchedulerClient;
42 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler,
43 FakeSchedulerClient* client);
45 class TestScheduler : public Scheduler {
46 public:
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));
56 virtual ~TestScheduler() {}
58 bool IsBeginRetroFrameArgsEmpty() const {
59 return begin_retro_frame_args_.empty();
62 bool IsSyntheticBeginFrameSourceActive() const {
63 return synthetic_begin_frame_source_->IsActive();
66 private:
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) {
79 class FakeSchedulerClient : public SchedulerClient {
80 public:
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();
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;
98 TestScheduler* CreateScheduler(const SchedulerSettings& settings) {
99 task_runner_ = new OrderedSimpleTaskRunner;
100 scheduler_ = TestScheduler::Create(this, settings, 0, task_runner_);
101 return scheduler_.get();
104 // Most tests don't care about DidAnticipatedDrawTimeChange, so only record it
105 // for tests that do.
106 void set_log_anticipated_draw_time_change(bool log) {
107 log_anticipated_draw_time_change_ = log;
109 bool needs_begin_frame() { return needs_begin_frame_; }
110 int num_draws() const { return num_draws_; }
111 int num_actions_() const { return static_cast<int>(actions_.size()); }
112 const char* Action(int i) const { return actions_[i]; }
113 base::Value& StateForAction(int i) const { return *states_[i]; }
114 base::TimeTicks posted_begin_impl_frame_deadline() const {
115 return posted_begin_impl_frame_deadline_;
118 OrderedSimpleTaskRunner& task_runner() { return *task_runner_; }
120 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;
127 void SetSwapContainsIncompleteTile(bool contain) {
128 swap_contains_incomplete_tile_ = contain;
131 bool HasAction(const char* action) const {
132 return ActionIndex(action) >= 0;
135 void SetDrawWillHappen(bool draw_will_happen) {
136 draw_will_happen_ = draw_will_happen;
138 void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
139 swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
141 void SetAutomaticSwapAck(bool automatic_swap_ack) {
142 automatic_swap_ack_ = automatic_swap_ack;
144 void SetRedrawWillHappenIfUpdateVisibleTilesHappens(bool redraw) {
145 redraw_will_happen_if_update_visible_tiles_happens_ = redraw;
147 // SchedulerClient implementation.
148 virtual void SetNeedsBeginFrame(bool enable) OVERRIDE {
149 actions_.push_back("SetNeedsBeginFrame");
150 states_.push_back(scheduler_->AsValue().release());
151 needs_begin_frame_ = enable;
153 virtual void WillBeginImplFrame(const BeginFrameArgs& args) OVERRIDE {
154 actions_.push_back("WillBeginImplFrame");
155 states_.push_back(scheduler_->AsValue().release());
157 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {
158 actions_.push_back("ScheduledActionSendBeginMainFrame");
159 states_.push_back(scheduler_->AsValue().release());
161 virtual void ScheduledActionAnimate() OVERRIDE {
162 actions_.push_back("ScheduledActionAnimate");
163 states_.push_back(scheduler_->AsValue().release());
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);
182 if (automatic_swap_ack_)
183 scheduler_->DidSwapBuffersComplete();
185 return result;
187 virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE {
188 actions_.push_back("ScheduledActionDrawAndSwapForced");
189 states_.push_back(scheduler_->AsValue().release());
190 return DRAW_SUCCESS;
192 virtual void ScheduledActionCommit() OVERRIDE {
193 actions_.push_back("ScheduledActionCommit");
194 states_.push_back(scheduler_->AsValue().release());
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();
202 virtual void ScheduledActionActivateSyncTree() OVERRIDE {
203 actions_.push_back("ScheduledActionActivateSyncTree");
204 states_.push_back(scheduler_->AsValue().release());
206 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {
207 actions_.push_back("ScheduledActionBeginOutputSurfaceCreation");
208 states_.push_back(scheduler_->AsValue().release());
210 virtual void ScheduledActionManageTiles() OVERRIDE {
211 actions_.push_back("ScheduledActionManageTiles");
212 states_.push_back(scheduler_->AsValue().release());
214 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {
215 if (log_anticipated_draw_time_change_)
216 actions_.push_back("DidAnticipatedDrawTimeChange");
218 virtual base::TimeDelta DrawDurationEstimate() OVERRIDE {
219 return base::TimeDelta();
221 virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE {
222 return base::TimeDelta();
224 virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE {
225 return base::TimeDelta();
228 virtual void DidBeginImplFrameDeadline() OVERRIDE {}
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_;
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;
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.
264 // Run the posted deadline task.
265 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
266 client->task_runner().RunPendingTasks();
267 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
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.
276 // Run the posted deadline task.
277 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
278 client->task_runner().RunPendingTasks();
279 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
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);
290 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
291 client.Reset();
292 scheduler->DidCreateAndInitializeOutputSurface();
293 EXPECT_NO_ACTION(client);
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);
304 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
305 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
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();
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();
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();
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();
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();
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();
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();
357 client.task_runner().RunPendingTasks(); // Run posted deadline.
358 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
359 EXPECT_FALSE(client.needs_begin_frame());
360 client.Reset();
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);
371 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
372 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
373 client.Reset();
375 // SetNeedsCommit should begin the frame.
376 scheduler->SetNeedsCommit();
377 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
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());
385 EXPECT_TRUE(client.needs_begin_frame());
386 client.Reset();
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();
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());
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();
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();
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();
438 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
439 public:
440 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
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();
449 virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE {
450 NOTREACHED();
451 return DRAW_SUCCESS;
454 virtual void ScheduledActionCommit() OVERRIDE {}
455 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {}
456 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
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
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();
473 scheduler->SetNeedsRedraw();
474 EXPECT_TRUE(scheduler->RedrawPending());
475 EXPECT_TRUE(client.needs_begin_frame());
476 EXPECT_EQ(0, client.num_draws());
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());
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());
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());
499 // Test that requesting redraw inside a failed draw doesn't lose the request.
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();
510 client.SetDrawWillHappen(false);
512 scheduler->SetNeedsRedraw();
513 EXPECT_TRUE(scheduler->RedrawPending());
514 EXPECT_TRUE(client.needs_begin_frame());
515 EXPECT_EQ(0, client.num_draws());
517 // Fail the draw.
518 scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
519 client.task_runner().RunPendingTasks(); // Run posted deadline.
520 EXPECT_EQ(1, client.num_draws());
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());
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());
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());
546 class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
547 public:
548 SchedulerClientThatSetNeedsCommitInsideDraw()
549 : set_needs_commit_on_next_draw_(false) {}
551 virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
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;
559 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
562 virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE {
563 NOTREACHED();
564 return DRAW_SUCCESS;
567 virtual void ScheduledActionCommit() OVERRIDE {}
568 virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {}
569 virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
571 void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; }
573 private:
574 bool set_needs_commit_on_next_draw_;
577 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
578 // happen inside a ScheduledActionDrawAndSwap
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();
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());
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();
605 scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
606 client.task_runner().RunPendingTasks(); // Run posted deadline.
607 EXPECT_EQ(2, client.num_draws());
609 EXPECT_FALSE(scheduler->RedrawPending());
610 EXPECT_FALSE(scheduler->CommitPending());
611 EXPECT_TRUE(client.needs_begin_frame());
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());
623 // Tests that when a draw fails then the pending commit should not be dropped.
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();
634 client.SetDrawWillHappen(false);
636 scheduler->SetNeedsRedraw();
637 EXPECT_TRUE(scheduler->RedrawPending());
638 EXPECT_TRUE(client.needs_begin_frame());
639 EXPECT_EQ(0, client.num_draws());
641 // Fail the draw.
642 scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
643 client.task_runner().RunPendingTasks(); // Run posted deadline.
644 EXPECT_EQ(1, client.num_draws());
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());
652 // Fail the draw again.
653 scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
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());
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());
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();
681 scheduler->SetNeedsRedraw();
682 EXPECT_TRUE(scheduler->RedrawPending());
683 EXPECT_TRUE(client.needs_begin_frame());
684 EXPECT_EQ(0, client.num_draws());
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());
692 scheduler->SetNeedsRedraw();
693 EXPECT_TRUE(scheduler->RedrawPending());
694 EXPECT_TRUE(client.needs_begin_frame());
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());
704 class SchedulerClientNeedsManageTilesInDraw : public FakeSchedulerClient {
705 public:
706 virtual DrawResult ScheduledActionDrawAndSwapIfPossible()
707 OVERRIDE {
708 scheduler_->SetNeedsManageTiles();
709 return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
713 // Test manage tiles is independant of draws.
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);
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"));
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());
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());
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());
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());
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());
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());
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());
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());
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.
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);
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());
839 EXPECT_TRUE(scheduler->ManageTilesPending());
840 scheduler->DidManageTiles(); // An explicit ManageTiles.
841 EXPECT_FALSE(scheduler->ManageTilesPending());
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());
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());
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
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());
884 EXPECT_TRUE(scheduler->ManageTilesPending());
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());
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());
907 EXPECT_TRUE(scheduler->ManageTilesPending());
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());
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());
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
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);
949 client.SetRedrawWillHappenIfUpdateVisibleTilesHappens(true);
951 // SetNeedsCommit should begin the frame.
952 client.Reset();
953 scheduler->SetNeedsCommit();
954 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
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());
962 client.Reset();
963 scheduler->NotifyBeginMainFrameStarted();
964 scheduler->NotifyReadyToCommit();
965 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
967 client.Reset();
968 scheduler->NotifyReadyToActivate();
969 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client);
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());
978 client.Reset();
979 scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
980 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
981 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
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);
989 client.Reset();
990 scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
991 EXPECT_SINGLE_ACTION("WillBeginImplFrame", client);
992 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
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());
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);
1010 client.Reset();
1011 scheduler->SetNeedsRedraw();
1012 scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
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());
1019 class SchedulerClientWithFixedEstimates : public FakeSchedulerClient {
1020 public:
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) {}
1030 virtual base::TimeDelta DrawDurationEstimate() OVERRIDE {
1031 return draw_duration_;
1033 virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE {
1034 return begin_main_frame_to_commit_duration_;
1036 virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE {
1037 return commit_to_activate_duration_;
1040 private:
1041 base::TimeDelta draw_duration_;
1042 base::TimeDelta begin_main_frame_to_commit_duration_;
1043 base::TimeDelta commit_to_activate_duration_;
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);
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"));
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);
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);
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);
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);
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);
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);
1126 scheduler->SetCanDraw(true);
1127 scheduler->SetCanStart();
1128 scheduler->SetVisible(true);
1129 scheduler->DidCreateAndInitializeOutputSurface();
1131 scheduler->SetNeedsCommit();
1132 EXPECT_TRUE(scheduler->CommitPending());
1133 scheduler->NotifyBeginMainFrameStarted();
1134 scheduler->NotifyReadyToCommit();
1135 scheduler->SetNeedsRedraw();
1137 BeginFrameArgs frame_args = CreateBeginFrameArgsForTesting();
1138 frame_args.interval = base::TimeDelta::FromMilliseconds(1000);
1139 scheduler->BeginFrame(frame_args);
1141 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1142 client.task_runner().RunPendingTasks(); // Run posted deadline.
1143 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1145 scheduler->DidSwapBuffers();
1146 scheduler->DidSwapBuffersComplete();
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());
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();
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_();
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_();
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_();
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);
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();
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();
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);
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();
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();
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();
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();
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();
1261 client.task_runner().RunPendingTasks(); // Run posted deadline.
1262 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1263 EXPECT_FALSE(client.needs_begin_frame());
1264 client.Reset();
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);
1276 // To test swap ack throttling, this test disables automatic swap acks.
1277 scheduler->SetMaxSwapsPending(1);
1278 client.SetAutomaticSwapAck(false);
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();
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();
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();
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();
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();
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();
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();
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();
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();
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);
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();
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();
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();
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();
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();
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();
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();
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();
1429 // See: http://crbug.com/388901
1430 TEST(SchedulerTest, DISABLED_SyntheticBeginFrames) {
1431 bool begin_frame_scheduling_enabled = false;
1432 bool throttle_frame_production = true;
1433 BeginFramesNotFromClient(begin_frame_scheduling_enabled,
1434 throttle_frame_production);
1437 TEST(SchedulerTest, VSyncThrottlingDisabled) {
1438 bool begin_frame_scheduling_enabled = true;
1439 bool throttle_frame_production = false;
1440 BeginFramesNotFromClient(begin_frame_scheduling_enabled,
1441 throttle_frame_production);
1444 TEST(SchedulerTest, SyntheticBeginFrames_And_VSyncThrottlingDisabled) {
1445 bool begin_frame_scheduling_enabled = false;
1446 bool throttle_frame_production = false;
1447 BeginFramesNotFromClient(begin_frame_scheduling_enabled,
1448 throttle_frame_production);
1451 void BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled,
1452 bool throttle_frame_production) {
1453 FakeSchedulerClient client;
1454 SchedulerSettings scheduler_settings;
1455 scheduler_settings.begin_frame_scheduling_enabled =
1456 begin_frame_scheduling_enabled;
1457 scheduler_settings.throttle_frame_production = throttle_frame_production;
1458 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1459 scheduler->SetCanStart();
1460 scheduler->SetVisible(true);
1461 scheduler->SetCanDraw(true);
1462 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1464 // To test swap ack throttling, this test disables automatic swap acks.
1465 scheduler->SetMaxSwapsPending(1);
1466 client.SetAutomaticSwapAck(false);
1468 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1469 client.Reset();
1470 scheduler->SetNeedsCommit();
1471 EXPECT_FALSE(client.needs_begin_frame());
1472 EXPECT_NO_ACTION(client);
1473 client.Reset();
1475 // Trigger the first BeginImplFrame and BeginMainFrame
1476 client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1477 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1478 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1479 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1480 EXPECT_FALSE(client.needs_begin_frame());
1481 client.Reset();
1483 // NotifyReadyToCommit should trigger the pending commit and draw.
1484 scheduler->NotifyBeginMainFrameStarted();
1485 scheduler->NotifyReadyToCommit();
1486 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1487 EXPECT_FALSE(client.needs_begin_frame());
1488 client.Reset();
1490 // Swapping will put us into a swap throttled state.
1491 client.task_runner().RunPendingTasks(); // Run posted deadline.
1492 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
1493 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
1494 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1495 EXPECT_FALSE(client.needs_begin_frame());
1496 client.Reset();
1498 // While swap throttled, BeginFrames should trigger BeginImplFrames,
1499 // but not a BeginMainFrame or draw.
1500 scheduler->SetNeedsCommit();
1501 client.task_runner().RunPendingTasks(); // Run posted BeginFrame.
1502 EXPECT_ACTION("WillBeginImplFrame", client, 0, 1);
1503 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1504 EXPECT_FALSE(client.needs_begin_frame());
1505 client.Reset();
1507 // Take us out of a swap throttled state.
1508 scheduler->DidSwapBuffersComplete();
1509 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 1);
1510 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1511 EXPECT_FALSE(client.needs_begin_frame());
1512 client.Reset();
1514 // BeginImplFrame deadline should draw.
1515 scheduler->SetNeedsRedraw();
1516 client.task_runner().RunPendingTasks(); // Run posted deadline.
1517 EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2);
1518 EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2);
1519 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1520 EXPECT_FALSE(client.needs_begin_frame());
1521 client.Reset();
1524 TEST(SchedulerTest, SyntheticBeginFrames_SwapThrottled) {
1525 bool begin_frame_scheduling_enabled = false;
1526 bool throttle_frame_production = true;
1527 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled,
1528 throttle_frame_production);
1531 TEST(SchedulerTest, VSyncThrottlingDisabled_SwapThrottled) {
1532 bool begin_frame_scheduling_enabled = true;
1533 bool throttle_frame_production = false;
1534 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled,
1535 throttle_frame_production);
1538 TEST(SchedulerTest,
1539 SyntheticBeginFrames_And_VSyncThrottlingDisabled_SwapThrottled) {
1540 bool begin_frame_scheduling_enabled = false;
1541 bool throttle_frame_production = false;
1542 BeginFramesNotFromClient_SwapThrottled(begin_frame_scheduling_enabled,
1543 throttle_frame_production);
1546 TEST(SchedulerTest, DidLoseOutputSurfaceAfterOutputSurfaceIsInitialized) {
1547 FakeSchedulerClient client;
1548 SchedulerSettings scheduler_settings;
1549 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1550 scheduler->SetCanStart();
1551 scheduler->SetVisible(true);
1552 scheduler->SetCanDraw(true);
1554 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1555 client.Reset();
1556 scheduler->DidCreateAndInitializeOutputSurface();
1557 EXPECT_NO_ACTION(client);
1559 scheduler->DidLoseOutputSurface();
1560 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1563 TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) {
1564 FakeSchedulerClient client;
1565 SchedulerSettings scheduler_settings;
1566 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1567 scheduler->SetCanStart();
1568 scheduler->SetVisible(true);
1569 scheduler->SetCanDraw(true);
1571 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1572 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1573 // SetNeedsCommit should begin the frame.
1574 client.Reset();
1575 scheduler->SetNeedsCommit();
1576 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1578 client.Reset();
1579 scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
1580 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1581 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1582 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1584 client.Reset();
1585 scheduler->DidLoseOutputSurface();
1586 // Do nothing when impl frame is in deadine pending state.
1587 EXPECT_NO_ACTION(client);
1589 client.Reset();
1590 scheduler->NotifyBeginMainFrameStarted();
1591 scheduler->NotifyReadyToCommit();
1592 EXPECT_ACTION("ScheduledActionCommit", client, 0, 1);
1594 client.Reset();
1595 client.task_runner().RunPendingTasks(); // Run posted deadline.
1596 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1599 void DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(
1600 bool impl_side_painting) {
1601 FakeSchedulerClient client;
1602 SchedulerSettings scheduler_settings;
1603 scheduler_settings.impl_side_painting = impl_side_painting;
1604 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1605 scheduler->SetCanStart();
1606 scheduler->SetVisible(true);
1607 scheduler->SetCanDraw(true);
1609 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1610 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1612 // SetNeedsCommit should begin the frame.
1613 client.Reset();
1614 scheduler->SetNeedsCommit();
1615 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1617 client.Reset();
1618 scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
1619 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1620 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1621 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1623 client.Reset();
1624 scheduler->DidLoseOutputSurface();
1625 // Do nothing when impl frame is in deadine pending state.
1626 EXPECT_NO_ACTION(client);
1628 client.Reset();
1629 client.task_runner().RunPendingTasks(); // Run posted deadline.
1630 // OnBeginImplFrameDeadline didn't schedule any actions because main frame is
1631 // not yet completed.
1632 EXPECT_NO_ACTION(client);
1634 // BeginImplFrame is not started.
1635 scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
1636 EXPECT_NO_ACTION(client);
1637 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1639 client.Reset();
1640 scheduler->NotifyBeginMainFrameStarted();
1641 scheduler->NotifyReadyToCommit();
1642 if (impl_side_painting) {
1643 EXPECT_ACTION("ScheduledActionCommit", client, 0, 3);
1644 EXPECT_ACTION("ScheduledActionActivateSyncTree", client, 1, 3);
1645 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 2, 3);
1646 } else {
1647 EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
1648 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 1, 2);
1652 TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency) {
1653 bool impl_side_painting = false;
1654 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
1657 TEST(SchedulerTest,
1658 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatencyWithImplPaint) {
1659 bool impl_side_painting = true;
1660 DidLoseOutputSurfaceAfterBeginFrameStartedWithHighLatency(impl_side_painting);
1663 void DidLoseOutputSurfaceAfterReadyToCommit(bool impl_side_painting) {
1664 FakeSchedulerClient client;
1665 SchedulerSettings scheduler_settings;
1666 scheduler_settings.impl_side_painting = impl_side_painting;
1667 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1668 scheduler->SetCanStart();
1669 scheduler->SetVisible(true);
1670 scheduler->SetCanDraw(true);
1672 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1673 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1675 // SetNeedsCommit should begin the frame.
1676 client.Reset();
1677 scheduler->SetNeedsCommit();
1678 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1680 client.Reset();
1681 scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
1682 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1683 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1684 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1686 client.Reset();
1687 scheduler->NotifyBeginMainFrameStarted();
1688 scheduler->NotifyReadyToCommit();
1689 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1691 client.Reset();
1692 scheduler->DidLoseOutputSurface();
1693 if (impl_side_painting) {
1694 // Sync tree should be forced to activate.
1695 EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client);
1696 } else {
1697 // Do nothing when impl frame is in deadine pending state.
1698 EXPECT_NO_ACTION(client);
1701 client.Reset();
1702 client.task_runner().RunPendingTasks(); // Run posted deadline.
1703 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1706 TEST(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) {
1707 DidLoseOutputSurfaceAfterReadyToCommit(false);
1710 TEST(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommitWithImplPainting) {
1711 DidLoseOutputSurfaceAfterReadyToCommit(true);
1714 TEST(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsManageTiles) {
1715 FakeSchedulerClient client;
1716 SchedulerSettings scheduler_settings;
1717 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1718 scheduler->SetCanStart();
1719 scheduler->SetVisible(true);
1720 scheduler->SetCanDraw(true);
1721 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1723 client.Reset();
1724 scheduler->SetNeedsManageTiles();
1725 scheduler->SetNeedsRedraw();
1726 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1727 EXPECT_TRUE(client.needs_begin_frame());
1729 client.Reset();
1730 scheduler->BeginFrame(CreateBeginFrameArgsForTesting());
1731 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1732 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1733 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1735 client.Reset();
1736 scheduler->DidLoseOutputSurface();
1737 EXPECT_NO_ACTION(client);
1739 client.Reset();
1740 client.task_runner().RunPendingTasks(); // Run posted deadline.
1741 EXPECT_ACTION("ScheduledActionManageTiles", client, 0, 2);
1742 EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client, 1, 2);
1745 TEST(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) {
1746 FakeSchedulerClient client;
1747 SchedulerSettings scheduler_settings;
1748 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1749 scheduler->SetCanStart();
1750 scheduler->SetVisible(true);
1751 scheduler->SetCanDraw(true);
1752 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1754 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1755 client.Reset();
1756 scheduler->SetNeedsCommit();
1757 EXPECT_TRUE(client.needs_begin_frame());
1758 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1760 // Create a BeginFrame with a long deadline to avoid race conditions.
1761 // This is the first BeginFrame, which will be handled immediately.
1762 client.Reset();
1763 BeginFrameArgs args = CreateBeginFrameArgsForTesting();
1764 args.deadline += base::TimeDelta::FromHours(1);
1765 scheduler->BeginFrame(args);
1766 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1767 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1768 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1769 EXPECT_TRUE(client.needs_begin_frame());
1771 // Queue BeginFrames while we are still handling the previous BeginFrame.
1772 args.frame_time += base::TimeDelta::FromSeconds(1);
1773 scheduler->BeginFrame(args);
1774 args.frame_time += base::TimeDelta::FromSeconds(1);
1775 scheduler->BeginFrame(args);
1777 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1778 client.Reset();
1779 client.task_runner().RunPendingTasks(); // Run posted deadline.
1780 EXPECT_NO_ACTION(client);
1781 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1782 EXPECT_TRUE(client.needs_begin_frame());
1784 // NotifyReadyToCommit should trigger the commit.
1785 client.Reset();
1786 scheduler->NotifyBeginMainFrameStarted();
1787 scheduler->NotifyReadyToCommit();
1788 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1789 EXPECT_TRUE(client.needs_begin_frame());
1791 client.Reset();
1792 EXPECT_FALSE(scheduler->IsBeginRetroFrameArgsEmpty());
1793 scheduler->DidLoseOutputSurface();
1794 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1795 EXPECT_TRUE(client.needs_begin_frame());
1796 EXPECT_TRUE(scheduler->IsBeginRetroFrameArgsEmpty());
1798 // Posted BeginRetroFrame is aborted.
1799 client.Reset();
1800 client.task_runner().RunPendingTasks();
1801 EXPECT_NO_ACTION(client);
1804 TEST(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) {
1805 FakeSchedulerClient client;
1806 SchedulerSettings scheduler_settings;
1807 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1808 scheduler->SetCanStart();
1809 scheduler->SetVisible(true);
1810 scheduler->SetCanDraw(true);
1811 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1813 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1814 client.Reset();
1815 scheduler->SetNeedsCommit();
1816 EXPECT_TRUE(client.needs_begin_frame());
1817 EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
1819 // Create a BeginFrame with a long deadline to avoid race conditions.
1820 // This is the first BeginFrame, which will be handled immediately.
1821 client.Reset();
1822 BeginFrameArgs args = CreateBeginFrameArgsForTesting();
1823 args.deadline += base::TimeDelta::FromHours(1);
1824 scheduler->BeginFrame(args);
1825 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1826 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1827 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1828 EXPECT_TRUE(client.needs_begin_frame());
1830 // Queue BeginFrames while we are still handling the previous BeginFrame.
1831 args.frame_time += base::TimeDelta::FromSeconds(1);
1832 scheduler->BeginFrame(args);
1833 args.frame_time += base::TimeDelta::FromSeconds(1);
1834 scheduler->BeginFrame(args);
1836 // If we don't swap on the deadline, we wait for the next BeginImplFrame.
1837 client.Reset();
1838 client.task_runner().RunPendingTasks(); // Run posted deadline.
1839 EXPECT_NO_ACTION(client);
1840 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1841 EXPECT_TRUE(client.needs_begin_frame());
1843 // NotifyReadyToCommit should trigger the commit.
1844 client.Reset();
1845 scheduler->NotifyBeginMainFrameStarted();
1846 scheduler->NotifyReadyToCommit();
1847 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1848 EXPECT_TRUE(client.needs_begin_frame());
1850 // BeginImplFrame should prepare the draw.
1851 client.Reset();
1852 client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
1853 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1854 EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2);
1855 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1856 EXPECT_TRUE(client.needs_begin_frame());
1858 client.Reset();
1859 EXPECT_FALSE(scheduler->IsBeginRetroFrameArgsEmpty());
1860 scheduler->DidLoseOutputSurface();
1861 EXPECT_NO_ACTION(client);
1862 EXPECT_TRUE(scheduler->IsBeginRetroFrameArgsEmpty());
1864 // BeginImplFrame deadline should abort drawing.
1865 client.Reset();
1866 client.task_runner().RunPendingTasks(); // Run posted deadline.
1867 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1868 EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
1869 EXPECT_TRUE(client.needs_begin_frame());
1871 // No more BeginRetroFrame because BeginRetroFrame queue is cleared.
1872 client.Reset();
1873 client.task_runner().RunPendingTasks();
1874 EXPECT_NO_ACTION(client);
1877 TEST(SchedulerTest,
1878 StopBeginFrameAfterDidLoseOutputSurfaceWithSyntheticBeginFrameSource) {
1879 FakeSchedulerClient client;
1880 SchedulerSettings scheduler_settings;
1881 scheduler_settings.begin_frame_scheduling_enabled = false;
1882 TestScheduler* scheduler = client.CreateScheduler(scheduler_settings);
1883 scheduler->SetCanStart();
1884 scheduler->SetVisible(true);
1885 scheduler->SetCanDraw(true);
1886 InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
1888 // SetNeedsCommit should begin the frame on the next BeginImplFrame.
1889 client.Reset();
1890 EXPECT_FALSE(scheduler->IsSyntheticBeginFrameSourceActive());
1891 scheduler->SetNeedsCommit();
1892 EXPECT_TRUE(scheduler->IsSyntheticBeginFrameSourceActive());
1894 client.Reset();
1895 client.task_runner().RunPendingTasks(); // Run posted Tick.
1896 EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
1897 EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
1898 EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
1899 EXPECT_TRUE(scheduler->IsSyntheticBeginFrameSourceActive());
1901 // NotifyReadyToCommit should trigger the commit.
1902 client.Reset();
1903 scheduler->NotifyBeginMainFrameStarted();
1904 scheduler->NotifyReadyToCommit();
1905 EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
1906 EXPECT_TRUE(scheduler->IsSyntheticBeginFrameSourceActive());
1908 client.Reset();
1909 scheduler->DidLoseOutputSurface();
1910 EXPECT_EQ(0, client.num_actions_());
1911 EXPECT_FALSE(scheduler->IsSyntheticBeginFrameSourceActive());
1913 client.Reset();
1914 client.task_runner().RunPendingTasks(); // Run posted deadline.
1915 EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
1916 EXPECT_FALSE(scheduler->IsSyntheticBeginFrameSourceActive());
1919 } // namespace
1920 } // namespace cc