• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "cc/scheduler/scheduler_state_machine.h"
6 
7 #include "base/debug/trace_event.h"
8 #include "cc/scheduler/scheduler.h"
9 #include "cc/test/begin_frame_args_test.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 
12 #define EXPECT_ACTION_UPDATE_STATE(action)                                   \
13   EXPECT_EQ(action, state.NextAction()) << state.AsValue()->ToString();      \
14   if (action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE ||   \
15       action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED) {        \
16     EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, \
17               state.begin_impl_frame_state())                                \
18         << state.AsValue()->ToString();                                      \
19   }                                                                          \
20   state.UpdateState(action);                                                 \
21   if (action == SchedulerStateMachine::ACTION_NONE) {                        \
22     if (state.begin_impl_frame_state() ==                                    \
23         SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING)  \
24       state.OnBeginImplFrameDeadlinePending();                               \
25     if (state.begin_impl_frame_state() ==                                    \
26         SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)       \
27       state.OnBeginImplFrameIdle();                                          \
28   }
29 
30 namespace cc {
31 
32 namespace {
33 
34 const SchedulerStateMachine::BeginImplFrameState all_begin_impl_frame_states[] =
35     {SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE,
36      SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
37      SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
38      SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, };
39 
40 const SchedulerStateMachine::CommitState all_commit_states[] = {
41     SchedulerStateMachine::COMMIT_STATE_IDLE,
42     SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
43     SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED,
44     SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
45     SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_ACTIVATION,
46     SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW};
47 
48 // Exposes the protected state fields of the SchedulerStateMachine for testing
49 class StateMachine : public SchedulerStateMachine {
50  public:
StateMachine(const SchedulerSettings & scheduler_settings)51   explicit StateMachine(const SchedulerSettings& scheduler_settings)
52       : SchedulerStateMachine(scheduler_settings) {}
53 
CreateAndInitializeOutputSurfaceWithActivatedCommit()54   void CreateAndInitializeOutputSurfaceWithActivatedCommit() {
55     DidCreateAndInitializeOutputSurface();
56     output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
57   }
58 
SetCommitState(CommitState cs)59   void SetCommitState(CommitState cs) { commit_state_ = cs; }
CommitState() const60   CommitState CommitState() const { return commit_state_; }
61 
ForcedRedrawState() const62   ForcedRedrawOnTimeoutState ForcedRedrawState() const {
63     return forced_redraw_state_;
64   }
65 
SetBeginImplFrameState(BeginImplFrameState bifs)66   void SetBeginImplFrameState(BeginImplFrameState bifs) {
67     begin_impl_frame_state_ = bifs;
68   }
69 
begin_impl_frame_state() const70   BeginImplFrameState begin_impl_frame_state() const {
71     return begin_impl_frame_state_;
72   }
73 
output_surface_state() const74   OutputSurfaceState output_surface_state() const {
75     return output_surface_state_;
76   }
77 
NeedsCommit() const78   bool NeedsCommit() const { return needs_commit_; }
79 
SetNeedsRedraw(bool b)80   void SetNeedsRedraw(bool b) { needs_redraw_ = b; }
81 
SetNeedsForcedRedrawForTimeout(bool b)82   void SetNeedsForcedRedrawForTimeout(bool b) {
83     forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT;
84     active_tree_needs_first_draw_ = true;
85   }
NeedsForcedRedrawForTimeout() const86   bool NeedsForcedRedrawForTimeout() const {
87     return forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE;
88   }
89 
SetActiveTreeNeedsFirstDraw(bool needs_first_draw)90   void SetActiveTreeNeedsFirstDraw(bool needs_first_draw) {
91     active_tree_needs_first_draw_ = needs_first_draw;
92   }
93 
CanDraw() const94   bool CanDraw() const { return can_draw_; }
Visible() const95   bool Visible() const { return visible_; }
96 
PendingActivationsShouldBeForced() const97   bool PendingActivationsShouldBeForced() const {
98     return SchedulerStateMachine::PendingActivationsShouldBeForced();
99   }
100 
SetHasPendingTree(bool has_pending_tree)101   void SetHasPendingTree(bool has_pending_tree) {
102     has_pending_tree_ = has_pending_tree;
103   }
104 };
105 
TEST(SchedulerStateMachineTest,TestNextActionBeginsMainFrameIfNeeded)106 TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) {
107   SchedulerSettings default_scheduler_settings;
108 
109   // If no commit needed, do nothing.
110   {
111     StateMachine state(default_scheduler_settings);
112     state.SetCanStart();
113     EXPECT_ACTION_UPDATE_STATE(
114         SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION)
115     state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
116     state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
117     state.SetNeedsRedraw(false);
118     state.SetVisible(true);
119 
120     EXPECT_FALSE(state.BeginFrameNeeded());
121 
122     EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
123     EXPECT_FALSE(state.BeginFrameNeeded());
124     state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
125 
126     EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
127     state.OnBeginImplFrameDeadline();
128   }
129 
130   // If commit requested but can_start is still false, do nothing.
131   {
132     StateMachine state(default_scheduler_settings);
133     state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
134     state.SetNeedsRedraw(false);
135     state.SetVisible(true);
136     state.SetNeedsCommit();
137 
138     EXPECT_FALSE(state.BeginFrameNeeded());
139 
140     EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
141     EXPECT_FALSE(state.BeginFrameNeeded());
142     state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
143     EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
144     state.OnBeginImplFrameDeadline();
145   }
146 
147   // If commit requested, begin a main frame.
148   {
149     StateMachine state(default_scheduler_settings);
150     state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
151     state.SetCanStart();
152     state.UpdateState(state.NextAction());
153     state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
154     state.SetNeedsRedraw(false);
155     state.SetVisible(true);
156     state.SetNeedsCommit();
157 
158     EXPECT_TRUE(state.BeginFrameNeeded());
159 
160     state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
161     EXPECT_ACTION_UPDATE_STATE(
162         SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
163   }
164 
165   // Begin the frame, make sure needs_commit and commit_state update correctly.
166   {
167     StateMachine state(default_scheduler_settings);
168     state.SetCanStart();
169     state.UpdateState(state.NextAction());
170     state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
171     state.SetVisible(true);
172     state.UpdateState(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
173     EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
174               state.CommitState());
175     EXPECT_FALSE(state.NeedsCommit());
176   }
177 }
178 
179 // Explicitly test main_frame_before_draw_enabled = false
TEST(SchedulerStateMachineTest,MainFrameBeforeDrawDisabled)180 TEST(SchedulerStateMachineTest, MainFrameBeforeDrawDisabled) {
181   SchedulerSettings scheduler_settings;
182   scheduler_settings.impl_side_painting = true;
183   scheduler_settings.main_frame_before_draw_enabled = false;
184   StateMachine state(scheduler_settings);
185   state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
186   state.SetCanStart();
187   state.UpdateState(state.NextAction());
188   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
189   state.SetNeedsRedraw(false);
190   state.SetVisible(true);
191   state.SetCanDraw(true);
192   state.SetNeedsCommit();
193 
194   EXPECT_TRUE(state.BeginFrameNeeded());
195 
196   // Commit to the pending tree.
197   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
198   EXPECT_ACTION_UPDATE_STATE(
199       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
200   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
201   state.NotifyBeginMainFrameStarted();
202   state.NotifyReadyToCommit();
203   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
204   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
205   EXPECT_EQ(state.CommitState(),
206             SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
207 
208   state.OnBeginImplFrameDeadline();
209   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
210   EXPECT_EQ(state.CommitState(),
211             SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
212 
213   // Verify that the next commit doesn't start until the previous
214   // commit has been drawn.
215   state.SetNeedsCommit();
216   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
217   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
218 
219   // Make sure that a draw of the active tree doesn't spuriously advance
220   // the commit state and unblock the next commit.
221   state.SetNeedsRedraw(true);
222   state.OnBeginImplFrameDeadline();
223   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
224   EXPECT_ACTION_UPDATE_STATE(
225       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
226   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
227   EXPECT_EQ(state.CommitState(),
228             SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
229   EXPECT_TRUE(state.has_pending_tree());
230 
231   // Verify NotifyReadyToActivate unblocks activation, draw, and
232   // commit in that order.
233   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
234 
235   state.NotifyReadyToActivate();
236   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE);
237   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
238   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
239   EXPECT_EQ(state.CommitState(),
240             SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
241 
242   EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly());
243   state.OnBeginImplFrameDeadline();
244   EXPECT_ACTION_UPDATE_STATE(
245       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
246   state.DidSwapBuffers();
247   state.DidSwapBuffersComplete();
248   EXPECT_EQ(state.CommitState(), SchedulerStateMachine::COMMIT_STATE_IDLE);
249   EXPECT_ACTION_UPDATE_STATE(
250       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
251   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
252   EXPECT_EQ(state.CommitState(),
253             SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
254 
255   state.NotifyBeginMainFrameStarted();
256   state.NotifyReadyToCommit();
257   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
258   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
259   EXPECT_EQ(state.CommitState(),
260             SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
261 }
262 
263 // Explicitly test main_frame_before_activation_enabled = true
TEST(SchedulerStateMachineTest,MainFrameBeforeActivationEnabled)264 TEST(SchedulerStateMachineTest, MainFrameBeforeActivationEnabled) {
265   SchedulerSettings scheduler_settings;
266   scheduler_settings.impl_side_painting = true;
267   scheduler_settings.main_frame_before_activation_enabled = true;
268   StateMachine state(scheduler_settings);
269   state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
270   state.SetCanStart();
271   state.UpdateState(state.NextAction());
272   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
273   state.SetNeedsRedraw(false);
274   state.SetVisible(true);
275   state.SetCanDraw(true);
276   state.SetNeedsCommit();
277 
278   EXPECT_TRUE(state.BeginFrameNeeded());
279 
280   // Commit to the pending tree.
281   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
282   EXPECT_ACTION_UPDATE_STATE(
283       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
284   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
285 
286   state.NotifyBeginMainFrameStarted();
287   state.NotifyReadyToCommit();
288   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
289   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
290   EXPECT_EQ(state.CommitState(), SchedulerStateMachine::COMMIT_STATE_IDLE);
291 
292   state.OnBeginImplFrameDeadline();
293   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
294 
295   // Verify that the next commit starts while there is still a pending tree.
296   state.SetNeedsCommit();
297   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
298   EXPECT_ACTION_UPDATE_STATE(
299       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
300   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
301 
302   // Verify the pending commit doesn't overwrite the pending
303   // tree until the pending tree has been activated.
304   state.NotifyBeginMainFrameStarted();
305   state.NotifyReadyToCommit();
306   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
307 
308   // Verify NotifyReadyToActivate unblocks activation, draw, and
309   // commit in that order.
310   state.NotifyReadyToActivate();
311   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE);
312   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
313 
314   EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly());
315   state.OnBeginImplFrameDeadline();
316   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
317   EXPECT_ACTION_UPDATE_STATE(
318       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
319   state.DidSwapBuffers();
320   state.DidSwapBuffersComplete();
321   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
322   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
323   EXPECT_EQ(state.CommitState(), SchedulerStateMachine::COMMIT_STATE_IDLE);
324 }
325 
TEST(SchedulerStateMachineTest,TestFailedDrawForAnimationCheckerboardSetsNeedsCommitAndDoesNotDrawAgain)326 TEST(SchedulerStateMachineTest,
327      TestFailedDrawForAnimationCheckerboardSetsNeedsCommitAndDoesNotDrawAgain) {
328   SchedulerSettings default_scheduler_settings;
329   StateMachine state(default_scheduler_settings);
330   state.SetCanStart();
331   state.UpdateState(state.NextAction());
332   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
333   state.SetVisible(true);
334   state.SetCanDraw(true);
335   state.SetNeedsRedraw(true);
336   EXPECT_TRUE(state.RedrawPending());
337   EXPECT_TRUE(state.BeginFrameNeeded());
338   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
339   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
340   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
341   state.OnBeginImplFrameDeadline();
342 
343   // We're drawing now.
344   EXPECT_ACTION_UPDATE_STATE(
345       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
346   state.DidSwapBuffers();
347   state.DidSwapBuffersComplete();
348   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
349 
350   EXPECT_FALSE(state.RedrawPending());
351   EXPECT_FALSE(state.CommitPending());
352 
353   // Failing the draw makes us require a commit.
354   state.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
355   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
356   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
357   EXPECT_ACTION_UPDATE_STATE(
358       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
359   EXPECT_TRUE(state.RedrawPending());
360   EXPECT_TRUE(state.CommitPending());
361 }
362 
TEST(SchedulerStateMachineTest,TestFailedDrawForMissingHighResNeedsCommit)363 TEST(SchedulerStateMachineTest, TestFailedDrawForMissingHighResNeedsCommit) {
364   SchedulerSettings default_scheduler_settings;
365   StateMachine state(default_scheduler_settings);
366   state.SetCanStart();
367   state.UpdateState(state.NextAction());
368   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
369   state.SetVisible(true);
370   state.SetCanDraw(true);
371   state.SetNeedsRedraw(true);
372   EXPECT_TRUE(state.RedrawPending());
373   EXPECT_TRUE(state.BeginFrameNeeded());
374 
375   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
376   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
377   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
378   state.OnBeginImplFrameDeadline();
379   EXPECT_ACTION_UPDATE_STATE(
380       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
381   state.DidSwapBuffers();
382   state.DidSwapBuffersComplete();
383   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
384   EXPECT_FALSE(state.RedrawPending());
385   EXPECT_FALSE(state.CommitPending());
386 
387   // Missing high res content requires a commit (but not a redraw)
388   state.DidDrawIfPossibleCompleted(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT);
389   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
390   EXPECT_ACTION_UPDATE_STATE(
391       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
392   EXPECT_FALSE(state.RedrawPending());
393   EXPECT_TRUE(state.CommitPending());
394 }
395 
TEST(SchedulerStateMachineTest,TestsetNeedsRedrawDuringFailedDrawDoesNotRemoveNeedsRedraw)396 TEST(SchedulerStateMachineTest,
397      TestsetNeedsRedrawDuringFailedDrawDoesNotRemoveNeedsRedraw) {
398   SchedulerSettings default_scheduler_settings;
399   StateMachine state(default_scheduler_settings);
400   state.SetCanStart();
401   state.UpdateState(state.NextAction());
402   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
403 
404   state.SetVisible(true);
405   state.SetCanDraw(true);
406   state.SetNeedsRedraw(true);
407   EXPECT_TRUE(state.RedrawPending());
408   EXPECT_TRUE(state.BeginFrameNeeded());
409   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
410   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
411   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
412   state.OnBeginImplFrameDeadline();
413 
414   // We're drawing now.
415   EXPECT_ACTION_UPDATE_STATE(
416       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
417   state.DidSwapBuffers();
418   state.DidSwapBuffersComplete();
419   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
420   EXPECT_FALSE(state.RedrawPending());
421   EXPECT_FALSE(state.CommitPending());
422 
423   // While still in the same BeginMainFrame callback on the main thread,
424   // set needs redraw again. This should not redraw.
425   state.SetNeedsRedraw(true);
426   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
427 
428   // Failing the draw for animation checkerboards makes us require a commit.
429   state.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
430   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
431   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
432   EXPECT_ACTION_UPDATE_STATE(
433       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
434   EXPECT_TRUE(state.RedrawPending());
435 }
436 
TestFailedDrawsEventuallyForceDrawAfterNextCommit(bool main_frame_before_draw_enabled)437 void TestFailedDrawsEventuallyForceDrawAfterNextCommit(
438     bool main_frame_before_draw_enabled) {
439   SchedulerSettings scheduler_settings;
440   scheduler_settings.main_frame_before_draw_enabled =
441       main_frame_before_draw_enabled;
442   scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ = 1;
443   StateMachine state(scheduler_settings);
444   state.SetCanStart();
445   state.UpdateState(state.NextAction());
446   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
447   state.SetVisible(true);
448   state.SetCanDraw(true);
449 
450   // Start a commit.
451   state.SetNeedsCommit();
452   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
453   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
454   EXPECT_ACTION_UPDATE_STATE(
455       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
456   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
457   EXPECT_TRUE(state.CommitPending());
458 
459   // Then initiate a draw.
460   state.SetNeedsRedraw(true);
461   state.OnBeginImplFrameDeadline();
462   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
463   EXPECT_ACTION_UPDATE_STATE(
464       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
465 
466   // Fail the draw.
467   state.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
468   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
469   EXPECT_TRUE(state.BeginFrameNeeded());
470   EXPECT_TRUE(state.RedrawPending());
471   // But the commit is ongoing.
472   EXPECT_TRUE(state.CommitPending());
473 
474   // Finish the commit. Note, we should not yet be forcing a draw, but should
475   // continue the commit as usual.
476   state.NotifyBeginMainFrameStarted();
477   state.NotifyReadyToCommit();
478   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
479   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
480   EXPECT_TRUE(state.RedrawPending());
481 
482   // The redraw should be forced at the end of the next BeginImplFrame.
483   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
484   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
485   if (main_frame_before_draw_enabled) {
486     EXPECT_ACTION_UPDATE_STATE(
487         SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
488   }
489   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
490   state.OnBeginImplFrameDeadline();
491   EXPECT_ACTION_UPDATE_STATE(
492       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED);
493   state.DidSwapBuffers();
494   state.DidSwapBuffersComplete();
495 }
496 
TEST(SchedulerStateMachineTest,TestFailedDrawsEventuallyForceDrawAfterNextCommit)497 TEST(SchedulerStateMachineTest,
498      TestFailedDrawsEventuallyForceDrawAfterNextCommit) {
499   bool main_frame_before_draw_enabled = false;
500   TestFailedDrawsEventuallyForceDrawAfterNextCommit(
501       main_frame_before_draw_enabled);
502 }
503 
TEST(SchedulerStateMachineTest,TestFailedDrawsEventuallyForceDrawAfterNextCommit_CommitBeforeDraw)504 TEST(SchedulerStateMachineTest,
505      TestFailedDrawsEventuallyForceDrawAfterNextCommit_CommitBeforeDraw) {
506   bool main_frame_before_draw_enabled = true;
507   TestFailedDrawsEventuallyForceDrawAfterNextCommit(
508       main_frame_before_draw_enabled);
509 }
510 
TEST(SchedulerStateMachineTest,TestFailedDrawsDoNotRestartForcedDraw)511 TEST(SchedulerStateMachineTest, TestFailedDrawsDoNotRestartForcedDraw) {
512   SchedulerSettings scheduler_settings;
513   int draw_limit = 1;
514   scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ =
515       draw_limit;
516   scheduler_settings.impl_side_painting = true;
517   StateMachine state(scheduler_settings);
518   state.SetCanStart();
519   state.UpdateState(state.NextAction());
520   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
521   state.SetVisible(true);
522   state.SetCanDraw(true);
523 
524   // Start a commit.
525   state.SetNeedsCommit();
526   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
527   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
528   EXPECT_ACTION_UPDATE_STATE(
529       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
530   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
531   EXPECT_TRUE(state.CommitPending());
532 
533   // Then initiate a draw.
534   state.SetNeedsRedraw(true);
535   state.OnBeginImplFrameDeadline();
536   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
537   EXPECT_ACTION_UPDATE_STATE(
538       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
539 
540   // Fail the draw enough times to force a redraw,
541   // then once more for good measure.
542   for (int i = 0; i < draw_limit + 1; ++i)
543     state.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
544   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
545   EXPECT_TRUE(state.BeginFrameNeeded());
546   EXPECT_TRUE(state.RedrawPending());
547   // But the commit is ongoing.
548   EXPECT_TRUE(state.CommitPending());
549   EXPECT_TRUE(state.ForcedRedrawState() ==
550               SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_COMMIT);
551 
552   state.NotifyBeginMainFrameStarted();
553   state.NotifyReadyToCommit();
554   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
555   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
556   EXPECT_TRUE(state.RedrawPending());
557   EXPECT_FALSE(state.CommitPending());
558 
559   // Now force redraw should be in waiting for activation
560   EXPECT_TRUE(state.ForcedRedrawState() ==
561     SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION);
562 
563   // After failing additional draws, we should still be in a forced
564   // redraw, but not back in WAITING_FOR_COMMIT.
565   for (int i = 0; i < draw_limit + 1; ++i)
566     state.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
567   EXPECT_TRUE(state.RedrawPending());
568   EXPECT_TRUE(state.ForcedRedrawState() ==
569     SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION);
570 }
571 
TEST(SchedulerStateMachineTest,TestFailedDrawIsRetriedInNextBeginImplFrame)572 TEST(SchedulerStateMachineTest, TestFailedDrawIsRetriedInNextBeginImplFrame) {
573   SchedulerSettings default_scheduler_settings;
574   StateMachine state(default_scheduler_settings);
575   state.SetCanStart();
576   state.UpdateState(state.NextAction());
577   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
578   state.SetVisible(true);
579   state.SetCanDraw(true);
580 
581   // Start a draw.
582   state.SetNeedsRedraw(true);
583   EXPECT_TRUE(state.BeginFrameNeeded());
584   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
585   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
586   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
587   state.OnBeginImplFrameDeadline();
588   EXPECT_TRUE(state.RedrawPending());
589   EXPECT_ACTION_UPDATE_STATE(
590       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
591 
592   // Failing the draw for animation checkerboards makes us require a commit.
593   state.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
594   EXPECT_ACTION_UPDATE_STATE(
595       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
596   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
597   EXPECT_TRUE(state.RedrawPending());
598 
599   // We should not be trying to draw again now, but we have a commit pending.
600   EXPECT_TRUE(state.BeginFrameNeeded());
601   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
602   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
603   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
604 
605   // We should try to draw again at the end of the next BeginImplFrame on
606   // the impl thread.
607   state.OnBeginImplFrameDeadline();
608   EXPECT_ACTION_UPDATE_STATE(
609       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
610   state.DidSwapBuffers();
611   state.DidSwapBuffersComplete();
612   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
613 }
614 
TEST(SchedulerStateMachineTest,TestDoestDrawTwiceInSameFrame)615 TEST(SchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame) {
616   SchedulerSettings default_scheduler_settings;
617   StateMachine state(default_scheduler_settings);
618   state.SetCanStart();
619   state.UpdateState(state.NextAction());
620   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
621   state.SetVisible(true);
622   state.SetCanDraw(true);
623   state.SetNeedsRedraw(true);
624 
625   // Draw the first frame.
626   EXPECT_TRUE(state.BeginFrameNeeded());
627   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
628   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
629   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
630 
631   state.OnBeginImplFrameDeadline();
632   EXPECT_ACTION_UPDATE_STATE(
633       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
634   state.DidSwapBuffers();
635   state.DidDrawIfPossibleCompleted(DRAW_SUCCESS);
636   state.DidSwapBuffersComplete();
637   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
638 
639   // Before the next BeginImplFrame, set needs redraw again.
640   // This should not redraw until the next BeginImplFrame.
641   state.SetNeedsRedraw(true);
642   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
643 
644   // Move to another frame. This should now draw.
645   EXPECT_TRUE(state.BeginFrameNeeded());
646   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
647 
648   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
649   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
650 
651   state.OnBeginImplFrameDeadline();
652   EXPECT_ACTION_UPDATE_STATE(
653       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
654   state.DidSwapBuffers();
655   state.DidDrawIfPossibleCompleted(DRAW_SUCCESS);
656   state.DidSwapBuffersComplete();
657   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
658 
659   // We just swapped, so we should proactively request another BeginImplFrame.
660   EXPECT_TRUE(state.BeginFrameNeeded());
661 }
662 
TEST(SchedulerStateMachineTest,TestNextActionDrawsOnBeginImplFrame)663 TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginImplFrame) {
664   SchedulerSettings default_scheduler_settings;
665 
666   // When not in BeginImplFrame deadline, or in BeginImplFrame deadline
667   // but not visible, don't draw.
668   size_t num_commit_states =
669       sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
670   size_t num_begin_impl_frame_states =
671       sizeof(all_begin_impl_frame_states) /
672       sizeof(SchedulerStateMachine::BeginImplFrameState);
673   for (size_t i = 0; i < num_commit_states; ++i) {
674     for (size_t j = 0; j < num_begin_impl_frame_states; ++j) {
675       StateMachine state(default_scheduler_settings);
676       state.SetCanStart();
677       state.UpdateState(state.NextAction());
678       state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
679       state.SetCommitState(all_commit_states[i]);
680       state.SetBeginImplFrameState(all_begin_impl_frame_states[j]);
681       bool visible =
682           (all_begin_impl_frame_states[j] !=
683            SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
684       state.SetVisible(visible);
685 
686       // Case 1: needs_commit=false
687       EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
688                 state.NextAction());
689 
690       // Case 2: needs_commit=true
691       state.SetNeedsCommit();
692       EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
693                 state.NextAction())
694           << state.AsValue()->ToString();
695     }
696   }
697 
698   // When in BeginImplFrame deadline we should always draw for SetNeedsRedraw
699   // except if we're ready to commit, in which case we expect a commit first.
700   for (size_t i = 0; i < num_commit_states; ++i) {
701     StateMachine state(default_scheduler_settings);
702     state.SetCanStart();
703     state.UpdateState(state.NextAction());
704     state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
705     state.SetCanDraw(true);
706     state.SetCommitState(all_commit_states[i]);
707     state.SetBeginImplFrameState(
708         SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
709 
710     state.SetNeedsRedraw(true);
711     state.SetVisible(true);
712 
713     SchedulerStateMachine::Action expected_action;
714     if (all_commit_states[i] ==
715         SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT) {
716       expected_action = SchedulerStateMachine::ACTION_COMMIT;
717     } else {
718       expected_action = SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
719       EXPECT_EQ(state.NextAction(), SchedulerStateMachine::ACTION_ANIMATE)
720           << state.AsValue()->ToString();
721       state.UpdateState(state.NextAction());
722     }
723 
724     // Case 1: needs_commit=false.
725     EXPECT_EQ(state.NextAction(), expected_action)
726         << state.AsValue()->ToString();
727 
728     // Case 2: needs_commit=true.
729     state.SetNeedsCommit();
730     EXPECT_EQ(state.NextAction(), expected_action)
731         << state.AsValue()->ToString();
732   }
733 }
734 
TEST(SchedulerStateMachineTest,TestNoCommitStatesRedrawWhenInvisible)735 TEST(SchedulerStateMachineTest, TestNoCommitStatesRedrawWhenInvisible) {
736   SchedulerSettings default_scheduler_settings;
737 
738   size_t num_commit_states =
739       sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
740   for (size_t i = 0; i < num_commit_states; ++i) {
741     // There shouldn't be any drawing regardless of BeginImplFrame.
742     for (size_t j = 0; j < 2; ++j) {
743       StateMachine state(default_scheduler_settings);
744       state.SetCanStart();
745       state.UpdateState(state.NextAction());
746       state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
747       state.SetCommitState(all_commit_states[i]);
748       state.SetVisible(false);
749       state.SetNeedsRedraw(true);
750       if (j == 1) {
751         state.SetBeginImplFrameState(
752             SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
753       }
754 
755       // Case 1: needs_commit=false.
756       EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
757                 state.NextAction());
758 
759       // Case 2: needs_commit=true.
760       state.SetNeedsCommit();
761       EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
762                 state.NextAction())
763           << state.AsValue()->ToString();
764     }
765   }
766 }
767 
TEST(SchedulerStateMachineTest,TestCanRedraw_StopsDraw)768 TEST(SchedulerStateMachineTest, TestCanRedraw_StopsDraw) {
769   SchedulerSettings default_scheduler_settings;
770 
771   size_t num_commit_states =
772       sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
773   for (size_t i = 0; i < num_commit_states; ++i) {
774     // There shouldn't be any drawing regardless of BeginImplFrame.
775     for (size_t j = 0; j < 2; ++j) {
776       StateMachine state(default_scheduler_settings);
777       state.SetCanStart();
778       state.UpdateState(state.NextAction());
779       state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
780       state.SetCommitState(all_commit_states[i]);
781       state.SetVisible(false);
782       state.SetNeedsRedraw(true);
783       if (j == 1)
784         state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
785 
786       state.SetCanDraw(false);
787       EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
788                 state.NextAction());
789     }
790   }
791 }
792 
TEST(SchedulerStateMachineTest,TestCanRedrawWithWaitingForFirstDrawMakesProgress)793 TEST(SchedulerStateMachineTest,
794      TestCanRedrawWithWaitingForFirstDrawMakesProgress) {
795   SchedulerSettings default_scheduler_settings;
796   StateMachine state(default_scheduler_settings);
797   state.SetCanStart();
798   state.UpdateState(state.NextAction());
799   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
800 
801   state.SetActiveTreeNeedsFirstDraw(true);
802   state.SetNeedsCommit();
803   state.SetNeedsRedraw(true);
804   state.SetVisible(true);
805   state.SetCanDraw(false);
806   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
807   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
808   EXPECT_ACTION_UPDATE_STATE(
809       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
810   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
811   state.NotifyBeginMainFrameStarted();
812   state.NotifyReadyToCommit();
813   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
814   state.OnBeginImplFrameDeadline();
815   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
816   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
817 }
818 
TestSetNeedsCommitIsNotLost(bool main_frame_before_draw_enabled)819 void TestSetNeedsCommitIsNotLost(bool main_frame_before_draw_enabled) {
820   SchedulerSettings scheduler_settings;
821   scheduler_settings.main_frame_before_draw_enabled =
822       main_frame_before_draw_enabled;
823   StateMachine state(scheduler_settings);
824   state.SetCanStart();
825   state.UpdateState(state.NextAction());
826   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
827   state.SetNeedsCommit();
828   state.SetVisible(true);
829   state.SetCanDraw(true);
830 
831   EXPECT_TRUE(state.BeginFrameNeeded());
832 
833   // Begin the frame.
834   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
835   EXPECT_ACTION_UPDATE_STATE(
836       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
837   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
838             state.CommitState());
839 
840   // Now, while the frame is in progress, set another commit.
841   state.SetNeedsCommit();
842   EXPECT_TRUE(state.NeedsCommit());
843 
844   // Let the frame finish.
845   state.NotifyBeginMainFrameStarted();
846   state.NotifyReadyToCommit();
847   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
848             state.CommitState());
849 
850   // Expect to commit regardless of BeginImplFrame state.
851   EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
852             state.begin_impl_frame_state());
853   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
854 
855   state.OnBeginImplFrameDeadlinePending();
856   EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
857             state.begin_impl_frame_state());
858   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
859 
860   state.OnBeginImplFrameDeadline();
861   EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE,
862             state.begin_impl_frame_state());
863   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
864 
865   state.OnBeginImplFrameIdle();
866   EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE,
867             state.begin_impl_frame_state());
868   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
869 
870   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
871   EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
872             state.begin_impl_frame_state());
873   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
874 
875   // Finish the commit, then make sure we start the next commit immediately
876   // and draw on the next BeginImplFrame.
877   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
878   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
879   if (main_frame_before_draw_enabled) {
880     EXPECT_ACTION_UPDATE_STATE(
881         SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
882   }
883   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
884 
885   state.OnBeginImplFrameDeadline();
886 
887   EXPECT_TRUE(state.active_tree_needs_first_draw());
888   EXPECT_ACTION_UPDATE_STATE(
889       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
890   state.DidSwapBuffers();
891   state.DidDrawIfPossibleCompleted(DRAW_SUCCESS);
892   state.DidSwapBuffersComplete();
893   if (!main_frame_before_draw_enabled) {
894     EXPECT_ACTION_UPDATE_STATE(
895         SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
896   }
897   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
898 }
899 
TEST(SchedulerStateMachineTest,TestSetNeedsCommitIsNotLost)900 TEST(SchedulerStateMachineTest, TestSetNeedsCommitIsNotLost) {
901   bool main_frame_before_draw_enabled = false;
902   TestSetNeedsCommitIsNotLost(main_frame_before_draw_enabled);
903 }
904 
TEST(SchedulerStateMachineTest,TestSetNeedsCommitIsNotLost_CommitBeforeDraw)905 TEST(SchedulerStateMachineTest, TestSetNeedsCommitIsNotLost_CommitBeforeDraw) {
906   bool main_frame_before_draw_enabled = true;
907   TestSetNeedsCommitIsNotLost(main_frame_before_draw_enabled);
908 }
909 
TEST(SchedulerStateMachineTest,TestFullCycle)910 TEST(SchedulerStateMachineTest, TestFullCycle) {
911   SchedulerSettings default_scheduler_settings;
912   StateMachine state(default_scheduler_settings);
913   state.SetCanStart();
914   state.UpdateState(state.NextAction());
915   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
916   state.SetVisible(true);
917   state.SetCanDraw(true);
918 
919   // Start clean and set commit.
920   state.SetNeedsCommit();
921 
922   // Begin the frame.
923   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
924   EXPECT_ACTION_UPDATE_STATE(
925       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
926   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
927             state.CommitState());
928   EXPECT_FALSE(state.NeedsCommit());
929   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
930 
931   // Tell the scheduler the frame finished.
932   state.NotifyBeginMainFrameStarted();
933   state.NotifyReadyToCommit();
934   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
935             state.CommitState());
936 
937   // Commit.
938   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
939   EXPECT_TRUE(state.active_tree_needs_first_draw());
940   EXPECT_TRUE(state.needs_redraw());
941 
942   // Expect to do nothing until BeginImplFrame deadline
943   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
944 
945   // At BeginImplFrame deadline, draw.
946   state.OnBeginImplFrameDeadline();
947   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
948   EXPECT_ACTION_UPDATE_STATE(
949       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
950   state.DidSwapBuffers();
951   state.DidDrawIfPossibleCompleted(DRAW_SUCCESS);
952   state.DidSwapBuffersComplete();
953 
954   // Should be synchronized, no draw needed, no action needed.
955   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
956   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
957   EXPECT_FALSE(state.needs_redraw());
958 }
959 
TEST(SchedulerStateMachineTest,TestFullCycleWithCommitRequestInbetween)960 TEST(SchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween) {
961   SchedulerSettings default_scheduler_settings;
962   StateMachine state(default_scheduler_settings);
963   state.SetCanStart();
964   state.UpdateState(state.NextAction());
965   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
966   state.SetVisible(true);
967   state.SetCanDraw(true);
968 
969   // Start clean and set commit.
970   state.SetNeedsCommit();
971 
972   // Begin the frame.
973   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
974   EXPECT_ACTION_UPDATE_STATE(
975       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
976   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
977             state.CommitState());
978   EXPECT_FALSE(state.NeedsCommit());
979   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
980 
981   // Request another commit while the commit is in flight.
982   state.SetNeedsCommit();
983   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
984 
985   // Tell the scheduler the frame finished.
986   state.NotifyBeginMainFrameStarted();
987   state.NotifyReadyToCommit();
988   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
989             state.CommitState());
990 
991   // First commit.
992   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
993   EXPECT_TRUE(state.active_tree_needs_first_draw());
994   EXPECT_TRUE(state.needs_redraw());
995 
996   // Expect to do nothing until BeginImplFrame deadline.
997   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
998 
999   // At BeginImplFrame deadline, draw.
1000   state.OnBeginImplFrameDeadline();
1001   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
1002   EXPECT_ACTION_UPDATE_STATE(
1003       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
1004   state.DidSwapBuffers();
1005   state.DidDrawIfPossibleCompleted(DRAW_SUCCESS);
1006   state.DidSwapBuffersComplete();
1007 
1008   // Should be synchronized, no draw needed, no action needed.
1009   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1010   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
1011   EXPECT_FALSE(state.needs_redraw());
1012 
1013   // Next BeginImplFrame should initiate second commit.
1014   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1015   EXPECT_ACTION_UPDATE_STATE(
1016       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1017 }
1018 
TEST(SchedulerStateMachineTest,TestRequestCommitInvisible)1019 TEST(SchedulerStateMachineTest, TestRequestCommitInvisible) {
1020   SchedulerSettings default_scheduler_settings;
1021   StateMachine state(default_scheduler_settings);
1022   state.SetCanStart();
1023   state.UpdateState(state.NextAction());
1024   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1025   state.SetNeedsCommit();
1026   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1027 }
1028 
TEST(SchedulerStateMachineTest,TestGoesInvisibleBeforeFinishCommit)1029 TEST(SchedulerStateMachineTest, TestGoesInvisibleBeforeFinishCommit) {
1030   SchedulerSettings default_scheduler_settings;
1031   StateMachine state(default_scheduler_settings);
1032   state.SetCanStart();
1033   state.UpdateState(state.NextAction());
1034   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1035   state.SetVisible(true);
1036   state.SetCanDraw(true);
1037 
1038   // Start clean and set commit.
1039   state.SetNeedsCommit();
1040 
1041   // Begin the frame while visible.
1042   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1043   EXPECT_ACTION_UPDATE_STATE(
1044       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1045   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
1046             state.CommitState());
1047   EXPECT_FALSE(state.NeedsCommit());
1048   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1049 
1050   // Become invisible and abort BeginMainFrame.
1051   state.SetVisible(false);
1052   state.BeginMainFrameAborted(false);
1053 
1054   // We should now be back in the idle state as if we never started the frame.
1055   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
1056   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1057 
1058   // We shouldn't do anything on the BeginImplFrame deadline.
1059   state.OnBeginImplFrameDeadline();
1060   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1061 
1062   // Become visible again.
1063   state.SetVisible(true);
1064 
1065   // Although we have aborted on this frame and haven't cancelled the commit
1066   // (i.e. need another), don't send another BeginMainFrame yet.
1067   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
1068   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1069   EXPECT_TRUE(state.NeedsCommit());
1070 
1071   // Start a new frame.
1072   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1073   EXPECT_ACTION_UPDATE_STATE(
1074       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1075 
1076   // We should be starting the commit now.
1077   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
1078             state.CommitState());
1079   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1080 }
1081 
TEST(SchedulerStateMachineTest,AbortBeginMainFrameAndCancelCommit)1082 TEST(SchedulerStateMachineTest, AbortBeginMainFrameAndCancelCommit) {
1083   SchedulerSettings default_scheduler_settings;
1084   StateMachine state(default_scheduler_settings);
1085   state.SetCanStart();
1086   state.UpdateState(state.NextAction());
1087   state.DidCreateAndInitializeOutputSurface();
1088   state.SetVisible(true);
1089   state.SetCanDraw(true);
1090 
1091   // Get into a begin frame / commit state.
1092   state.SetNeedsCommit();
1093 
1094   EXPECT_ACTION_UPDATE_STATE(
1095       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1096   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
1097             state.CommitState());
1098   EXPECT_FALSE(state.NeedsCommit());
1099   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1100 
1101   // Abort the commit, cancelling future commits.
1102   state.BeginMainFrameAborted(true);
1103 
1104   // Verify that another commit doesn't start on the same frame.
1105   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
1106   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1107   EXPECT_FALSE(state.NeedsCommit());
1108 
1109   // Start a new frame; draw because this is the first frame since output
1110   // surface init'd.
1111   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1112   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
1113   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1114   state.OnBeginImplFrameDeadline();
1115   EXPECT_ACTION_UPDATE_STATE(
1116       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
1117   state.DidSwapBuffers();
1118   state.DidSwapBuffersComplete();
1119 
1120   // Verify another commit doesn't start on another frame either.
1121   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
1122   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1123   EXPECT_FALSE(state.NeedsCommit());
1124 
1125   // Verify another commit can start if requested, though.
1126   state.SetNeedsCommit();
1127   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
1128   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME,
1129             state.NextAction());
1130 }
1131 
TEST(SchedulerStateMachineTest,AbortBeginMainFrameAndCancelCommitWhenInvisible)1132 TEST(SchedulerStateMachineTest,
1133      AbortBeginMainFrameAndCancelCommitWhenInvisible) {
1134   SchedulerSettings default_scheduler_settings;
1135   StateMachine state(default_scheduler_settings);
1136   state.SetCanStart();
1137   state.UpdateState(state.NextAction());
1138   state.DidCreateAndInitializeOutputSurface();
1139   state.SetVisible(true);
1140   state.SetCanDraw(true);
1141 
1142   // Get into a begin frame / commit state.
1143   state.SetNeedsCommit();
1144 
1145   EXPECT_ACTION_UPDATE_STATE(
1146       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1147   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
1148             state.CommitState());
1149   EXPECT_FALSE(state.NeedsCommit());
1150   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1151 
1152   // Become invisible and abort BeginMainFrame.
1153   state.SetVisible(false);
1154   state.BeginMainFrameAborted(true);
1155 
1156   // Verify that another commit doesn't start on the same frame.
1157   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
1158   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1159   EXPECT_FALSE(state.NeedsCommit());
1160 
1161   // Become visible and start a new frame.
1162   state.SetVisible(true);
1163   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1164   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
1165   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1166 
1167   // Draw because this is the first frame since output surface init'd.
1168   state.OnBeginImplFrameDeadline();
1169   EXPECT_ACTION_UPDATE_STATE(
1170       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
1171   state.DidSwapBuffers();
1172   state.DidSwapBuffersComplete();
1173 
1174   // Verify another commit doesn't start on another frame either.
1175   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
1176   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1177   EXPECT_FALSE(state.NeedsCommit());
1178 
1179   // Verify another commit can start if requested, though.
1180   state.SetNeedsCommit();
1181   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
1182   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME,
1183             state.NextAction());
1184 }
1185 
TEST(SchedulerStateMachineTest,AbortBeginMainFrameAndRequestCommitWhenInvisible)1186 TEST(SchedulerStateMachineTest,
1187      AbortBeginMainFrameAndRequestCommitWhenInvisible) {
1188   SchedulerSettings default_scheduler_settings;
1189   StateMachine state(default_scheduler_settings);
1190   state.SetCanStart();
1191   state.UpdateState(state.NextAction());
1192   state.DidCreateAndInitializeOutputSurface();
1193   state.SetVisible(true);
1194   state.SetCanDraw(true);
1195 
1196   // Get into a begin frame / commit state.
1197   state.SetNeedsCommit();
1198 
1199   EXPECT_ACTION_UPDATE_STATE(
1200       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1201   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
1202             state.CommitState());
1203   EXPECT_FALSE(state.NeedsCommit());
1204   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1205 
1206   // Become invisible and abort BeginMainFrame.
1207   state.SetVisible(false);
1208   state.BeginMainFrameAborted(true);
1209 
1210   // Verify that another commit doesn't start on the same frame.
1211   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
1212   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1213   EXPECT_FALSE(state.NeedsCommit());
1214 
1215   // Asking for a commit while not visible won't make it happen.
1216   state.SetNeedsCommit();
1217   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
1218   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1219   EXPECT_TRUE(state.NeedsCommit());
1220 
1221   // Become visible but nothing happens until the next frame.
1222   state.SetVisible(true);
1223   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
1224   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1225   EXPECT_TRUE(state.NeedsCommit());
1226 
1227   // We should get that commit when we begin the next frame.
1228   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1229   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
1230   EXPECT_ACTION_UPDATE_STATE(
1231       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1232 }
1233 
TEST(SchedulerStateMachineTest,AbortBeginMainFrameAndRequestCommitAndBeginImplFrameWhenInvisible)1234 TEST(SchedulerStateMachineTest,
1235      AbortBeginMainFrameAndRequestCommitAndBeginImplFrameWhenInvisible) {
1236   SchedulerSettings default_scheduler_settings;
1237   StateMachine state(default_scheduler_settings);
1238   state.SetCanStart();
1239   state.UpdateState(state.NextAction());
1240   state.DidCreateAndInitializeOutputSurface();
1241   state.SetVisible(true);
1242   state.SetCanDraw(true);
1243 
1244   // Get into a begin frame / commit state.
1245   state.SetNeedsCommit();
1246 
1247   EXPECT_ACTION_UPDATE_STATE(
1248       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1249   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
1250             state.CommitState());
1251   EXPECT_FALSE(state.NeedsCommit());
1252   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1253 
1254   // Become invisible and abort BeginMainFrame.
1255   state.SetVisible(false);
1256   state.BeginMainFrameAborted(true);
1257 
1258   // Asking for a commit while not visible won't make it happen.
1259   state.SetNeedsCommit();
1260   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
1261   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1262   EXPECT_TRUE(state.NeedsCommit());
1263 
1264   // Begin a frame when not visible, the scheduler animates but does not commit.
1265   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1266   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
1267   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
1268   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1269   EXPECT_TRUE(state.NeedsCommit());
1270 
1271   // Become visible and the requested commit happens immediately.
1272   state.SetVisible(true);
1273   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
1274   EXPECT_ACTION_UPDATE_STATE(
1275       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1276 }
1277 
TEST(SchedulerStateMachineTest,TestFirstContextCreation)1278 TEST(SchedulerStateMachineTest, TestFirstContextCreation) {
1279   SchedulerSettings default_scheduler_settings;
1280   StateMachine state(default_scheduler_settings);
1281   state.SetCanStart();
1282   state.SetVisible(true);
1283   state.SetCanDraw(true);
1284 
1285   EXPECT_ACTION_UPDATE_STATE(
1286       SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
1287   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1288   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1289 
1290   // Check that the first init does not SetNeedsCommit.
1291   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1292   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1293   state.OnBeginImplFrameDeadline();
1294   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1295 
1296   // Check that a needs commit initiates a BeginMainFrame.
1297   state.SetNeedsCommit();
1298   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1299   EXPECT_ACTION_UPDATE_STATE(
1300       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1301 }
1302 
TEST(SchedulerStateMachineTest,TestContextLostWhenCompletelyIdle)1303 TEST(SchedulerStateMachineTest, TestContextLostWhenCompletelyIdle) {
1304   SchedulerSettings default_scheduler_settings;
1305   StateMachine state(default_scheduler_settings);
1306   state.SetCanStart();
1307   state.UpdateState(state.NextAction());
1308   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1309 
1310   state.SetVisible(true);
1311   state.SetCanDraw(true);
1312 
1313   EXPECT_NE(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
1314             state.NextAction());
1315   state.DidLoseOutputSurface();
1316 
1317   EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
1318             state.NextAction());
1319   state.UpdateState(state.NextAction());
1320 
1321   // Once context recreation begins, nothing should happen.
1322   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1323 
1324   // Recreate the context.
1325   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1326 
1327   // When the context is recreated, we should begin a commit.
1328   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1329   EXPECT_ACTION_UPDATE_STATE(
1330       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1331 }
1332 
TEST(SchedulerStateMachineTest,TestContextLostWhenIdleAndCommitRequestedWhileRecreating)1333 TEST(SchedulerStateMachineTest,
1334      TestContextLostWhenIdleAndCommitRequestedWhileRecreating) {
1335   SchedulerSettings default_scheduler_settings;
1336   StateMachine state(default_scheduler_settings);
1337   state.SetCanStart();
1338   state.UpdateState(state.NextAction());
1339   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1340   state.SetVisible(true);
1341   state.SetCanDraw(true);
1342 
1343   EXPECT_NE(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
1344             state.NextAction());
1345   state.DidLoseOutputSurface();
1346 
1347   EXPECT_ACTION_UPDATE_STATE(
1348       SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
1349   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1350 
1351   // Once context recreation begins, nothing should happen.
1352   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1353   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1354   state.OnBeginImplFrameDeadline();
1355   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1356 
1357   // While context is recreating, commits shouldn't begin.
1358   state.SetNeedsCommit();
1359   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1360   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1361   state.OnBeginImplFrameDeadline();
1362   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1363 
1364   // Recreate the context
1365   state.DidCreateAndInitializeOutputSurface();
1366   EXPECT_FALSE(state.RedrawPending());
1367 
1368   // When the context is recreated, we should begin a commit
1369   EXPECT_ACTION_UPDATE_STATE(
1370       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1371   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1372   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT,
1373             state.CommitState());
1374 
1375   state.NotifyBeginMainFrameStarted();
1376   state.NotifyReadyToCommit();
1377   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1378   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1379   // Finishing the first commit after initializing an output surface should
1380   // automatically cause a redraw.
1381   EXPECT_TRUE(state.RedrawPending());
1382 
1383   // Once the context is recreated, whether we draw should be based on
1384   // SetCanDraw.
1385   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1386   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
1387   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1388   state.OnBeginImplFrameDeadline();
1389   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
1390             state.NextAction());
1391   state.SetCanDraw(false);
1392   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT,
1393             state.NextAction());
1394   state.SetCanDraw(true);
1395   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
1396             state.NextAction());
1397 }
1398 
TEST(SchedulerStateMachineTest,TestContextLostWhileCommitInProgress)1399 TEST(SchedulerStateMachineTest, TestContextLostWhileCommitInProgress) {
1400   SchedulerSettings scheduler_settings;
1401   StateMachine state(scheduler_settings);
1402   state.SetCanStart();
1403   state.UpdateState(state.NextAction());
1404   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1405   state.SetVisible(true);
1406   state.SetCanDraw(true);
1407 
1408   // Get a commit in flight.
1409   state.SetNeedsCommit();
1410 
1411   // Set damage and expect a draw.
1412   state.SetNeedsRedraw(true);
1413   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1414   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
1415   EXPECT_ACTION_UPDATE_STATE(
1416       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1417   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1418   state.OnBeginImplFrameDeadline();
1419   EXPECT_ACTION_UPDATE_STATE(
1420       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
1421   state.DidSwapBuffers();
1422   state.DidSwapBuffersComplete();
1423   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1424 
1425   // Cause a lost context while the BeginMainFrame is in flight.
1426   state.DidLoseOutputSurface();
1427 
1428   // Ask for another draw. Expect nothing happens.
1429   state.SetNeedsRedraw(true);
1430   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1431 
1432   // Finish the frame, and commit.
1433   state.NotifyBeginMainFrameStarted();
1434   state.NotifyReadyToCommit();
1435   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1436 
1437   // We will abort the draw when the output surface is lost if we are
1438   // waiting for the first draw to unblock the main thread.
1439   EXPECT_TRUE(state.active_tree_needs_first_draw());
1440   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
1441 
1442   // Expect to begin context recreation only in BEGIN_IMPL_FRAME_STATE_IDLE
1443   EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE,
1444             state.begin_impl_frame_state());
1445   EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
1446             state.NextAction());
1447 
1448   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1449   EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
1450             state.begin_impl_frame_state());
1451   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1452 
1453   state.OnBeginImplFrameDeadlinePending();
1454   EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
1455             state.begin_impl_frame_state());
1456   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1457 
1458   state.OnBeginImplFrameDeadline();
1459   EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE,
1460             state.begin_impl_frame_state());
1461   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1462 }
1463 
TEST(SchedulerStateMachineTest,TestContextLostWhileCommitInProgressAndAnotherCommitRequested)1464 TEST(SchedulerStateMachineTest,
1465      TestContextLostWhileCommitInProgressAndAnotherCommitRequested) {
1466   SchedulerSettings scheduler_settings;
1467   StateMachine state(scheduler_settings);
1468   state.SetCanStart();
1469   state.UpdateState(state.NextAction());
1470   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1471   state.SetVisible(true);
1472   state.SetCanDraw(true);
1473 
1474   // Get a commit in flight.
1475   state.SetNeedsCommit();
1476   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1477 
1478   // Set damage and expect a draw.
1479   state.SetNeedsRedraw(true);
1480   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1481   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
1482   EXPECT_ACTION_UPDATE_STATE(
1483       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1484   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1485   state.OnBeginImplFrameDeadline();
1486   EXPECT_ACTION_UPDATE_STATE(
1487       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
1488   state.DidSwapBuffers();
1489   state.DidSwapBuffersComplete();
1490   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1491 
1492   // Cause a lost context while the BeginMainFrame is in flight.
1493   state.DidLoseOutputSurface();
1494 
1495   // Ask for another draw and also set needs commit. Expect nothing happens.
1496   state.SetNeedsRedraw(true);
1497   state.SetNeedsCommit();
1498   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1499 
1500   // Finish the frame, and commit.
1501   state.NotifyBeginMainFrameStarted();
1502   state.NotifyReadyToCommit();
1503   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1504   EXPECT_TRUE(state.active_tree_needs_first_draw());
1505 
1506   // Because the output surface is missing, we expect the draw to abort.
1507   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
1508 
1509   // Expect to begin context recreation only in BEGIN_IMPL_FRAME_STATE_IDLE
1510   EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE,
1511             state.begin_impl_frame_state());
1512   EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
1513             state.NextAction());
1514 
1515   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1516   EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
1517             state.begin_impl_frame_state());
1518   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1519 
1520   state.OnBeginImplFrameDeadlinePending();
1521   EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
1522             state.begin_impl_frame_state());
1523   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1524 
1525   state.OnBeginImplFrameDeadline();
1526   EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE,
1527             state.begin_impl_frame_state());
1528   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1529 
1530   state.OnBeginImplFrameIdle();
1531   EXPECT_ACTION_UPDATE_STATE(
1532       SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
1533 
1534   // After we get a new output surface, the commit flow should start.
1535   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1536   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1537   EXPECT_ACTION_UPDATE_STATE(
1538       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1539   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1540   state.NotifyBeginMainFrameStarted();
1541   state.NotifyReadyToCommit();
1542   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1543   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1544   state.OnBeginImplFrameDeadline();
1545   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
1546   EXPECT_ACTION_UPDATE_STATE(
1547       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
1548   state.DidSwapBuffers();
1549   state.DidSwapBuffersComplete();
1550   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1551 }
1552 
TEST(SchedulerStateMachineTest,DontDrawBeforeCommitAfterLostOutputSurface)1553 TEST(SchedulerStateMachineTest, DontDrawBeforeCommitAfterLostOutputSurface) {
1554   SchedulerSettings default_scheduler_settings;
1555   StateMachine state(default_scheduler_settings);
1556   state.SetCanStart();
1557   state.UpdateState(state.NextAction());
1558   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1559   state.SetVisible(true);
1560   state.SetCanDraw(true);
1561 
1562   state.SetNeedsRedraw(true);
1563 
1564   // Cause a lost output surface, and restore it.
1565   state.DidLoseOutputSurface();
1566   EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
1567             state.NextAction());
1568   state.UpdateState(state.NextAction());
1569   state.DidCreateAndInitializeOutputSurface();
1570 
1571   EXPECT_FALSE(state.RedrawPending());
1572   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1573   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME,
1574             state.NextAction());
1575 }
1576 
TEST(SchedulerStateMachineTest,TestPendingActivationsShouldBeForcedAfterLostOutputSurface)1577 TEST(SchedulerStateMachineTest,
1578      TestPendingActivationsShouldBeForcedAfterLostOutputSurface) {
1579   SchedulerSettings settings;
1580   settings.impl_side_painting = true;
1581   StateMachine state(settings);
1582   state.SetCanStart();
1583   state.UpdateState(state.NextAction());
1584   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1585   state.SetVisible(true);
1586   state.SetCanDraw(true);
1587 
1588   state.SetCommitState(
1589       SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
1590 
1591   // Cause a lost context.
1592   state.DidLoseOutputSurface();
1593 
1594   state.NotifyBeginMainFrameStarted();
1595   state.NotifyReadyToCommit();
1596   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1597 
1598   EXPECT_TRUE(state.PendingActivationsShouldBeForced());
1599   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE);
1600 
1601   EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
1602   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
1603 }
1604 
TEST(SchedulerStateMachineTest,TestNoBeginMainFrameWhenInvisible)1605 TEST(SchedulerStateMachineTest, TestNoBeginMainFrameWhenInvisible) {
1606   SchedulerSettings default_scheduler_settings;
1607   StateMachine state(default_scheduler_settings);
1608   state.SetCanStart();
1609   state.UpdateState(state.NextAction());
1610   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1611   state.SetVisible(false);
1612   state.SetNeedsCommit();
1613   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1614 }
1615 
TEST(SchedulerStateMachineTest,TestFinishCommitWhenCommitInProgress)1616 TEST(SchedulerStateMachineTest, TestFinishCommitWhenCommitInProgress) {
1617   SchedulerSettings default_scheduler_settings;
1618   StateMachine state(default_scheduler_settings);
1619   state.SetCanStart();
1620   state.UpdateState(state.NextAction());
1621   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1622   state.SetVisible(false);
1623   state.SetCommitState(
1624       SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT);
1625   state.SetNeedsCommit();
1626 
1627   state.NotifyBeginMainFrameStarted();
1628   state.NotifyReadyToCommit();
1629   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
1630   state.UpdateState(state.NextAction());
1631 
1632   EXPECT_TRUE(state.active_tree_needs_first_draw());
1633   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
1634 }
1635 
TEST(SchedulerStateMachineTest,TestInitialActionsWhenContextLost)1636 TEST(SchedulerStateMachineTest, TestInitialActionsWhenContextLost) {
1637   SchedulerSettings default_scheduler_settings;
1638   StateMachine state(default_scheduler_settings);
1639   state.SetCanStart();
1640   state.UpdateState(state.NextAction());
1641   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1642   state.SetVisible(true);
1643   state.SetCanDraw(true);
1644   state.SetNeedsCommit();
1645   state.DidLoseOutputSurface();
1646 
1647   // When we are visible, we normally want to begin output surface creation
1648   // as soon as possible.
1649   EXPECT_ACTION_UPDATE_STATE(
1650       SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
1651 
1652   state.DidCreateAndInitializeOutputSurface();
1653   EXPECT_EQ(state.output_surface_state(),
1654             SchedulerStateMachine::OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT);
1655 
1656   // We should not send a BeginMainFrame when we are invisible, even if we've
1657   // lost the output surface and are trying to get the first commit, since the
1658   // main thread will just abort anyway.
1659   state.SetVisible(false);
1660   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction())
1661       << state.AsValue()->ToString();
1662 }
1663 
TEST(SchedulerStateMachineTest,ReportIfNotDrawing)1664 TEST(SchedulerStateMachineTest, ReportIfNotDrawing) {
1665   SchedulerSettings default_scheduler_settings;
1666   StateMachine state(default_scheduler_settings);
1667   state.SetCanStart();
1668   state.UpdateState(state.NextAction());
1669   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1670 
1671   state.SetCanDraw(true);
1672   state.SetVisible(true);
1673   EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
1674 
1675   state.SetCanDraw(false);
1676   state.SetVisible(true);
1677   EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
1678 
1679   state.SetCanDraw(true);
1680   state.SetVisible(false);
1681   EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
1682 
1683   state.SetCanDraw(false);
1684   state.SetVisible(false);
1685   EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
1686 
1687   state.SetCanDraw(true);
1688   state.SetVisible(true);
1689   EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
1690 }
1691 
TEST(SchedulerStateMachineTest,TestTriggerDeadlineEarlyAfterAbortedCommit)1692 TEST(SchedulerStateMachineTest, TestTriggerDeadlineEarlyAfterAbortedCommit) {
1693   SchedulerSettings settings;
1694   settings.impl_side_painting = true;
1695   StateMachine state(settings);
1696   state.SetCanStart();
1697   state.UpdateState(state.NextAction());
1698   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1699   state.SetVisible(true);
1700   state.SetCanDraw(true);
1701 
1702   // This test mirrors what happens during the first frame of a scroll gesture.
1703   // First we get the input event and a BeginFrame.
1704   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1705 
1706   // As a response the compositor requests a redraw and a commit to tell the
1707   // main thread about the new scroll offset.
1708   state.SetNeedsRedraw(true);
1709   state.SetNeedsCommit();
1710 
1711   // We should start the commit normally.
1712   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
1713   EXPECT_ACTION_UPDATE_STATE(
1714       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1715   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1716 
1717   // Since only the scroll offset changed, the main thread will abort the
1718   // commit.
1719   state.BeginMainFrameAborted(true);
1720 
1721   // Since the commit was aborted, we should draw right away instead of waiting
1722   // for the deadline.
1723   EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly());
1724 }
1725 
FinishPreviousCommitAndDrawWithoutExitingDeadline(StateMachine * state_ptr)1726 void FinishPreviousCommitAndDrawWithoutExitingDeadline(
1727     StateMachine* state_ptr) {
1728   // Gross, but allows us to use macros below.
1729   StateMachine& state = *state_ptr;
1730 
1731   state.NotifyBeginMainFrameStarted();
1732   state.NotifyReadyToCommit();
1733   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1734   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1735   state.NotifyReadyToActivate();
1736   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE);
1737   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1738 
1739   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1740   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
1741   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1742 
1743   EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly());
1744   state.OnBeginImplFrameDeadline();
1745   EXPECT_ACTION_UPDATE_STATE(
1746       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
1747   state.DidSwapBuffers();
1748 }
1749 
TEST(SchedulerStateMachineTest,TestImplLatencyTakesPriority)1750 TEST(SchedulerStateMachineTest, TestImplLatencyTakesPriority) {
1751   SchedulerSettings settings;
1752   settings.impl_side_painting = true;
1753   StateMachine state(settings);
1754   state.SetCanStart();
1755   state.UpdateState(state.NextAction());
1756   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1757   state.SetVisible(true);
1758   state.SetCanDraw(true);
1759 
1760   // This test ensures that impl-draws are prioritized over main thread updates
1761   // in prefer impl latency mode.
1762   state.SetNeedsRedraw(true);
1763   state.SetNeedsCommit();
1764   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1765   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
1766   EXPECT_ACTION_UPDATE_STATE(
1767       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1768   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1769 
1770   // Verify the deadline is not triggered early until we enter
1771   // prefer impl latency mode.
1772   EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineEarly());
1773   state.SetImplLatencyTakesPriority(true);
1774   EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly());
1775 
1776   // Trigger the deadline.
1777   state.OnBeginImplFrameDeadline();
1778   EXPECT_ACTION_UPDATE_STATE(
1779       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
1780   state.DidSwapBuffers();
1781   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1782   state.DidSwapBuffersComplete();
1783 
1784   // Request a new commit and finish the previous one.
1785   state.SetNeedsCommit();
1786   FinishPreviousCommitAndDrawWithoutExitingDeadline(&state);
1787   EXPECT_ACTION_UPDATE_STATE(
1788       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1789   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1790   state.DidSwapBuffersComplete();
1791   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1792 
1793   // Finish the previous commit and draw it.
1794   FinishPreviousCommitAndDrawWithoutExitingDeadline(&state);
1795   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1796 
1797   // Verify we do not send another BeginMainFrame if was are swap throttled
1798   // and did not just swap.
1799   state.SetNeedsCommit();
1800   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1801   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1802   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1803   EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineEarly());
1804   state.OnBeginImplFrameDeadline();
1805   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1806 }
1807 
TEST(SchedulerStateMachineTest,TestTriggerDeadlineEarlyOnLostOutputSurface)1808 TEST(SchedulerStateMachineTest, TestTriggerDeadlineEarlyOnLostOutputSurface) {
1809   SchedulerSettings default_scheduler_settings;
1810   StateMachine state(default_scheduler_settings);
1811   state.SetCanStart();
1812   state.UpdateState(state.NextAction());
1813   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1814   state.SetVisible(true);
1815   state.SetCanDraw(true);
1816 
1817   state.SetNeedsCommit();
1818 
1819   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1820   EXPECT_ACTION_UPDATE_STATE(
1821       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1822   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1823   EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineEarly());
1824 
1825   state.DidLoseOutputSurface();
1826   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1827   // The deadline should be triggered immediately when output surface is lost.
1828   EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly());
1829 }
1830 
TEST(SchedulerStateMachineTest,TestSetNeedsAnimate)1831 TEST(SchedulerStateMachineTest, TestSetNeedsAnimate) {
1832   SchedulerSettings settings;
1833   settings.impl_side_painting = true;
1834   StateMachine state(settings);
1835   state.SetCanStart();
1836   state.UpdateState(state.NextAction());
1837   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1838   state.SetVisible(true);
1839   state.SetCanDraw(true);
1840 
1841   // Test requesting an animation that, when run, causes us to draw.
1842   state.SetNeedsAnimate();
1843   EXPECT_TRUE(state.BeginFrameNeeded());
1844   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1845 
1846   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1847   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
1848 
1849   state.OnBeginImplFrameDeadlinePending();
1850   state.OnBeginImplFrameDeadline();
1851   EXPECT_ACTION_UPDATE_STATE(
1852       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
1853 }
1854 
TEST(SchedulerStateMachineTest,TestAnimateBeforeCommit)1855 TEST(SchedulerStateMachineTest, TestAnimateBeforeCommit) {
1856   SchedulerSettings settings;
1857   settings.impl_side_painting = true;
1858   StateMachine state(settings);
1859   state.SetCanStart();
1860   state.UpdateState(state.NextAction());
1861   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1862   state.SetVisible(true);
1863   state.SetCanDraw(true);
1864 
1865   // Check that animations are updated before we start a commit.
1866   state.SetNeedsAnimate();
1867   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1868   state.SetNeedsCommit();
1869   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1870   EXPECT_TRUE(state.BeginFrameNeeded());
1871 
1872   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1873   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
1874   EXPECT_ACTION_UPDATE_STATE(
1875       SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1876 
1877   state.OnBeginImplFrameDeadlinePending();
1878   state.OnBeginImplFrameDeadline();
1879   EXPECT_ACTION_UPDATE_STATE(
1880       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
1881 }
1882 
TEST(SchedulerStateMachineTest,TestSetNeedsAnimateAfterAnimate)1883 TEST(SchedulerStateMachineTest, TestSetNeedsAnimateAfterAnimate) {
1884   SchedulerSettings settings;
1885   settings.impl_side_painting = true;
1886   StateMachine state(settings);
1887   state.SetCanStart();
1888   state.UpdateState(state.NextAction());
1889   state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1890   state.SetVisible(true);
1891   state.SetCanDraw(true);
1892 
1893   // Test requesting an animation after we have already animated during this
1894   // frame.
1895   state.SetNeedsRedraw(true);
1896   EXPECT_TRUE(state.BeginFrameNeeded());
1897   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1898 
1899   state.OnBeginImplFrame(CreateBeginFrameArgsForTesting());
1900   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE);
1901 
1902   state.SetNeedsAnimate();
1903   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1904 
1905   state.OnBeginImplFrameDeadline();
1906   EXPECT_ACTION_UPDATE_STATE(
1907       SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
1908 }
1909 
1910 }  // namespace
1911 }  // namespace cc
1912