- add sources.
[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/logging.h"
10 #include "base/memory/scoped_vector.h"
11 #include "cc/test/scheduler_test_common.h"
12 #include "testing/gmock/include/gmock/gmock.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 #define EXPECT_ACTION(action, client, action_index, expected_num_actions) \
16   EXPECT_EQ(expected_num_actions, client.num_actions_());                 \
17   ASSERT_LT(action_index, client.num_actions_());                         \
18   do {                                                                    \
19     EXPECT_STREQ(action, client.Action(action_index));                    \
20     for (int i = expected_num_actions; i < client.num_actions_(); ++i)    \
21       ADD_FAILURE() << "Unexpected action: " << client.Action(i) <<       \
22           " with state:\n" << client.StateForAction(action_index);        \
23   } while (false)
24
25 #define EXPECT_SINGLE_ACTION(action, client) \
26   EXPECT_ACTION(action, client, 0, 1)
27
28 namespace cc {
29 namespace {
30
31 void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler) {
32   scheduler->DidCreateAndInitializeOutputSurface();
33   scheduler->SetNeedsCommit();
34   scheduler->FinishCommit();
35   // Go through the motions to draw the commit.
36   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
37   scheduler->OnBeginImplFrameDeadline();
38   // We need another BeginImplFrame so Scheduler calls
39   // SetNeedsBeginImplFrame(false).
40   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
41   scheduler->OnBeginImplFrameDeadline();
42 }
43
44 class FakeSchedulerClient : public SchedulerClient {
45  public:
46   FakeSchedulerClient()
47   : needs_begin_impl_frame_(false) {
48     Reset();
49   }
50
51   void Reset() {
52     actions_.clear();
53     states_.clear();
54     draw_will_happen_ = true;
55     swap_will_happen_if_draw_happens_ = true;
56     num_draws_ = 0;
57   }
58
59   Scheduler* CreateScheduler(const SchedulerSettings& settings) {
60     scheduler_ = Scheduler::Create(this, settings);
61     return scheduler_.get();
62   }
63
64   bool needs_begin_impl_frame() { return needs_begin_impl_frame_; }
65   int num_draws() const { return num_draws_; }
66   int num_actions_() const { return static_cast<int>(actions_.size()); }
67   const char* Action(int i) const { return actions_[i]; }
68   base::Value& StateForAction(int i) const { return *states_[i]; }
69
70   int ActionIndex(const char* action) const {
71     for (size_t i = 0; i < actions_.size(); i++)
72       if (!strcmp(actions_[i], action))
73         return i;
74     return -1;
75   }
76
77   bool HasAction(const char* action) const {
78     return ActionIndex(action) >= 0;
79   }
80
81   void SetDrawWillHappen(bool draw_will_happen) {
82     draw_will_happen_ = draw_will_happen;
83   }
84   void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
85     swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
86   }
87
88   // Scheduler Implementation.
89   virtual void SetNeedsBeginImplFrame(bool enable) OVERRIDE {
90     actions_.push_back("SetNeedsBeginImplFrame");
91     states_.push_back(scheduler_->StateAsValue().release());
92     needs_begin_impl_frame_ = enable;
93   }
94   virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {
95     actions_.push_back("ScheduledActionSendBeginMainFrame");
96     states_.push_back(scheduler_->StateAsValue().release());
97   }
98   virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
99       OVERRIDE {
100     actions_.push_back("ScheduledActionDrawAndSwapIfPossible");
101     states_.push_back(scheduler_->StateAsValue().release());
102     num_draws_++;
103     bool did_readback = false;
104     return DrawSwapReadbackResult(
105         draw_will_happen_,
106         draw_will_happen_ && swap_will_happen_if_draw_happens_,
107         did_readback);
108   }
109   virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
110     actions_.push_back("ScheduledActionDrawAndSwapForced");
111     states_.push_back(scheduler_->StateAsValue().release());
112     bool did_draw = true;
113     bool did_swap = swap_will_happen_if_draw_happens_;
114     bool did_readback = false;
115     return DrawSwapReadbackResult(did_draw, did_swap, did_readback);
116   }
117   virtual DrawSwapReadbackResult ScheduledActionDrawAndReadback() OVERRIDE {
118     actions_.push_back("ScheduledActionDrawAndReadback");
119     states_.push_back(scheduler_->StateAsValue().release());
120     bool did_draw = true;
121     bool did_swap = false;
122     bool did_readback = true;
123     return DrawSwapReadbackResult(did_draw, did_swap, did_readback);
124   }
125   virtual void ScheduledActionCommit() OVERRIDE {
126     actions_.push_back("ScheduledActionCommit");
127     states_.push_back(scheduler_->StateAsValue().release());
128   }
129   virtual void ScheduledActionUpdateVisibleTiles() OVERRIDE {
130     actions_.push_back("ScheduledActionUpdateVisibleTiles");
131     states_.push_back(scheduler_->StateAsValue().release());
132   }
133   virtual void ScheduledActionActivatePendingTree() OVERRIDE {
134     actions_.push_back("ScheduledActionActivatePendingTree");
135     states_.push_back(scheduler_->StateAsValue().release());
136   }
137   virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {
138     actions_.push_back("ScheduledActionBeginOutputSurfaceCreation");
139     states_.push_back(scheduler_->StateAsValue().release());
140   }
141   virtual void ScheduledActionAcquireLayerTexturesForMainThread() OVERRIDE {
142     actions_.push_back("ScheduledActionAcquireLayerTexturesForMainThread");
143     states_.push_back(scheduler_->StateAsValue().release());
144   }
145   virtual void ScheduledActionManageTiles() OVERRIDE {
146     actions_.push_back("ScheduledActionManageTiles");
147     states_.push_back(scheduler_->StateAsValue().release());
148   }
149   virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
150   virtual base::TimeDelta DrawDurationEstimate() OVERRIDE {
151     return base::TimeDelta();
152   }
153   virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() OVERRIDE {
154     return base::TimeDelta();
155   }
156   virtual base::TimeDelta CommitToActivateDurationEstimate() OVERRIDE {
157     return base::TimeDelta();
158   }
159
160   virtual void PostBeginImplFrameDeadline(const base::Closure& closure,
161                                           base::TimeTicks deadline) OVERRIDE {
162     actions_.push_back("PostBeginImplFrameDeadlineTask");
163     states_.push_back(scheduler_->StateAsValue().release());
164   }
165
166   virtual void DidBeginImplFrameDeadline() OVERRIDE {}
167
168  protected:
169   bool needs_begin_impl_frame_;
170   bool draw_will_happen_;
171   bool swap_will_happen_if_draw_happens_;
172   int num_draws_;
173   std::vector<const char*> actions_;
174   ScopedVector<base::Value> states_;
175   scoped_ptr<Scheduler> scheduler_;
176 };
177
178 TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginImplFrame) {
179   FakeSchedulerClient client;
180   SchedulerSettings default_scheduler_settings;
181   Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
182   scheduler->SetCanStart();
183   scheduler->SetVisible(true);
184   scheduler->SetCanDraw(true);
185
186   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
187   client.Reset();
188   scheduler->DidCreateAndInitializeOutputSurface();
189   EXPECT_EQ(0, client.num_actions_());
190 }
191
192 void RequestCommit(bool deadline_scheduling_enabled) {
193   FakeSchedulerClient client;
194   SchedulerSettings scheduler_settings;
195   scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
196   Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
197   scheduler->SetCanStart();
198   scheduler->SetVisible(true);
199   scheduler->SetCanDraw(true);
200
201   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
202   InitializeOutputSurfaceAndFirstCommit(scheduler);
203
204   // SetNeedsCommit should begin the frame on the next BeginImplFrame.
205   client.Reset();
206   scheduler->SetNeedsCommit();
207   EXPECT_TRUE(client.needs_begin_impl_frame());
208   if (deadline_scheduling_enabled) {
209     EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
210   } else {
211     EXPECT_EQ(client.num_actions_(), 2);
212     EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
213     EXPECT_TRUE(client.HasAction("SetNeedsBeginImplFrame"));
214   }
215   client.Reset();
216
217   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
218   if (deadline_scheduling_enabled) {
219     EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
220     EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
221   } else {
222     EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
223   }
224   EXPECT_TRUE(client.needs_begin_impl_frame());
225   client.Reset();
226
227   // If we don't swap on the deadline, we need to request another
228   // BeginImplFrame.
229   scheduler->OnBeginImplFrameDeadline();
230   EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
231   EXPECT_TRUE(client.needs_begin_impl_frame());
232   client.Reset();
233
234   // FinishCommit should commit
235   scheduler->FinishCommit();
236   EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
237   EXPECT_TRUE(client.needs_begin_impl_frame());
238   client.Reset();
239
240   // BeginImplFrame should prepare the draw.
241   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
242   EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
243   EXPECT_TRUE(client.needs_begin_impl_frame());
244   client.Reset();
245
246   // BeginImplFrame deadline should draw.
247   scheduler->OnBeginImplFrameDeadline();
248   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
249   EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
250   EXPECT_TRUE(client.needs_begin_impl_frame());
251   client.Reset();
252
253   // The following BeginImplFrame deadline should SetNeedsBeginImplFrame(false)
254   // to avoid excessive toggles.
255   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
256   EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
257   client.Reset();
258
259   scheduler->OnBeginImplFrameDeadline();
260   EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
261   EXPECT_FALSE(client.needs_begin_impl_frame());
262   client.Reset();
263 }
264
265 TEST(SchedulerTest, RequestCommit) {
266   bool deadline_scheduling_enabled = false;
267   RequestCommit(deadline_scheduling_enabled);
268 }
269
270 TEST(SchedulerTest, RequestCommit_Deadline) {
271   bool deadline_scheduling_enabled = true;
272   RequestCommit(deadline_scheduling_enabled);
273 }
274
275 void RequestCommitAfterBeginMainFrameSent(
276     bool deadline_scheduling_enabled) {
277   FakeSchedulerClient client;
278   SchedulerSettings scheduler_settings;
279   scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
280   Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
281   scheduler->SetCanStart();
282   scheduler->SetVisible(true);
283   scheduler->SetCanDraw(true);
284
285   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
286   InitializeOutputSurfaceAndFirstCommit(scheduler);
287   client.Reset();
288
289   // SetNeedsCommit should begin the frame.
290   scheduler->SetNeedsCommit();
291   if (deadline_scheduling_enabled) {
292     EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
293   } else {
294     EXPECT_EQ(client.num_actions_(), 2);
295     EXPECT_TRUE(client.HasAction("SetNeedsBeginImplFrame"));
296     EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
297   }
298
299   client.Reset();
300   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
301   if (deadline_scheduling_enabled) {
302     EXPECT_EQ(client.num_actions_(), 2);
303     EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
304     EXPECT_TRUE(client.HasAction("PostBeginImplFrameDeadlineTask"));
305   } else {
306     EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
307   }
308
309   EXPECT_TRUE(client.needs_begin_impl_frame());
310   client.Reset();
311
312   // Now SetNeedsCommit again. Calling here means we need a second commit.
313   scheduler->SetNeedsCommit();
314   EXPECT_EQ(client.num_actions_(), 0);
315   client.Reset();
316
317   // Finish the first commit.
318   scheduler->FinishCommit();
319   EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
320   EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
321   client.Reset();
322   scheduler->OnBeginImplFrameDeadline();
323   if (deadline_scheduling_enabled) {
324     EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
325     EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
326   } else {
327     EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 3);
328     EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 3);
329     EXPECT_ACTION("SetNeedsBeginImplFrame", client, 2, 3);
330   }
331
332   // Because we just swapped, the Scheduler should also request the next
333   // BeginImplFrame from the OutputSurface.
334   EXPECT_TRUE(client.needs_begin_impl_frame());
335   client.Reset();
336
337   // Since another commit is needed, the next BeginImplFrame should initiate
338   // the second commit.
339   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
340   if (deadline_scheduling_enabled) {
341     EXPECT_EQ(client.num_actions_(), 2);
342     EXPECT_TRUE(client.HasAction("ScheduledActionSendBeginMainFrame"));
343     EXPECT_TRUE(client.HasAction("PostBeginImplFrameDeadlineTask"));
344   } else {
345     EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
346   }
347   client.Reset();
348
349   // Finishing the commit before the deadline should post a new deadline task
350   // to trigger the deadline early.
351   scheduler->FinishCommit();
352   EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
353   EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
354   client.Reset();
355   scheduler->OnBeginImplFrameDeadline();
356   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
357   EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
358   EXPECT_TRUE(client.needs_begin_impl_frame());
359   client.Reset();
360
361   // On the next BeginImplFrame, verify we go back to a quiescent state and
362   // no longer request BeginImplFrames.
363   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
364   scheduler->OnBeginImplFrameDeadline();
365   EXPECT_FALSE(client.needs_begin_impl_frame());
366   client.Reset();
367 }
368
369 TEST(SchedulerTest, RequestCommitAfterBeginMainFrameSent) {
370   bool deadline_scheduling_enabled = false;
371   RequestCommitAfterBeginMainFrameSent(deadline_scheduling_enabled);
372 }
373
374 TEST(SchedulerTest, RequestCommitAfterBeginMainFrameSent_Deadline) {
375   bool deadline_scheduling_enabled = true;
376   RequestCommitAfterBeginMainFrameSent(deadline_scheduling_enabled);
377 }
378
379 void TextureAcquisitionCausesCommitInsteadOfDraw(
380     bool deadline_scheduling_enabled) {
381   FakeSchedulerClient client;
382   SchedulerSettings scheduler_settings;
383   scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
384   Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
385   scheduler->SetCanStart();
386   scheduler->SetVisible(true);
387   scheduler->SetCanDraw(true);
388   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
389
390   InitializeOutputSurfaceAndFirstCommit(scheduler);
391   client.Reset();
392   scheduler->SetNeedsRedraw();
393   EXPECT_TRUE(scheduler->RedrawPending());
394   EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
395   EXPECT_TRUE(client.needs_begin_impl_frame());
396
397   client.Reset();
398   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
399   EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
400   client.Reset();
401   scheduler->OnBeginImplFrameDeadline();
402   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
403   EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
404   EXPECT_FALSE(scheduler->RedrawPending());
405   EXPECT_TRUE(client.needs_begin_impl_frame());
406
407   client.Reset();
408   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
409   EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
410   client.Reset();
411   scheduler->OnBeginImplFrameDeadline();
412   EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
413   EXPECT_FALSE(scheduler->RedrawPending());
414   EXPECT_FALSE(client.needs_begin_impl_frame());
415
416   client.Reset();
417   scheduler->SetMainThreadNeedsLayerTextures();
418   EXPECT_SINGLE_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
419                        client);
420
421   // We should request a BeginImplFrame in anticipation of a draw.
422   client.Reset();
423   scheduler->SetNeedsRedraw();
424   EXPECT_TRUE(scheduler->RedrawPending());
425   EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
426   EXPECT_TRUE(client.needs_begin_impl_frame());
427
428   // No draw happens since the textures are acquired by the main thread.
429   client.Reset();
430   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
431   EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
432   client.Reset();
433   scheduler->OnBeginImplFrameDeadline();
434   EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
435   EXPECT_TRUE(scheduler->RedrawPending());
436   EXPECT_TRUE(client.needs_begin_impl_frame());
437
438   client.Reset();
439   scheduler->SetNeedsCommit();
440   if (deadline_scheduling_enabled) {
441     EXPECT_EQ(0, client.num_actions_());
442   } else {
443     EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client);
444   }
445
446   client.Reset();
447   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
448   if (deadline_scheduling_enabled) {
449     EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
450     EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
451   } else {
452     EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
453   }
454
455   // Commit will release the texture.
456   client.Reset();
457   scheduler->FinishCommit();
458   EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
459   EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
460   EXPECT_TRUE(scheduler->RedrawPending());
461
462   // Now we can draw again after the commit happens.
463   client.Reset();
464   scheduler->OnBeginImplFrameDeadline();
465   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
466   EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
467   EXPECT_FALSE(scheduler->RedrawPending());
468   EXPECT_TRUE(client.needs_begin_impl_frame());
469
470   // Make sure we stop requesting BeginImplFrames if we don't swap.
471   client.Reset();
472   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
473   EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
474   client.Reset();
475   scheduler->OnBeginImplFrameDeadline();
476   EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
477   EXPECT_FALSE(client.needs_begin_impl_frame());
478 }
479
480 TEST(SchedulerTest, TextureAcquisitionCausesCommitInsteadOfDraw) {
481   bool deadline_scheduling_enabled = false;
482   TextureAcquisitionCausesCommitInsteadOfDraw(deadline_scheduling_enabled);
483 }
484
485 TEST(SchedulerTest, TextureAcquisitionCausesCommitInsteadOfDraw_Deadline) {
486   bool deadline_scheduling_enabled = true;
487   TextureAcquisitionCausesCommitInsteadOfDraw(deadline_scheduling_enabled);
488 }
489
490 void TextureAcquisitionCollision(bool deadline_scheduling_enabled) {
491   FakeSchedulerClient client;
492   SchedulerSettings scheduler_settings;
493   scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
494   Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
495   scheduler->SetCanStart();
496   scheduler->SetVisible(true);
497   scheduler->SetCanDraw(true);
498
499   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
500   InitializeOutputSurfaceAndFirstCommit(scheduler);
501
502   client.Reset();
503   scheduler->SetNeedsCommit();
504 if (deadline_scheduling_enabled) {
505     EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
506   } else {
507     EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
508     EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
509   }
510
511   client.Reset();
512   scheduler->SetMainThreadNeedsLayerTextures();
513   EXPECT_SINGLE_ACTION(
514       "ScheduledActionAcquireLayerTexturesForMainThread", client);
515
516   client.Reset();
517   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
518   if (deadline_scheduling_enabled) {
519     EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
520     EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
521   } else {
522     EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
523   }
524
525   client.Reset();
526   scheduler->OnBeginImplFrameDeadline();
527   EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
528
529   // Although the compositor cannot draw because textures are locked by main
530   // thread, we continue requesting SetNeedsBeginImplFrame in anticipation of
531   // the unlock.
532   EXPECT_TRUE(client.needs_begin_impl_frame());
533
534   // Trigger the commit
535   scheduler->FinishCommit();
536   EXPECT_TRUE(client.needs_begin_impl_frame());
537
538   // Between commit and draw, texture acquisition for main thread delayed,
539   // and main thread blocks.
540   client.Reset();
541   scheduler->SetMainThreadNeedsLayerTextures();
542   EXPECT_EQ(0, client.num_actions_());
543
544   // No implicit commit is expected.
545   client.Reset();
546   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
547   EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
548
549   client.Reset();
550   scheduler->OnBeginImplFrameDeadline();
551   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 3);
552   EXPECT_ACTION(
553       "ScheduledActionAcquireLayerTexturesForMainThread", client, 1, 3);
554   EXPECT_ACTION("SetNeedsBeginImplFrame", client, 2, 3);
555   EXPECT_TRUE(client.needs_begin_impl_frame());
556
557   // The compositor should not draw because textures are locked by main
558   // thread.
559   client.Reset();
560   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
561   EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
562   client.Reset();
563   scheduler->OnBeginImplFrameDeadline();
564   EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
565   EXPECT_FALSE(client.needs_begin_impl_frame());
566
567   // The impl thread need an explicit commit from the main thread to lock
568   // the textures.
569   client.Reset();
570   scheduler->SetNeedsCommit();
571   if (deadline_scheduling_enabled) {
572     EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);
573   } else {
574     EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
575     EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
576   }
577   EXPECT_TRUE(client.needs_begin_impl_frame());
578
579   client.Reset();
580   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
581   if (deadline_scheduling_enabled) {
582     EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
583     EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
584   } else {
585     EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
586   }
587   client.Reset();
588
589   // Trigger the commit, which will trigger the deadline task early.
590   scheduler->FinishCommit();
591   EXPECT_ACTION("ScheduledActionCommit", client, 0, 2);
592   EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
593   EXPECT_TRUE(client.needs_begin_impl_frame());
594   client.Reset();
595
596   // Verify we draw on the next BeginImplFrame deadline
597   scheduler->OnBeginImplFrameDeadline();
598   EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
599   EXPECT_ACTION("SetNeedsBeginImplFrame", client, 1, 2);
600   EXPECT_TRUE(client.needs_begin_impl_frame());
601   client.Reset();
602 }
603
604 TEST(SchedulerTest, TextureAcquisitionCollision) {
605   bool deadline_scheduling_enabled = false;
606   TextureAcquisitionCollision(deadline_scheduling_enabled);
607 }
608
609 TEST(SchedulerTest, TextureAcquisitionCollision_Deadline) {
610   bool deadline_scheduling_enabled = true;
611   TextureAcquisitionCollision(deadline_scheduling_enabled);
612 }
613
614 void VisibilitySwitchWithTextureAcquisition(bool deadline_scheduling_enabled) {
615   FakeSchedulerClient client;
616   SchedulerSettings scheduler_settings;
617   scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
618   Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
619   scheduler->SetCanStart();
620   scheduler->SetVisible(true);
621   scheduler->SetCanDraw(true);
622
623   EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
624   client.Reset();
625   scheduler->DidCreateAndInitializeOutputSurface();
626
627   scheduler->SetNeedsCommit();
628   if (deadline_scheduling_enabled) {
629     scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
630     scheduler->OnBeginImplFrameDeadline();
631   }
632   scheduler->FinishCommit();
633   scheduler->SetMainThreadNeedsLayerTextures();
634   scheduler->SetNeedsCommit();
635   client.Reset();
636   // Verify that pending texture acquisition fires when visibility
637   // is lost in order to avoid a deadlock.
638   scheduler->SetVisible(false);
639   EXPECT_SINGLE_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
640                        client);
641
642   client.Reset();
643   scheduler->SetVisible(true);
644   EXPECT_EQ(0, client.num_actions_());
645   EXPECT_TRUE(client.needs_begin_impl_frame());
646
647   // Regaining visibility with textures acquired by main thread while
648   // compositor is waiting for first draw should result in a request
649   // for a new frame in order to escape a deadlock.
650   client.Reset();
651   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
652   EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 2);
653   EXPECT_ACTION("PostBeginImplFrameDeadlineTask", client, 1, 2);
654 }
655
656 TEST(SchedulerTest, VisibilitySwitchWithTextureAcquisition) {
657   bool deadline_scheduling_enabled = false;
658   VisibilitySwitchWithTextureAcquisition(deadline_scheduling_enabled);
659 }
660
661 TEST(SchedulerTest, VisibilitySwitchWithTextureAcquisition_Deadline) {
662   bool deadline_scheduling_enabled = true;
663   VisibilitySwitchWithTextureAcquisition(deadline_scheduling_enabled);
664 }
665
666 class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
667  public:
668   virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
669   virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
670       OVERRIDE {
671     // Only SetNeedsRedraw the first time this is called
672     if (!num_draws_)
673       scheduler_->SetNeedsRedraw();
674     return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
675   }
676
677   virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
678     NOTREACHED();
679     bool did_draw = true;
680     bool did_swap = true;
681     bool did_readback = false;
682     return DrawSwapReadbackResult(did_draw, did_swap, did_readback);
683   }
684
685   virtual void ScheduledActionCommit() OVERRIDE {}
686   virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {}
687   virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
688 };
689
690 // Tests for two different situations:
691 // 1. the scheduler dropping SetNeedsRedraw requests that happen inside
692 //    a ScheduledActionDrawAndSwap
693 // 2. the scheduler drawing twice inside a single tick
694 TEST(SchedulerTest, RequestRedrawInsideDraw) {
695   SchedulerClientThatsetNeedsDrawInsideDraw client;
696   SchedulerSettings default_scheduler_settings;
697   Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
698   scheduler->SetCanStart();
699   scheduler->SetVisible(true);
700   scheduler->SetCanDraw(true);
701   InitializeOutputSurfaceAndFirstCommit(scheduler);
702   client.Reset();
703
704   scheduler->SetNeedsRedraw();
705   EXPECT_TRUE(scheduler->RedrawPending());
706   EXPECT_TRUE(client.needs_begin_impl_frame());
707   EXPECT_EQ(0, client.num_draws());
708
709   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
710   scheduler->OnBeginImplFrameDeadline();
711   EXPECT_EQ(1, client.num_draws());
712   EXPECT_TRUE(scheduler->RedrawPending());
713   EXPECT_TRUE(client.needs_begin_impl_frame());
714
715   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
716   scheduler->OnBeginImplFrameDeadline();
717   EXPECT_EQ(2, client.num_draws());
718   EXPECT_FALSE(scheduler->RedrawPending());
719   EXPECT_TRUE(client.needs_begin_impl_frame());
720
721   // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
722   // swap.
723   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
724   scheduler->OnBeginImplFrameDeadline();
725   EXPECT_EQ(2, client.num_draws());
726   EXPECT_FALSE(scheduler->RedrawPending());
727   EXPECT_FALSE(client.needs_begin_impl_frame());
728 }
729
730 // Test that requesting redraw inside a failed draw doesn't lose the request.
731 TEST(SchedulerTest, RequestRedrawInsideFailedDraw) {
732   SchedulerClientThatsetNeedsDrawInsideDraw client;
733   SchedulerSettings default_scheduler_settings;
734   Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
735   scheduler->SetCanStart();
736   scheduler->SetVisible(true);
737   scheduler->SetCanDraw(true);
738   InitializeOutputSurfaceAndFirstCommit(scheduler);
739   client.Reset();
740
741   client.SetDrawWillHappen(false);
742
743   scheduler->SetNeedsRedraw();
744   EXPECT_TRUE(scheduler->RedrawPending());
745   EXPECT_TRUE(client.needs_begin_impl_frame());
746   EXPECT_EQ(0, client.num_draws());
747
748   // Fail the draw.
749   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
750   scheduler->OnBeginImplFrameDeadline();
751   EXPECT_EQ(1, client.num_draws());
752
753   // We have a commit pending and the draw failed, and we didn't lose the redraw
754   // request.
755   EXPECT_TRUE(scheduler->CommitPending());
756   EXPECT_TRUE(scheduler->RedrawPending());
757   EXPECT_TRUE(client.needs_begin_impl_frame());
758
759   // Fail the draw again.
760   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
761   scheduler->OnBeginImplFrameDeadline();
762   EXPECT_EQ(2, client.num_draws());
763   EXPECT_TRUE(scheduler->CommitPending());
764   EXPECT_TRUE(scheduler->RedrawPending());
765   EXPECT_TRUE(client.needs_begin_impl_frame());
766
767   // Draw successfully.
768   client.SetDrawWillHappen(true);
769   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
770   scheduler->OnBeginImplFrameDeadline();
771   EXPECT_EQ(3, client.num_draws());
772   EXPECT_TRUE(scheduler->CommitPending());
773   EXPECT_FALSE(scheduler->RedrawPending());
774   EXPECT_TRUE(client.needs_begin_impl_frame());
775 }
776
777 class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
778  public:
779   SchedulerClientThatSetNeedsCommitInsideDraw()
780       : set_needs_commit_on_next_draw_(false) {}
781
782   virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {}
783   virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
784       OVERRIDE {
785     // Only SetNeedsCommit the first time this is called
786     if (set_needs_commit_on_next_draw_) {
787       scheduler_->SetNeedsCommit();
788       set_needs_commit_on_next_draw_ = false;
789     }
790     return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
791   }
792
793   virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
794     NOTREACHED();
795     bool did_draw = true;
796     bool did_swap = false;
797     bool did_readback = false;
798     return DrawSwapReadbackResult(did_draw, did_swap, did_readback);
799   }
800
801   virtual void ScheduledActionCommit() OVERRIDE {}
802   virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {}
803   virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
804
805   void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; }
806
807  private:
808   bool set_needs_commit_on_next_draw_;
809 };
810
811 // Tests for the scheduler infinite-looping on SetNeedsCommit requests that
812 // happen inside a ScheduledActionDrawAndSwap
813 TEST(SchedulerTest, RequestCommitInsideDraw) {
814   SchedulerClientThatSetNeedsCommitInsideDraw client;
815   SchedulerSettings default_scheduler_settings;
816   Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
817   scheduler->SetCanStart();
818   scheduler->SetVisible(true);
819   scheduler->SetCanDraw(true);
820   InitializeOutputSurfaceAndFirstCommit(scheduler);
821   client.Reset();
822
823   EXPECT_FALSE(client.needs_begin_impl_frame());
824   scheduler->SetNeedsRedraw();
825   EXPECT_TRUE(scheduler->RedrawPending());
826   EXPECT_EQ(0, client.num_draws());
827   EXPECT_TRUE(client.needs_begin_impl_frame());
828
829   client.SetNeedsCommitOnNextDraw();
830   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
831   client.SetNeedsCommitOnNextDraw();
832   scheduler->OnBeginImplFrameDeadline();
833   EXPECT_EQ(1, client.num_draws());
834   EXPECT_TRUE(scheduler->CommitPending());
835   EXPECT_TRUE(client.needs_begin_impl_frame());
836   scheduler->FinishCommit();
837
838   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
839   scheduler->OnBeginImplFrameDeadline();
840   EXPECT_EQ(2, client.num_draws());
841
842   EXPECT_FALSE(scheduler->RedrawPending());
843   EXPECT_FALSE(scheduler->CommitPending());
844   EXPECT_TRUE(client.needs_begin_impl_frame());
845
846   // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
847   // swap.
848   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
849   scheduler->OnBeginImplFrameDeadline();
850   EXPECT_EQ(2, client.num_draws());
851   EXPECT_FALSE(scheduler->RedrawPending());
852   EXPECT_FALSE(scheduler->CommitPending());
853   EXPECT_FALSE(client.needs_begin_impl_frame());
854 }
855
856 // Tests that when a draw fails then the pending commit should not be dropped.
857 TEST(SchedulerTest, RequestCommitInsideFailedDraw) {
858   SchedulerClientThatsetNeedsDrawInsideDraw client;
859   SchedulerSettings default_scheduler_settings;
860   Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
861   scheduler->SetCanStart();
862   scheduler->SetVisible(true);
863   scheduler->SetCanDraw(true);
864   InitializeOutputSurfaceAndFirstCommit(scheduler);
865   client.Reset();
866
867   client.SetDrawWillHappen(false);
868
869   scheduler->SetNeedsRedraw();
870   EXPECT_TRUE(scheduler->RedrawPending());
871   EXPECT_TRUE(client.needs_begin_impl_frame());
872   EXPECT_EQ(0, client.num_draws());
873
874   // Fail the draw.
875   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
876   scheduler->OnBeginImplFrameDeadline();
877   EXPECT_EQ(1, client.num_draws());
878
879   // We have a commit pending and the draw failed, and we didn't lose the commit
880   // request.
881   EXPECT_TRUE(scheduler->CommitPending());
882   EXPECT_TRUE(scheduler->RedrawPending());
883   EXPECT_TRUE(client.needs_begin_impl_frame());
884
885   // Fail the draw again.
886   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
887   scheduler->OnBeginImplFrameDeadline();
888   EXPECT_EQ(2, client.num_draws());
889   EXPECT_TRUE(scheduler->CommitPending());
890   EXPECT_TRUE(scheduler->RedrawPending());
891   EXPECT_TRUE(client.needs_begin_impl_frame());
892
893   // Draw successfully.
894   client.SetDrawWillHappen(true);
895   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
896   scheduler->OnBeginImplFrameDeadline();
897   EXPECT_EQ(3, client.num_draws());
898   EXPECT_TRUE(scheduler->CommitPending());
899   EXPECT_FALSE(scheduler->RedrawPending());
900   EXPECT_TRUE(client.needs_begin_impl_frame());
901 }
902
903 TEST(SchedulerTest, NoSwapWhenDrawFails) {
904   SchedulerClientThatSetNeedsCommitInsideDraw client;
905   SchedulerSettings default_scheduler_settings;
906   Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
907   scheduler->SetCanStart();
908   scheduler->SetVisible(true);
909   scheduler->SetCanDraw(true);
910   InitializeOutputSurfaceAndFirstCommit(scheduler);
911   client.Reset();
912
913   scheduler->SetNeedsRedraw();
914   EXPECT_TRUE(scheduler->RedrawPending());
915   EXPECT_TRUE(client.needs_begin_impl_frame());
916   EXPECT_EQ(0, client.num_draws());
917
918   // Draw successfully, this starts a new frame.
919   client.SetNeedsCommitOnNextDraw();
920   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
921   scheduler->OnBeginImplFrameDeadline();
922   EXPECT_EQ(1, client.num_draws());
923
924   scheduler->SetNeedsRedraw();
925   EXPECT_TRUE(scheduler->RedrawPending());
926   EXPECT_TRUE(client.needs_begin_impl_frame());
927
928   // Fail to draw, this should not start a frame.
929   client.SetDrawWillHappen(false);
930   client.SetNeedsCommitOnNextDraw();
931   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
932   scheduler->OnBeginImplFrameDeadline();
933   EXPECT_EQ(2, client.num_draws());
934 }
935
936 TEST(SchedulerTest, NoSwapWhenSwapFailsDuringForcedCommit) {
937   FakeSchedulerClient client;
938   SchedulerSettings default_scheduler_settings;
939   Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
940
941   // Tell the client that it will fail to swap.
942   client.SetDrawWillHappen(true);
943   client.SetSwapWillHappenIfDrawHappens(false);
944
945   // Get the compositor to do a ScheduledActionDrawAndReadback.
946   scheduler->SetCanDraw(true);
947   scheduler->SetNeedsRedraw();
948   scheduler->SetNeedsForcedCommitForReadback();
949   scheduler->FinishCommit();
950   EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndReadback"));
951 }
952
953 TEST(SchedulerTest, BackToBackReadbackAllowed) {
954   // Some clients call readbacks twice in a row before the replacement
955   // commit comes in.  Make sure it is allowed.
956   FakeSchedulerClient client;
957   SchedulerSettings default_scheduler_settings;
958   Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
959
960   // Get the compositor to do 2 ScheduledActionDrawAndReadbacks before
961   // the replacement commit comes in.
962   scheduler->SetCanDraw(true);
963   scheduler->SetNeedsRedraw();
964   scheduler->SetNeedsForcedCommitForReadback();
965   scheduler->FinishCommit();
966   EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndReadback"));
967
968   client.Reset();
969   scheduler->SetNeedsForcedCommitForReadback();
970   scheduler->FinishCommit();
971   EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndReadback"));
972
973   // The replacement commit comes in after 2 readbacks.
974   client.Reset();
975   scheduler->FinishCommit();
976 }
977
978
979 class SchedulerClientNeedsManageTilesInDraw : public FakeSchedulerClient {
980  public:
981   virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible()
982       OVERRIDE {
983     scheduler_->SetNeedsManageTiles();
984     return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible();
985   }
986 };
987
988 // Test manage tiles is independant of draws.
989 TEST(SchedulerTest, ManageTiles) {
990   SchedulerClientNeedsManageTilesInDraw client;
991   SchedulerSettings default_scheduler_settings;
992   Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
993   scheduler->SetCanStart();
994   scheduler->SetVisible(true);
995   scheduler->SetCanDraw(true);
996   InitializeOutputSurfaceAndFirstCommit(scheduler);
997
998   // Request both draw and manage tiles. ManageTiles shouldn't
999   // be trigged until BeginImplFrame.
1000   client.Reset();
1001   scheduler->SetNeedsManageTiles();
1002   scheduler->SetNeedsRedraw();
1003   EXPECT_TRUE(scheduler->RedrawPending());
1004   EXPECT_TRUE(scheduler->ManageTilesPending());
1005   EXPECT_TRUE(client.needs_begin_impl_frame());
1006   EXPECT_EQ(0, client.num_draws());
1007   EXPECT_FALSE(client.HasAction("ScheduledActionManageTiles"));
1008   EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1009
1010   // We have no immediate actions to perform, so the BeginImplFrame should post
1011   // the deadline task.
1012   client.Reset();
1013   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1014   EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
1015
1016   // On the deadline, he actions should have occured in the right order.
1017   client.Reset();
1018   scheduler->OnBeginImplFrameDeadline();
1019   EXPECT_EQ(1, client.num_draws());
1020   EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1021   EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
1022   EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1023             client.ActionIndex("ScheduledActionManageTiles"));
1024   EXPECT_FALSE(scheduler->RedrawPending());
1025   EXPECT_FALSE(scheduler->ManageTilesPending());
1026
1027   // Request a draw. We don't need a ManageTiles yet.
1028   client.Reset();
1029   scheduler->SetNeedsRedraw();
1030   EXPECT_TRUE(scheduler->RedrawPending());
1031   EXPECT_FALSE(scheduler->ManageTilesPending());
1032   EXPECT_TRUE(client.needs_begin_impl_frame());
1033   EXPECT_EQ(0, client.num_draws());
1034
1035   // We have no immediate actions to perform, so the BeginImplFrame should post
1036   // the deadline task.
1037   client.Reset();
1038   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1039   EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
1040
1041   // Draw. The draw will trigger SetNeedsManageTiles, and
1042   // then the ManageTiles action will be triggered after the Draw.
1043   // Afterwards, neither a draw nor ManageTiles are pending.
1044   client.Reset();
1045   scheduler->OnBeginImplFrameDeadline();
1046   EXPECT_EQ(1, client.num_draws());
1047   EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1048   EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
1049   EXPECT_LT(client.ActionIndex("ScheduledActionDrawAndSwapIfPossible"),
1050             client.ActionIndex("ScheduledActionManageTiles"));
1051   EXPECT_FALSE(scheduler->RedrawPending());
1052   EXPECT_FALSE(scheduler->ManageTilesPending());
1053
1054   // We need a BeginImplFrame where we don't swap to go idle.
1055   client.Reset();
1056   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1057   EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
1058   client.Reset();
1059   scheduler->OnBeginImplFrameDeadline();
1060   EXPECT_SINGLE_ACTION("SetNeedsBeginImplFrame", client);;
1061   EXPECT_EQ(0, client.num_draws());
1062
1063   // Now trigger a ManageTiles outside of a draw. We will then need
1064   // a begin-frame for the ManageTiles, but we don't need a draw.
1065   client.Reset();
1066   EXPECT_FALSE(client.needs_begin_impl_frame());
1067   scheduler->SetNeedsManageTiles();
1068   EXPECT_TRUE(client.needs_begin_impl_frame());
1069   EXPECT_TRUE(scheduler->ManageTilesPending());
1070   EXPECT_FALSE(scheduler->RedrawPending());
1071
1072   // BeginImplFrame. There will be no draw, only ManageTiles.
1073   client.Reset();
1074   scheduler->BeginImplFrame(BeginFrameArgs::CreateForTesting());
1075   EXPECT_SINGLE_ACTION("PostBeginImplFrameDeadlineTask", client);
1076   client.Reset();
1077   scheduler->OnBeginImplFrameDeadline();
1078   EXPECT_EQ(0, client.num_draws());
1079   EXPECT_FALSE(client.HasAction("ScheduledActionDrawAndSwapIfPossible"));
1080   EXPECT_TRUE(client.HasAction("ScheduledActionManageTiles"));
1081 }
1082
1083 }  // namespace
1084 }  // namespace cc