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