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 namespace cc {
     11 
     12 namespace {
     13 
     14 const SchedulerStateMachine::CommitState all_commit_states[] = {
     15   SchedulerStateMachine::COMMIT_STATE_IDLE,
     16   SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
     17   SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
     18   SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW
     19 };
     20 
     21 // Exposes the protected state fields of the SchedulerStateMachine for testing
     22 class StateMachine : public SchedulerStateMachine {
     23  public:
     24   explicit StateMachine(const SchedulerSettings& scheduler_settings)
     25       : SchedulerStateMachine(scheduler_settings) {}
     26   void SetCommitState(CommitState cs) { commit_state_ = cs; }
     27   CommitState CommitState() const { return commit_state_; }
     28 
     29   bool NeedsCommit() const { return needs_commit_; }
     30 
     31   void SetNeedsRedraw(bool b) { needs_redraw_ = b; }
     32   bool NeedsRedraw() const { return needs_redraw_; }
     33 
     34   void SetNeedsForcedRedraw(bool b) { needs_forced_redraw_ = b; }
     35   bool NeedsForcedRedraw() const { return needs_forced_redraw_; }
     36 
     37   bool CanDraw() const { return can_draw_; }
     38   bool Visible() const { return visible_; }
     39 };
     40 
     41 TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) {
     42   SchedulerSettings default_scheduler_settings;
     43 
     44   // If no commit needed, do nothing.
     45   {
     46     StateMachine state(default_scheduler_settings);
     47     state.SetCanStart();
     48     state.UpdateState(state.NextAction());
     49     state.DidCreateAndInitializeOutputSurface();
     50     state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
     51     state.SetNeedsRedraw(false);
     52     state.SetVisible(true);
     53 
     54     EXPECT_FALSE(state.BeginFrameNeededToDrawByImplThread());
     55 
     56     state.DidLeaveBeginFrame();
     57     EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
     58     EXPECT_FALSE(state.BeginFrameNeededToDrawByImplThread());
     59     state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
     60     EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
     61   }
     62 
     63   // If commit requested but can_start is still false, do nothing.
     64   {
     65     StateMachine state(default_scheduler_settings);
     66     state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
     67     state.SetNeedsRedraw(false);
     68     state.SetVisible(true);
     69 
     70     EXPECT_FALSE(state.BeginFrameNeededToDrawByImplThread());
     71 
     72     state.DidLeaveBeginFrame();
     73     EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
     74     EXPECT_FALSE(state.BeginFrameNeededToDrawByImplThread());
     75     state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
     76     EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
     77   }
     78 
     79   // If commit requested, begin a main frame.
     80   {
     81     StateMachine state(default_scheduler_settings);
     82     state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
     83     state.SetCanStart();
     84     state.SetNeedsRedraw(false);
     85     state.SetVisible(true);
     86     EXPECT_FALSE(state.BeginFrameNeededToDrawByImplThread());
     87   }
     88 
     89   // Begin the frame, make sure needs_commit and commit_state update correctly.
     90   {
     91     StateMachine state(default_scheduler_settings);
     92     state.SetCanStart();
     93     state.UpdateState(state.NextAction());
     94     state.DidCreateAndInitializeOutputSurface();
     95     state.SetVisible(true);
     96     state.UpdateState(
     97         SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
     98     EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
     99               state.CommitState());
    100     EXPECT_FALSE(state.NeedsCommit());
    101     EXPECT_FALSE(state.BeginFrameNeededToDrawByImplThread());
    102   }
    103 }
    104 
    105 TEST(SchedulerStateMachineTest, TestSetForcedRedrawDoesNotSetsNormalRedraw) {
    106   SchedulerSettings default_scheduler_settings;
    107   SchedulerStateMachine state(default_scheduler_settings);
    108   state.SetCanDraw(true);
    109   state.SetNeedsForcedRedraw();
    110   EXPECT_FALSE(state.RedrawPending());
    111   EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread());
    112 }
    113 
    114 TEST(SchedulerStateMachineTest,
    115      TestFailedDrawSetsNeedsCommitAndDoesNotDrawAgain) {
    116   SchedulerSettings default_scheduler_settings;
    117   SchedulerStateMachine state(default_scheduler_settings);
    118   state.SetCanStart();
    119   state.UpdateState(state.NextAction());
    120   state.DidCreateAndInitializeOutputSurface();
    121   state.SetVisible(true);
    122   state.SetCanDraw(true);
    123   state.SetNeedsRedraw();
    124   EXPECT_TRUE(state.RedrawPending());
    125   EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread());
    126   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    127 
    128   // We're drawing now.
    129   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    130   state.UpdateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
    131   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    132   EXPECT_FALSE(state.RedrawPending());
    133   EXPECT_FALSE(state.CommitPending());
    134 
    135   // Failing the draw makes us require a commit.
    136   state.DidDrawIfPossibleCompleted(false);
    137   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    138       state.NextAction());
    139   state.UpdateState(
    140       SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
    141   EXPECT_TRUE(state.RedrawPending());
    142   EXPECT_TRUE(state.CommitPending());
    143 }
    144 
    145 TEST(SchedulerStateMachineTest,
    146      TestsetNeedsRedrawDuringFailedDrawDoesNotRemoveNeedsRedraw) {
    147   SchedulerSettings default_scheduler_settings;
    148   SchedulerStateMachine state(default_scheduler_settings);
    149   state.SetCanStart();
    150   state.UpdateState(state.NextAction());
    151   state.DidCreateAndInitializeOutputSurface();
    152 
    153   state.SetVisible(true);
    154   state.SetCanDraw(true);
    155   state.SetNeedsRedraw();
    156   EXPECT_TRUE(state.RedrawPending());
    157   EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread());
    158   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    159 
    160   // We're drawing now.
    161   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    162   state.UpdateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
    163   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    164   EXPECT_FALSE(state.RedrawPending());
    165   EXPECT_FALSE(state.CommitPending());
    166 
    167   // While still in the same begin frame callback on the main thread,
    168   // set needs redraw again. This should not redraw.
    169   state.SetNeedsRedraw();
    170   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    171 
    172   // Failing the draw makes us require a commit.
    173   state.DidDrawIfPossibleCompleted(false);
    174   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    175             state.NextAction());
    176   EXPECT_TRUE(state.RedrawPending());
    177 }
    178 
    179 TEST(SchedulerStateMachineTest,
    180      TestCommitAfterFailedDrawAllowsDrawInSameFrame) {
    181   SchedulerSettings default_scheduler_settings;
    182   SchedulerStateMachine state(default_scheduler_settings);
    183   state.SetCanStart();
    184   state.UpdateState(state.NextAction());
    185   state.DidCreateAndInitializeOutputSurface();
    186   state.SetVisible(true);
    187   state.SetCanDraw(true);
    188 
    189   // Start a commit.
    190   state.SetNeedsCommit();
    191   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    192             state.NextAction());
    193   state.UpdateState(
    194       SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
    195   EXPECT_TRUE(state.CommitPending());
    196 
    197   // Then initiate a draw.
    198   state.SetNeedsRedraw();
    199   EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread());
    200   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    201   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    202   EXPECT_TRUE(state.RedrawPending());
    203 
    204   // Fail the draw.
    205   state.UpdateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
    206   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    207   state.DidDrawIfPossibleCompleted(false);
    208   EXPECT_TRUE(state.RedrawPending());
    209   // But the commit is ongoing.
    210   EXPECT_TRUE(state.CommitPending());
    211 
    212   // Finish the commit.
    213   state.FinishCommit();
    214   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
    215   state.UpdateState(SchedulerStateMachine::ACTION_COMMIT);
    216   EXPECT_TRUE(state.RedrawPending());
    217 
    218   // And we should be allowed to draw again.
    219   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    220 }
    221 
    222 TEST(SchedulerStateMachineTest,
    223      TestCommitAfterFailedAndSuccessfulDrawDoesNotAllowDrawInSameFrame) {
    224   SchedulerSettings default_scheduler_settings;
    225   SchedulerStateMachine state(default_scheduler_settings);
    226   state.SetCanStart();
    227   state.UpdateState(state.NextAction());
    228   state.DidCreateAndInitializeOutputSurface();
    229   state.SetVisible(true);
    230   state.SetCanDraw(true);
    231 
    232   // Start a commit.
    233   state.SetNeedsCommit();
    234   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    235             state.NextAction());
    236   state.UpdateState(
    237       SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
    238   EXPECT_TRUE(state.CommitPending());
    239 
    240   // Then initiate a draw.
    241   state.SetNeedsRedraw();
    242   EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread());
    243   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    244   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    245   EXPECT_TRUE(state.RedrawPending());
    246 
    247   // Fail the draw.
    248   state.UpdateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
    249   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    250   state.DidDrawIfPossibleCompleted(false);
    251   EXPECT_TRUE(state.RedrawPending());
    252   // But the commit is ongoing.
    253   EXPECT_TRUE(state.CommitPending());
    254 
    255   // Force a draw.
    256   state.SetNeedsForcedRedraw();
    257   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_FORCED, state.NextAction());
    258 
    259   // Do the forced draw.
    260   state.UpdateState(SchedulerStateMachine::ACTION_DRAW_FORCED);
    261   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    262   EXPECT_FALSE(state.RedrawPending());
    263   // And the commit is still ongoing.
    264   EXPECT_TRUE(state.CommitPending());
    265 
    266   // Finish the commit.
    267   state.FinishCommit();
    268   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
    269   state.UpdateState(SchedulerStateMachine::ACTION_COMMIT);
    270   EXPECT_TRUE(state.RedrawPending());
    271 
    272   // And we should not be allowed to draw again in the same frame..
    273   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    274 }
    275 
    276 TEST(SchedulerStateMachineTest,
    277      TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit) {
    278   SchedulerSettings default_scheduler_settings;
    279   SchedulerStateMachine state(default_scheduler_settings);
    280   state.SetCanStart();
    281   state.UpdateState(state.NextAction());
    282   state.DidCreateAndInitializeOutputSurface();
    283   state.SetVisible(true);
    284   state.SetCanDraw(true);
    285   state.SetMaximumNumberOfFailedDrawsBeforeDrawIsForced(1);
    286 
    287   // Start a commit.
    288   state.SetNeedsCommit();
    289   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    290             state.NextAction());
    291   state.UpdateState(
    292       SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
    293   EXPECT_TRUE(state.CommitPending());
    294 
    295   // Then initiate a draw.
    296   state.SetNeedsRedraw();
    297   EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread());
    298   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    299   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    300   EXPECT_TRUE(state.RedrawPending());
    301 
    302   // Fail the draw.
    303   state.UpdateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
    304   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    305   state.DidDrawIfPossibleCompleted(false);
    306   EXPECT_TRUE(state.RedrawPending());
    307   // But the commit is ongoing.
    308   EXPECT_TRUE(state.CommitPending());
    309 
    310   // Finish the commit. Note, we should not yet be forcing a draw, but should
    311   // continue the commit as usual.
    312   state.FinishCommit();
    313   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
    314   state.UpdateState(SchedulerStateMachine::ACTION_COMMIT);
    315   EXPECT_TRUE(state.RedrawPending());
    316 
    317   // The redraw should be forced in this case.
    318   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_FORCED, state.NextAction());
    319 }
    320 
    321 TEST(SchedulerStateMachineTest,
    322     TestFailedDrawIsRetriedInNextBeginFrameForImplThread) {
    323   SchedulerSettings default_scheduler_settings;
    324   SchedulerStateMachine state(default_scheduler_settings);
    325   state.SetCanStart();
    326   state.UpdateState(state.NextAction());
    327   state.DidCreateAndInitializeOutputSurface();
    328   state.SetVisible(true);
    329   state.SetCanDraw(true);
    330 
    331   // Start a draw.
    332   state.SetNeedsRedraw();
    333   EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread());
    334   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    335   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    336   EXPECT_TRUE(state.RedrawPending());
    337 
    338   // Fail the draw.
    339   state.UpdateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
    340   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    341   state.DidDrawIfPossibleCompleted(false);
    342   EXPECT_TRUE(state.RedrawPending());
    343 
    344   // We should not be trying to draw again now, but we have a commit pending.
    345   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    346             state.NextAction());
    347 
    348   state.DidLeaveBeginFrame();
    349   EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread());
    350   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    351 
    352   // We should try to draw again in the next begin frame on the impl thread.
    353   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    354 }
    355 
    356 TEST(SchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame) {
    357   SchedulerSettings default_scheduler_settings;
    358   SchedulerStateMachine state(default_scheduler_settings);
    359   state.SetCanStart();
    360   state.UpdateState(state.NextAction());
    361   state.DidCreateAndInitializeOutputSurface();
    362   state.SetVisible(true);
    363   state.SetCanDraw(true);
    364   state.SetNeedsRedraw();
    365   EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread());
    366   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    367   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    368   state.UpdateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
    369 
    370   // While still in the same begin frame for the impl thread, set needs redraw
    371   // again. This should not redraw.
    372   state.SetNeedsRedraw();
    373   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    374 
    375   // Move to another frame. This should now draw.
    376   state.DidDrawIfPossibleCompleted(true);
    377   state.DidLeaveBeginFrame();
    378   EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread());
    379   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    380 
    381   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    382   state.UpdateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
    383   state.DidDrawIfPossibleCompleted(true);
    384   EXPECT_FALSE(state.BeginFrameNeededToDrawByImplThread());
    385 }
    386 
    387 TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginFrame) {
    388   SchedulerSettings default_scheduler_settings;
    389 
    390   // When not in BeginFrame, or in BeginFrame but not visible,
    391   // don't draw.
    392   size_t num_commit_states =
    393       sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
    394   for (size_t i = 0; i < num_commit_states; ++i) {
    395     for (size_t j = 0; j < 2; ++j) {
    396       StateMachine state(default_scheduler_settings);
    397       state.SetCanStart();
    398       state.UpdateState(state.NextAction());
    399       state.DidCreateAndInitializeOutputSurface();
    400       state.SetCommitState(all_commit_states[i]);
    401       bool visible = j;
    402       if (!visible) {
    403         state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    404         state.SetVisible(false);
    405       } else {
    406         state.SetVisible(true);
    407       }
    408 
    409       // Case 1: needs_commit=false
    410       EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE,
    411                 state.NextAction());
    412 
    413       // Case 2: needs_commit=true
    414       state.SetNeedsCommit();
    415       EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE,
    416                 state.NextAction());
    417     }
    418   }
    419 
    420   // When in BeginFrame, or not in BeginFrame but needs_forced_dedraw
    421   // set, should always draw except if you're ready to commit, in which case
    422   // commit.
    423   for (size_t i = 0; i < num_commit_states; ++i) {
    424     for (size_t j = 0; j < 2; ++j) {
    425       StateMachine state(default_scheduler_settings);
    426       state.SetCanStart();
    427       state.UpdateState(state.NextAction());
    428       state.DidCreateAndInitializeOutputSurface();
    429       state.SetCanDraw(true);
    430       state.SetCommitState(all_commit_states[i]);
    431       bool forced_draw = j;
    432       if (!forced_draw) {
    433         state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    434         state.SetNeedsRedraw(true);
    435         state.SetVisible(true);
    436       } else {
    437         state.SetNeedsForcedRedraw(true);
    438       }
    439 
    440       SchedulerStateMachine::Action expected_action;
    441       if (all_commit_states[i] !=
    442           SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT) {
    443         expected_action =
    444             forced_draw ? SchedulerStateMachine::ACTION_DRAW_FORCED
    445                         : SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE;
    446       } else {
    447         expected_action = SchedulerStateMachine::ACTION_COMMIT;
    448       }
    449 
    450       // Case 1: needs_commit=false.
    451       EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread());
    452       EXPECT_EQ(expected_action, state.NextAction());
    453 
    454       // Case 2: needs_commit=true.
    455       state.SetNeedsCommit();
    456       EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread());
    457       EXPECT_EQ(expected_action, state.NextAction());
    458     }
    459   }
    460 }
    461 
    462 TEST(SchedulerStateMachineTest, TestNoCommitStatesRedrawWhenInvisible) {
    463   SchedulerSettings default_scheduler_settings;
    464 
    465   size_t num_commit_states =
    466       sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
    467   for (size_t i = 0; i < num_commit_states; ++i) {
    468     // There shouldn't be any drawing regardless of BeginFrame.
    469     for (size_t j = 0; j < 2; ++j) {
    470       StateMachine state(default_scheduler_settings);
    471       state.SetCanStart();
    472       state.UpdateState(state.NextAction());
    473       state.DidCreateAndInitializeOutputSurface();
    474       state.SetCommitState(all_commit_states[i]);
    475       state.SetVisible(false);
    476       state.SetNeedsRedraw(true);
    477       state.SetNeedsForcedRedraw(false);
    478       if (j == 1)
    479         state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    480 
    481       // Case 1: needs_commit=false.
    482       EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE,
    483                 state.NextAction());
    484 
    485       // Case 2: needs_commit=true.
    486       state.SetNeedsCommit();
    487       EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE,
    488                 state.NextAction());
    489     }
    490   }
    491 }
    492 
    493 TEST(SchedulerStateMachineTest, TestCanRedraw_StopsDraw) {
    494   SchedulerSettings default_scheduler_settings;
    495 
    496   size_t num_commit_states =
    497       sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
    498   for (size_t i = 0; i < num_commit_states; ++i) {
    499     // There shouldn't be any drawing regardless of BeginFrame.
    500     for (size_t j = 0; j < 2; ++j) {
    501       StateMachine state(default_scheduler_settings);
    502       state.SetCanStart();
    503       state.UpdateState(state.NextAction());
    504       state.DidCreateAndInitializeOutputSurface();
    505       state.SetCommitState(all_commit_states[i]);
    506       state.SetVisible(false);
    507       state.SetNeedsRedraw(true);
    508       state.SetNeedsForcedRedraw(false);
    509       if (j == 1)
    510         state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    511 
    512       state.SetCanDraw(false);
    513       EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE,
    514                 state.NextAction());
    515     }
    516   }
    517 }
    518 
    519 TEST(SchedulerStateMachineTest,
    520      TestCanRedrawWithWaitingForFirstDrawMakesProgress) {
    521   SchedulerSettings default_scheduler_settings;
    522   StateMachine state(default_scheduler_settings);
    523   state.SetCanStart();
    524   state.UpdateState(state.NextAction());
    525   state.DidCreateAndInitializeOutputSurface();
    526   state.SetCommitState(
    527       SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
    528   state.SetNeedsCommit();
    529   state.SetNeedsRedraw(true);
    530   state.SetVisible(true);
    531   state.SetCanDraw(false);
    532   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    533             state.NextAction());
    534 }
    535 
    536 TEST(SchedulerStateMachineTest, TestsetNeedsCommitIsNotLost) {
    537   SchedulerSettings default_scheduler_settings;
    538   StateMachine state(default_scheduler_settings);
    539   state.SetCanStart();
    540   state.UpdateState(state.NextAction());
    541   state.DidCreateAndInitializeOutputSurface();
    542   state.SetNeedsCommit();
    543   state.SetVisible(true);
    544   state.SetCanDraw(true);
    545 
    546   // Begin the frame.
    547   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    548             state.NextAction());
    549   state.UpdateState(state.NextAction());
    550   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
    551             state.CommitState());
    552 
    553   // Now, while the frame is in progress, set another commit.
    554   state.SetNeedsCommit();
    555   EXPECT_TRUE(state.NeedsCommit());
    556 
    557   // Let the frame finish.
    558   state.FinishCommit();
    559   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
    560             state.CommitState());
    561 
    562   // Expect to commit regardless of BeginFrame state.
    563   state.DidLeaveBeginFrame();
    564   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
    565   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    566   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
    567 
    568   // Commit and make sure we draw on next BeginFrame
    569   state.UpdateState(SchedulerStateMachine::ACTION_COMMIT);
    570   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    571   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
    572             state.CommitState());
    573   state.UpdateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
    574   state.DidDrawIfPossibleCompleted(true);
    575 
    576   // Verify that another commit will begin.
    577   state.DidLeaveBeginFrame();
    578   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    579             state.NextAction());
    580 }
    581 
    582 TEST(SchedulerStateMachineTest, TestFullCycle) {
    583   SchedulerSettings default_scheduler_settings;
    584   StateMachine state(default_scheduler_settings);
    585   state.SetCanStart();
    586   state.UpdateState(state.NextAction());
    587   state.DidCreateAndInitializeOutputSurface();
    588   state.SetVisible(true);
    589   state.SetCanDraw(true);
    590 
    591   // Start clean and set commit.
    592   state.SetNeedsCommit();
    593   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    594             state.NextAction());
    595 
    596   // Begin the frame.
    597   state.UpdateState(
    598       SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
    599   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
    600             state.CommitState());
    601   EXPECT_FALSE(state.NeedsCommit());
    602   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    603 
    604   // Tell the scheduler the frame finished.
    605   state.FinishCommit();
    606   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
    607             state.CommitState());
    608   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
    609 
    610   // Commit.
    611   state.UpdateState(SchedulerStateMachine::ACTION_COMMIT);
    612   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
    613             state.CommitState());
    614   EXPECT_TRUE(state.NeedsRedraw());
    615 
    616   // Expect to do nothing until BeginFrame.
    617   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    618 
    619   // At BeginFrame, draw.
    620   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    621   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    622   state.UpdateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
    623   state.DidDrawIfPossibleCompleted(true);
    624   state.DidLeaveBeginFrame();
    625 
    626   // Should be synchronized, no draw needed, no action needed.
    627   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
    628   EXPECT_FALSE(state.NeedsRedraw());
    629   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    630 }
    631 
    632 TEST(SchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween) {
    633   SchedulerSettings default_scheduler_settings;
    634   StateMachine state(default_scheduler_settings);
    635   state.SetCanStart();
    636   state.UpdateState(state.NextAction());
    637   state.DidCreateAndInitializeOutputSurface();
    638   state.SetVisible(true);
    639   state.SetCanDraw(true);
    640 
    641   // Start clean and set commit.
    642   state.SetNeedsCommit();
    643   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    644             state.NextAction());
    645 
    646   // Begin the frame.
    647   state.UpdateState(
    648       SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
    649   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
    650             state.CommitState());
    651   EXPECT_FALSE(state.NeedsCommit());
    652   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    653 
    654   // Request another commit while the commit is in flight.
    655   state.SetNeedsCommit();
    656   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    657 
    658   // Tell the scheduler the frame finished.
    659   state.FinishCommit();
    660   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
    661             state.CommitState());
    662   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
    663 
    664   // Commit.
    665   state.UpdateState(SchedulerStateMachine::ACTION_COMMIT);
    666   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
    667             state.CommitState());
    668   EXPECT_TRUE(state.NeedsRedraw());
    669 
    670   // Expect to do nothing until BeginFrame.
    671   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    672 
    673   // At BeginFrame, draw.
    674   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    675   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    676   state.UpdateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE);
    677   state.DidDrawIfPossibleCompleted(true);
    678   state.DidLeaveBeginFrame();
    679 
    680   // Should be synchronized, no draw needed, no action needed.
    681   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
    682   EXPECT_FALSE(state.NeedsRedraw());
    683   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    684             state.NextAction());
    685 }
    686 
    687 TEST(SchedulerStateMachineTest, TestRequestCommitInvisible) {
    688   SchedulerSettings default_scheduler_settings;
    689   StateMachine state(default_scheduler_settings);
    690   state.SetCanStart();
    691   state.UpdateState(state.NextAction());
    692   state.DidCreateAndInitializeOutputSurface();
    693   state.SetNeedsCommit();
    694   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    695 }
    696 
    697 TEST(SchedulerStateMachineTest, TestGoesInvisibleBeforeFinishCommit) {
    698   SchedulerSettings default_scheduler_settings;
    699   StateMachine state(default_scheduler_settings);
    700   state.SetCanStart();
    701   state.UpdateState(state.NextAction());
    702   state.DidCreateAndInitializeOutputSurface();
    703   state.SetVisible(true);
    704   state.SetCanDraw(true);
    705 
    706   // Start clean and set commit.
    707   state.SetNeedsCommit();
    708   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    709             state.NextAction());
    710 
    711   // Begin the frame while visible.
    712   state.UpdateState(
    713       SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
    714   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
    715             state.CommitState());
    716   EXPECT_FALSE(state.NeedsCommit());
    717   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    718 
    719   // Become invisible and abort the main thread's begin frame.
    720   state.SetVisible(false);
    721   state.BeginFrameAbortedByMainThread(false);
    722 
    723   // We should now be back in the idle state as if we didn't start a frame at
    724   // all.
    725   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
    726   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    727 
    728   // Become visible again.
    729   state.SetVisible(true);
    730 
    731   // Although we have aborted on this frame and haven't cancelled the commit
    732   // (i.e. need another), don't send another begin frame yet.
    733   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
    734   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    735   EXPECT_TRUE(state.NeedsCommit());
    736 
    737   // Start a new frame.
    738   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    739   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    740             state.NextAction());
    741 
    742   // Begin the frame.
    743   state.UpdateState(state.NextAction());
    744 
    745   // We should be starting the commit now.
    746   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
    747             state.CommitState());
    748 }
    749 
    750 TEST(SchedulerStateMachineTest, AbortBeginFrameAndCancelCommit) {
    751   SchedulerSettings default_scheduler_settings;
    752   StateMachine state(default_scheduler_settings);
    753   state.SetCanStart();
    754   state.UpdateState(state.NextAction());
    755   state.DidCreateAndInitializeOutputSurface();
    756   state.SetVisible(true);
    757   state.SetCanDraw(true);
    758 
    759   // Get into a begin frame / commit state.
    760   state.SetNeedsCommit();
    761   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    762             state.NextAction());
    763   state.UpdateState(
    764       SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD);
    765   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
    766             state.CommitState());
    767   EXPECT_FALSE(state.NeedsCommit());
    768   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    769 
    770   // Abort the commit, cancelling future commits.
    771   state.BeginFrameAbortedByMainThread(true);
    772 
    773   // Verify that another commit doesn't start on the same frame.
    774   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
    775   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    776   EXPECT_FALSE(state.NeedsCommit());
    777 
    778   // Start a new frame; draw because this is the first frame since output
    779   // surface init'd.
    780   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    781   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    782   state.DidLeaveBeginFrame();
    783 
    784   // Verify another commit doesn't start on another frame either.
    785   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
    786   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    787   EXPECT_FALSE(state.NeedsCommit());
    788 
    789   // Verify another commit can start if requested, though.
    790   state.SetNeedsCommit();
    791   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
    792   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    793             state.NextAction());
    794 }
    795 
    796 TEST(SchedulerStateMachineTest, TestFirstContextCreation) {
    797   SchedulerSettings default_scheduler_settings;
    798   StateMachine state(default_scheduler_settings);
    799   state.SetCanStart();
    800   state.SetVisible(true);
    801   state.SetCanDraw(true);
    802 
    803   EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
    804             state.NextAction());
    805   state.UpdateState(state.NextAction());
    806   state.DidCreateAndInitializeOutputSurface();
    807   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    808 
    809   // Check that the first init does not SetNeedsCommit.
    810   state.SetNeedsCommit();
    811   EXPECT_NE(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    812 }
    813 
    814 TEST(SchedulerStateMachineTest, TestContextLostWhenCompletelyIdle) {
    815   SchedulerSettings default_scheduler_settings;
    816   StateMachine state(default_scheduler_settings);
    817   state.SetCanStart();
    818   state.UpdateState(state.NextAction());
    819   state.DidCreateAndInitializeOutputSurface();
    820 
    821   state.SetVisible(true);
    822   state.SetCanDraw(true);
    823 
    824   EXPECT_NE(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
    825             state.NextAction());
    826   state.DidLoseOutputSurface();
    827 
    828   EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
    829             state.NextAction());
    830   state.UpdateState(state.NextAction());
    831 
    832   // Once context recreation begins, nothing should happen.
    833   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    834 
    835   // Recreate the context.
    836   state.DidCreateAndInitializeOutputSurface();
    837 
    838   // When the context is recreated, we should begin a commit.
    839   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    840             state.NextAction());
    841   state.UpdateState(state.NextAction());
    842 }
    843 
    844 TEST(SchedulerStateMachineTest,
    845      TestContextLostWhenIdleAndCommitRequestedWhileRecreating) {
    846   SchedulerSettings default_scheduler_settings;
    847   StateMachine state(default_scheduler_settings);
    848   state.SetCanStart();
    849   state.UpdateState(state.NextAction());
    850   state.DidCreateAndInitializeOutputSurface();
    851   state.SetVisible(true);
    852   state.SetCanDraw(true);
    853 
    854   EXPECT_NE(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
    855             state.NextAction());
    856   state.DidLoseOutputSurface();
    857 
    858   EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
    859             state.NextAction());
    860   state.UpdateState(state.NextAction());
    861 
    862   // Once context recreation begins, nothing should happen.
    863   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    864 
    865   // While context is recreating, commits shouldn't begin.
    866   state.SetNeedsCommit();
    867   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    868 
    869   // Recreate the context
    870   state.DidCreateAndInitializeOutputSurface();
    871   EXPECT_FALSE(state.RedrawPending());
    872 
    873   // When the context is recreated, we should begin a commit
    874   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    875             state.NextAction());
    876   state.UpdateState(state.NextAction());
    877   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
    878             state.CommitState());
    879   state.FinishCommit();
    880   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
    881   state.UpdateState(state.NextAction());
    882   // Finishing the first commit after initializing an output surface should
    883   // automatically cause a redraw.
    884   EXPECT_TRUE(state.RedrawPending());
    885 
    886   // Once the context is recreated, whether we draw should be based on
    887   // SetCanDraw.
    888   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    889   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    890   state.SetCanDraw(false);
    891   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    892   state.SetCanDraw(true);
    893   state.DidLeaveBeginFrame();
    894 }
    895 
    896 TEST(SchedulerStateMachineTest, TestContextLostWhileCommitInProgress) {
    897   SchedulerSettings default_scheduler_settings;
    898   StateMachine state(default_scheduler_settings);
    899   state.SetCanStart();
    900   state.UpdateState(state.NextAction());
    901   state.DidCreateAndInitializeOutputSurface();
    902   state.SetVisible(true);
    903   state.SetCanDraw(true);
    904 
    905   // Get a commit in flight.
    906   state.SetNeedsCommit();
    907   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    908             state.NextAction());
    909   state.UpdateState(state.NextAction());
    910 
    911   // Set damage and expect a draw.
    912   state.SetNeedsRedraw(true);
    913   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    914   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    915   state.UpdateState(state.NextAction());
    916   state.DidLeaveBeginFrame();
    917 
    918   // Cause a lost context while the begin frame is in flight
    919   // for the main thread.
    920   state.DidLoseOutputSurface();
    921 
    922   // Ask for another draw. Expect nothing happens.
    923   state.SetNeedsRedraw(true);
    924   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    925 
    926   // Finish the frame, and commit.
    927   state.FinishCommit();
    928   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
    929   state.UpdateState(state.NextAction());
    930 
    931   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
    932             state.CommitState());
    933 
    934   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    935   state.UpdateState(state.NextAction());
    936 
    937   // Expect to be told to begin context recreation, independent of
    938   // BeginFrame state.
    939   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    940   EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
    941             state.NextAction());
    942   state.DidLeaveBeginFrame();
    943   EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
    944             state.NextAction());
    945 }
    946 
    947 TEST(SchedulerStateMachineTest,
    948      TestContextLostWhileCommitInProgressAndAnotherCommitRequested) {
    949   SchedulerSettings default_scheduler_settings;
    950   StateMachine state(default_scheduler_settings);
    951   state.SetCanStart();
    952   state.UpdateState(state.NextAction());
    953   state.DidCreateAndInitializeOutputSurface();
    954   state.SetVisible(true);
    955   state.SetCanDraw(true);
    956 
    957   // Get a commit in flight.
    958   state.SetNeedsCommit();
    959   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
    960             state.NextAction());
    961   state.UpdateState(state.NextAction());
    962 
    963   // Set damage and expect a draw.
    964   state.SetNeedsRedraw(true);
    965   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    966   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    967   state.UpdateState(state.NextAction());
    968   state.DidLeaveBeginFrame();
    969 
    970   // Cause a lost context while the begin frame is in flight
    971   // for the main thread.
    972   state.DidLoseOutputSurface();
    973 
    974   // Ask for another draw and also set needs commit. Expect nothing happens.
    975   state.SetNeedsRedraw(true);
    976   state.SetNeedsCommit();
    977   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
    978 
    979   // Finish the frame, and commit.
    980   state.FinishCommit();
    981   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
    982   state.UpdateState(state.NextAction());
    983 
    984   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
    985             state.CommitState());
    986 
    987   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction());
    988   state.UpdateState(state.NextAction());
    989 
    990   // Expect to be told to begin context recreation, independent of
    991   // BeginFrame state
    992   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
    993   EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
    994             state.NextAction());
    995   state.DidLeaveBeginFrame();
    996   EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
    997             state.NextAction());
    998 }
    999 
   1000 TEST(SchedulerStateMachineTest, TestFinishAllRenderingWhileContextLost) {
   1001   SchedulerSettings default_scheduler_settings;
   1002   StateMachine state(default_scheduler_settings);
   1003   state.SetCanStart();
   1004   state.UpdateState(state.NextAction());
   1005   state.DidCreateAndInitializeOutputSurface();
   1006   state.SetVisible(true);
   1007   state.SetCanDraw(true);
   1008 
   1009   // Cause a lost context lost.
   1010   state.DidLoseOutputSurface();
   1011 
   1012   // Ask a forced redraw and verify it ocurrs.
   1013   state.SetNeedsForcedRedraw(true);
   1014   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
   1015   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_FORCED, state.NextAction());
   1016   state.DidLeaveBeginFrame();
   1017 
   1018   // Clear the forced redraw bit.
   1019   state.SetNeedsForcedRedraw(false);
   1020 
   1021   // Expect to be told to begin context recreation, independent of
   1022   // BeginFrame state
   1023   EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
   1024             state.NextAction());
   1025   state.UpdateState(state.NextAction());
   1026 
   1027   // Ask a forced redraw and verify it ocurrs.
   1028   state.SetNeedsForcedRedraw(true);
   1029   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
   1030   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_FORCED, state.NextAction());
   1031   state.DidLeaveBeginFrame();
   1032 }
   1033 
   1034 TEST(SchedulerStateMachineTest, DontDrawBeforeCommitAfterLostOutputSurface) {
   1035   SchedulerSettings default_scheduler_settings;
   1036   StateMachine state(default_scheduler_settings);
   1037   state.SetCanStart();
   1038   state.UpdateState(state.NextAction());
   1039   state.DidCreateAndInitializeOutputSurface();
   1040   state.SetVisible(true);
   1041   state.SetCanDraw(true);
   1042 
   1043   state.SetNeedsRedraw(true);
   1044 
   1045   // Cause a lost output surface, and restore it.
   1046   state.DidLoseOutputSurface();
   1047   EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
   1048             state.NextAction());
   1049   state.UpdateState(state.NextAction());
   1050   state.DidCreateAndInitializeOutputSurface();
   1051 
   1052   EXPECT_FALSE(state.RedrawPending());
   1053   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
   1054             state.NextAction());
   1055 }
   1056 
   1057 TEST(SchedulerStateMachineTest,
   1058     TestSendBeginFrameToMainThreadWhenInvisibleAndForceCommit) {
   1059   SchedulerSettings default_scheduler_settings;
   1060   StateMachine state(default_scheduler_settings);
   1061   state.SetCanStart();
   1062   state.UpdateState(state.NextAction());
   1063   state.DidCreateAndInitializeOutputSurface();
   1064   state.SetVisible(false);
   1065   state.SetNeedsCommit();
   1066   state.SetNeedsForcedCommit();
   1067   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
   1068             state.NextAction());
   1069 }
   1070 
   1071 TEST(SchedulerStateMachineTest,
   1072     TestSendBeginFrameToMainThreadWhenCanStartFalseAndForceCommit) {
   1073   SchedulerSettings default_scheduler_settings;
   1074   StateMachine state(default_scheduler_settings);
   1075   state.SetVisible(true);
   1076   state.SetCanDraw(true);
   1077   state.SetNeedsCommit();
   1078   state.SetNeedsForcedCommit();
   1079   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
   1080             state.NextAction());
   1081 }
   1082 
   1083 TEST(SchedulerStateMachineTest, TestFinishCommitWhenCommitInProgress) {
   1084   SchedulerSettings default_scheduler_settings;
   1085   StateMachine state(default_scheduler_settings);
   1086   state.SetCanStart();
   1087   state.UpdateState(state.NextAction());
   1088   state.DidCreateAndInitializeOutputSurface();
   1089   state.SetVisible(false);
   1090   state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS);
   1091   state.SetNeedsCommit();
   1092 
   1093   state.FinishCommit();
   1094   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
   1095   state.UpdateState(state.NextAction());
   1096 
   1097   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
   1098             state.CommitState());
   1099 
   1100   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
   1101 }
   1102 
   1103 TEST(SchedulerStateMachineTest, TestFinishCommitWhenForcedCommitInProgress) {
   1104   SchedulerSettings default_scheduler_settings;
   1105   StateMachine state(default_scheduler_settings);
   1106   state.SetCanStart();
   1107   state.UpdateState(state.NextAction());
   1108   state.DidCreateAndInitializeOutputSurface();
   1109   state.SetVisible(false);
   1110   state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS);
   1111   state.SetNeedsCommit();
   1112   state.SetNeedsForcedCommit();
   1113 
   1114   state.FinishCommit();
   1115   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
   1116   state.UpdateState(state.NextAction());
   1117 
   1118   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW,
   1119             state.CommitState());
   1120 
   1121   // If we are waiting for forced draw then we know a begin frame is already
   1122   // in flight for the main thread.
   1123   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
   1124 }
   1125 
   1126 TEST(SchedulerStateMachineTest, TestSendBeginFrameToMainThreadWhenContextLost) {
   1127   SchedulerSettings default_scheduler_settings;
   1128   StateMachine state(default_scheduler_settings);
   1129   state.SetCanStart();
   1130   state.UpdateState(state.NextAction());
   1131   state.DidCreateAndInitializeOutputSurface();
   1132   state.SetVisible(true);
   1133   state.SetCanDraw(true);
   1134   state.SetNeedsCommit();
   1135   state.SetNeedsForcedCommit();
   1136   state.DidLoseOutputSurface();
   1137   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
   1138             state.NextAction());
   1139 }
   1140 
   1141 TEST(SchedulerStateMachineTest, TestImmediateFinishCommit) {
   1142   SchedulerSettings default_scheduler_settings;
   1143   StateMachine state(default_scheduler_settings);
   1144   state.SetCanStart();
   1145   state.UpdateState(state.NextAction());
   1146   state.DidCreateAndInitializeOutputSurface();
   1147   state.SetVisible(true);
   1148   state.SetCanDraw(true);
   1149 
   1150   // Schedule a forced frame, commit it, draw it.
   1151   state.SetNeedsCommit();
   1152   state.SetNeedsForcedCommit();
   1153   state.UpdateState(state.NextAction());
   1154   state.FinishCommit();
   1155   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
   1156   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
   1157             state.CommitState());
   1158   state.UpdateState(state.NextAction());
   1159 
   1160   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW,
   1161             state.CommitState());
   1162 
   1163   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
   1164   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
   1165   state.SetNeedsForcedRedraw(true);
   1166   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_FORCED, state.NextAction());
   1167   state.UpdateState(state.NextAction());
   1168   state.DidDrawIfPossibleCompleted(true);
   1169   state.DidLeaveBeginFrame();
   1170 
   1171   // Should be waiting for the normal begin frame from the main thread.
   1172   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
   1173             state.CommitState());
   1174 }
   1175 
   1176 TEST(SchedulerStateMachineTest, TestImmediateFinishCommitDuringCommit) {
   1177   SchedulerSettings default_scheduler_settings;
   1178   StateMachine state(default_scheduler_settings);
   1179   state.SetCanStart();
   1180   state.UpdateState(state.NextAction());
   1181   state.DidCreateAndInitializeOutputSurface();
   1182   state.SetVisible(true);
   1183   state.SetCanDraw(true);
   1184 
   1185   // Start a normal commit.
   1186   state.SetNeedsCommit();
   1187   state.UpdateState(state.NextAction());
   1188 
   1189   // Schedule a forced frame, commit it, draw it.
   1190   state.SetNeedsCommit();
   1191   state.SetNeedsForcedCommit();
   1192   state.UpdateState(state.NextAction());
   1193   state.FinishCommit();
   1194   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
   1195   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
   1196             state.CommitState());
   1197   state.UpdateState(state.NextAction());
   1198 
   1199   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW,
   1200             state.CommitState());
   1201 
   1202   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
   1203   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
   1204   state.SetNeedsForcedRedraw(true);
   1205   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_FORCED, state.NextAction());
   1206   state.UpdateState(state.NextAction());
   1207   state.DidDrawIfPossibleCompleted(true);
   1208   state.DidLeaveBeginFrame();
   1209 
   1210   // Should be waiting for the normal begin frame from the main thread.
   1211   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
   1212             state.CommitState()) << state.ToString();
   1213 }
   1214 
   1215 TEST(SchedulerStateMachineTest,
   1216     ImmediateBeginFrameAbortedByMainThreadWhileInvisible) {
   1217   SchedulerSettings default_scheduler_settings;
   1218   StateMachine state(default_scheduler_settings);
   1219   state.SetCanStart();
   1220   state.UpdateState(state.NextAction());
   1221   state.DidCreateAndInitializeOutputSurface();
   1222   state.SetVisible(true);
   1223   state.SetCanDraw(true);
   1224 
   1225   state.SetNeedsCommit();
   1226   state.UpdateState(state.NextAction());
   1227 
   1228   state.SetNeedsCommit();
   1229   state.SetNeedsForcedCommit();
   1230   state.UpdateState(state.NextAction());
   1231   state.FinishCommit();
   1232 
   1233   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
   1234   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
   1235             state.CommitState());
   1236   state.UpdateState(state.NextAction());
   1237 
   1238   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW,
   1239             state.CommitState());
   1240 
   1241   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
   1242   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
   1243   state.SetNeedsForcedRedraw(true);
   1244   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_FORCED, state.NextAction());
   1245   state.UpdateState(state.NextAction());
   1246   state.DidDrawIfPossibleCompleted(true);
   1247   state.DidLeaveBeginFrame();
   1248 
   1249   // Should be waiting for the main thread's begin frame.
   1250   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
   1251             state.CommitState()) << state.ToString();
   1252 
   1253   // Become invisible and abort the main thread's begin frame.
   1254   state.SetVisible(false);
   1255   state.BeginFrameAbortedByMainThread(false);
   1256 
   1257   // Should be back in the idle state, but needing a commit.
   1258   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
   1259   EXPECT_TRUE(state.NeedsCommit());
   1260 }
   1261 
   1262 TEST(SchedulerStateMachineTest, ImmediateFinishCommitWhileCantDraw) {
   1263   SchedulerSettings default_scheduler_settings;
   1264   StateMachine state(default_scheduler_settings);
   1265   state.SetCanStart();
   1266   state.UpdateState(state.NextAction());
   1267   state.DidCreateAndInitializeOutputSurface();
   1268   state.SetVisible(true);
   1269   state.SetCanDraw(false);
   1270 
   1271   state.SetNeedsCommit();
   1272   state.UpdateState(state.NextAction());
   1273 
   1274   state.SetNeedsCommit();
   1275   state.SetNeedsForcedCommit();
   1276   state.UpdateState(state.NextAction());
   1277   state.FinishCommit();
   1278 
   1279   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
   1280   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
   1281             state.CommitState());
   1282   state.UpdateState(state.NextAction());
   1283 
   1284   EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW,
   1285             state.CommitState());
   1286 
   1287   state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting());
   1288   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
   1289   state.SetNeedsForcedRedraw(true);
   1290   EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_FORCED, state.NextAction());
   1291   state.UpdateState(state.NextAction());
   1292   state.DidDrawIfPossibleCompleted(true);
   1293   state.DidLeaveBeginFrame();
   1294 }
   1295 
   1296 TEST(SchedulerStateMachineTest, ReportIfNotDrawing) {
   1297   SchedulerSettings default_scheduler_settings;
   1298   SchedulerStateMachine state(default_scheduler_settings);
   1299 
   1300   state.SetCanDraw(true);
   1301   state.SetVisible(true);
   1302   EXPECT_FALSE(state.DrawSuspendedUntilCommit());
   1303 
   1304   state.SetCanDraw(false);
   1305   state.SetVisible(true);
   1306   EXPECT_TRUE(state.DrawSuspendedUntilCommit());
   1307 
   1308   state.SetCanDraw(true);
   1309   state.SetVisible(false);
   1310   EXPECT_TRUE(state.DrawSuspendedUntilCommit());
   1311 
   1312   state.SetCanDraw(false);
   1313   state.SetVisible(false);
   1314   EXPECT_TRUE(state.DrawSuspendedUntilCommit());
   1315 
   1316   state.SetCanDraw(true);
   1317   state.SetVisible(true);
   1318   EXPECT_FALSE(state.DrawSuspendedUntilCommit());
   1319 }
   1320 
   1321 TEST(SchedulerStateMachineTest, ReportIfNotDrawingFromAcquiredTextures) {
   1322   SchedulerSettings default_scheduler_settings;
   1323   SchedulerStateMachine state(default_scheduler_settings);
   1324   state.SetCanStart();
   1325   state.UpdateState(state.NextAction());
   1326   state.DidCreateAndInitializeOutputSurface();
   1327   state.SetCanDraw(true);
   1328   state.SetVisible(true);
   1329   EXPECT_FALSE(state.DrawSuspendedUntilCommit());
   1330 
   1331   state.SetMainThreadNeedsLayerTextures();
   1332   EXPECT_EQ(
   1333       SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD,
   1334       state.NextAction());
   1335   state.UpdateState(state.NextAction());
   1336   EXPECT_TRUE(state.DrawSuspendedUntilCommit());
   1337 
   1338   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
   1339 
   1340   state.SetNeedsCommit();
   1341   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
   1342             state.NextAction());
   1343 
   1344   state.UpdateState(state.NextAction());
   1345   EXPECT_TRUE(state.DrawSuspendedUntilCommit());
   1346 
   1347   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
   1348 
   1349   state.FinishCommit();
   1350   EXPECT_TRUE(state.DrawSuspendedUntilCommit());
   1351 
   1352   EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
   1353 
   1354   state.UpdateState(state.NextAction());
   1355   EXPECT_FALSE(state.DrawSuspendedUntilCommit());
   1356 }
   1357 
   1358 TEST(SchedulerStateMachineTest, AcquireTexturesWithAbort) {
   1359   SchedulerSettings default_scheduler_settings;
   1360   SchedulerStateMachine state(default_scheduler_settings);
   1361   state.SetCanStart();
   1362   state.UpdateState(state.NextAction());
   1363   state.DidCreateAndInitializeOutputSurface();
   1364   state.SetCanDraw(true);
   1365   state.SetVisible(true);
   1366 
   1367   state.SetMainThreadNeedsLayerTextures();
   1368   EXPECT_EQ(
   1369       SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD,
   1370       state.NextAction());
   1371   state.UpdateState(state.NextAction());
   1372   EXPECT_TRUE(state.DrawSuspendedUntilCommit());
   1373 
   1374   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
   1375 
   1376   state.SetNeedsCommit();
   1377   EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD,
   1378             state.NextAction());
   1379   state.UpdateState(state.NextAction());
   1380   EXPECT_TRUE(state.DrawSuspendedUntilCommit());
   1381 
   1382   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
   1383 
   1384   state.BeginFrameAbortedByMainThread(true);
   1385 
   1386   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
   1387   EXPECT_FALSE(state.DrawSuspendedUntilCommit());
   1388 }
   1389 
   1390 }  // namespace
   1391 }  // namespace cc
   1392