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