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