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