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