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
30namespace cc {
31
32namespace {
33
34const 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
40const 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
49class StateMachine : public SchedulerStateMachine {
50 public:
51  explicit StateMachine(const SchedulerSettings& scheduler_settings)
52      : SchedulerStateMachine(scheduler_settings) {}
53
54  void CreateAndInitializeOutputSurfaceWithActivatedCommit() {
55    DidCreateAndInitializeOutputSurface();
56    output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
57  }
58
59  void SetCommitState(CommitState cs) { commit_state_ = cs; }
60  CommitState CommitState() const { return commit_state_; }
61
62  ForcedRedrawOnTimeoutState ForcedRedrawState() const {
63    return forced_redraw_state_;
64  }
65
66  void SetBeginImplFrameState(BeginImplFrameState bifs) {
67    begin_impl_frame_state_ = bifs;
68  }
69
70  BeginImplFrameState begin_impl_frame_state() const {
71    return begin_impl_frame_state_;
72  }
73
74  OutputSurfaceState output_surface_state() const {
75    return output_surface_state_;
76  }
77
78  bool NeedsCommit() const { return needs_commit_; }
79
80  void SetNeedsRedraw(bool b) { needs_redraw_ = b; }
81
82  void SetNeedsForcedRedrawForTimeout(bool b) {
83    forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT;
84    active_tree_needs_first_draw_ = true;
85  }
86  bool NeedsForcedRedrawForTimeout() const {
87    return forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE;
88  }
89
90  void SetActiveTreeNeedsFirstDraw(bool needs_first_draw) {
91    active_tree_needs_first_draw_ = needs_first_draw;
92  }
93
94  bool CanDraw() const { return can_draw_; }
95  bool Visible() const { return visible_; }
96
97  bool PendingActivationsShouldBeForced() const {
98    return SchedulerStateMachine::PendingActivationsShouldBeForced();
99  }
100
101  void SetHasPendingTree(bool has_pending_tree) {
102    has_pending_tree_ = has_pending_tree;
103  }
104};
105
106TEST(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
180TEST(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
264TEST(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
326TEST(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
363TEST(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
396TEST(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
437void 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
497TEST(SchedulerStateMachineTest,
498     TestFailedDrawsEventuallyForceDrawAfterNextCommit) {
499  bool main_frame_before_draw_enabled = false;
500  TestFailedDrawsEventuallyForceDrawAfterNextCommit(
501      main_frame_before_draw_enabled);
502}
503
504TEST(SchedulerStateMachineTest,
505     TestFailedDrawsEventuallyForceDrawAfterNextCommit_CommitBeforeDraw) {
506  bool main_frame_before_draw_enabled = true;
507  TestFailedDrawsEventuallyForceDrawAfterNextCommit(
508      main_frame_before_draw_enabled);
509}
510
511TEST(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
572TEST(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
615TEST(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
663TEST(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
735TEST(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
768TEST(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
793TEST(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
819void 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
900TEST(SchedulerStateMachineTest, TestSetNeedsCommitIsNotLost) {
901  bool main_frame_before_draw_enabled = false;
902  TestSetNeedsCommitIsNotLost(main_frame_before_draw_enabled);
903}
904
905TEST(SchedulerStateMachineTest, TestSetNeedsCommitIsNotLost_CommitBeforeDraw) {
906  bool main_frame_before_draw_enabled = true;
907  TestSetNeedsCommitIsNotLost(main_frame_before_draw_enabled);
908}
909
910TEST(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
960TEST(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
1019TEST(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
1029TEST(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
1082TEST(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
1132TEST(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
1186TEST(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
1234TEST(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
1278TEST(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
1303TEST(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
1333TEST(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
1399TEST(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
1464TEST(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
1553TEST(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
1577TEST(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
1605TEST(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
1616TEST(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
1636TEST(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
1664TEST(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
1692TEST(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
1726void 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
1750TEST(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
1808TEST(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
1831TEST(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
1855TEST(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
1883TEST(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