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