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.
5 #include "cc/scheduler/scheduler_state_machine.h"
7 #include "base/trace_event/trace_event.h"
8 #include "cc/scheduler/scheduler.h"
9 #include "cc/test/begin_frame_args_test.h"
10 #include "testing/gtest/include/gtest/gtest.h"
12 // Macro to compare two enum values and get nice output.
14 // Value of: actual() Actual: 7
15 // Expected: expected() Which is: 0
17 // Value of: actual() Actual: "ACTION_ANIMATE"
18 // Expected: expected() Which is: "ACTION_NONE"
19 #define EXPECT_ENUM_EQ(enum_tostring, expected, actual) \
20 EXPECT_STREQ(SchedulerStateMachine::enum_tostring(expected), \
21 SchedulerStateMachine::enum_tostring(actual))
23 #define EXPECT_IMPL_FRAME_STATE(expected) \
24 EXPECT_ENUM_EQ(BeginImplFrameStateToString, expected, \
25 state.begin_impl_frame_state()) \
26 << state.AsValue()->ToString()
28 #define EXPECT_COMMIT_STATE(expected) \
29 EXPECT_ENUM_EQ(CommitStateToString, expected, state.CommitState())
31 #define EXPECT_ACTION(expected) \
32 EXPECT_ENUM_EQ(ActionToString, expected, state.NextAction()) \
33 << state.AsValue()->ToString()
35 #define EXPECT_ACTION_UPDATE_STATE(action) \
36 EXPECT_ACTION(action); \
37 if (action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE || \
38 action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED) { \
39 EXPECT_IMPL_FRAME_STATE( \
40 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE); \
42 state.UpdateState(action); \
43 if (action == SchedulerStateMachine::ACTION_NONE) { \
44 if (state.begin_impl_frame_state() == \
45 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) \
46 state.OnBeginImplFrameDeadlinePending(); \
47 if (state.begin_impl_frame_state() == \
48 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) \
49 state.OnBeginImplFrameIdle(); \
52 #define SET_UP_STATE(state) \
53 state.SetCanStart(); \
54 state.UpdateState(state.NextAction()); \
55 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); \
56 state.SetVisible(true); \
57 state.SetCanDraw(true);
63 const SchedulerStateMachine::BeginImplFrameState all_begin_impl_frame_states
[] =
64 {SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE
,
65 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING
,
66 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME
,
67 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
, };
69 const SchedulerStateMachine::CommitState all_commit_states
[] = {
70 SchedulerStateMachine::COMMIT_STATE_IDLE
,
71 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
,
72 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED
,
73 SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
,
74 SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_ACTIVATION
,
75 SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_DRAW
};
77 // Exposes the protected state fields of the SchedulerStateMachine for testing
78 class StateMachine
: public SchedulerStateMachine
{
80 explicit StateMachine(const SchedulerSettings
& scheduler_settings
)
81 : SchedulerStateMachine(scheduler_settings
) {}
83 void CreateAndInitializeOutputSurfaceWithActivatedCommit() {
84 DidCreateAndInitializeOutputSurface();
85 output_surface_state_
= OUTPUT_SURFACE_ACTIVE
;
88 void SetCommitState(CommitState cs
) { commit_state_
= cs
; }
89 CommitState
CommitState() const { return commit_state_
; }
91 ForcedRedrawOnTimeoutState
ForcedRedrawState() const {
92 return forced_redraw_state_
;
95 void SetBeginImplFrameState(BeginImplFrameState bifs
) {
96 begin_impl_frame_state_
= bifs
;
99 BeginImplFrameState
begin_impl_frame_state() const {
100 return begin_impl_frame_state_
;
103 OutputSurfaceState
output_surface_state() const {
104 return output_surface_state_
;
107 bool NeedsCommit() const { return needs_commit_
; }
109 void SetNeedsRedraw(bool b
) { needs_redraw_
= b
; }
111 void SetNeedsForcedRedrawForTimeout(bool b
) {
112 forced_redraw_state_
= FORCED_REDRAW_STATE_WAITING_FOR_COMMIT
;
113 active_tree_needs_first_draw_
= true;
115 bool NeedsForcedRedrawForTimeout() const {
116 return forced_redraw_state_
!= FORCED_REDRAW_STATE_IDLE
;
119 void SetActiveTreeNeedsFirstDraw(bool needs_first_draw
) {
120 active_tree_needs_first_draw_
= needs_first_draw
;
123 bool CanDraw() const { return can_draw_
; }
124 bool Visible() const { return visible_
; }
126 bool PendingActivationsShouldBeForced() const {
127 return SchedulerStateMachine::PendingActivationsShouldBeForced();
130 void SetHasPendingTree(bool has_pending_tree
) {
131 has_pending_tree_
= has_pending_tree
;
134 using SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately
;
135 using SchedulerStateMachine::ProactiveBeginFrameWanted
;
136 using SchedulerStateMachine::UpdateStateOnCommit
;
139 TEST(SchedulerStateMachineTest
, TestNextActionBeginsMainFrameIfNeeded
) {
140 SchedulerSettings default_scheduler_settings
;
142 // If no commit needed, do nothing.
144 StateMachine
state(default_scheduler_settings
);
146 EXPECT_ACTION_UPDATE_STATE(
147 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
)
148 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
149 state
.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE
);
150 state
.SetNeedsRedraw(false);
151 state
.SetVisible(true);
153 EXPECT_FALSE(state
.BeginFrameNeeded());
155 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
156 EXPECT_FALSE(state
.BeginFrameNeeded());
157 state
.OnBeginImplFrame();
159 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
160 state
.OnBeginImplFrameDeadline();
163 // If commit requested but can_start is still false, do nothing.
165 StateMachine
state(default_scheduler_settings
);
166 state
.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE
);
167 state
.SetNeedsRedraw(false);
168 state
.SetVisible(true);
169 state
.SetNeedsCommit();
171 EXPECT_FALSE(state
.BeginFrameNeeded());
173 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
174 EXPECT_FALSE(state
.BeginFrameNeeded());
175 state
.OnBeginImplFrame();
176 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
177 state
.OnBeginImplFrameDeadline();
180 // If commit requested, begin a main frame.
182 StateMachine
state(default_scheduler_settings
);
183 state
.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE
);
185 state
.UpdateState(state
.NextAction());
186 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
187 state
.SetNeedsRedraw(false);
188 state
.SetVisible(true);
189 state
.SetNeedsCommit();
191 EXPECT_TRUE(state
.BeginFrameNeeded());
193 state
.OnBeginImplFrame();
194 EXPECT_ACTION_UPDATE_STATE(
195 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
198 // Begin the frame, make sure needs_commit and commit_state update correctly.
200 StateMachine
state(default_scheduler_settings
);
202 state
.UpdateState(state
.NextAction());
203 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
204 state
.SetVisible(true);
205 state
.UpdateState(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
207 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
208 EXPECT_FALSE(state
.NeedsCommit());
212 // Explicitly test main_frame_before_activation_enabled = true
213 TEST(SchedulerStateMachineTest
, MainFrameBeforeActivationEnabled
) {
214 SchedulerSettings scheduler_settings
;
215 scheduler_settings
.impl_side_painting
= true;
216 scheduler_settings
.main_frame_before_activation_enabled
= true;
217 StateMachine
state(scheduler_settings
);
218 state
.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE
);
220 state
.SetNeedsRedraw(false);
221 state
.SetNeedsCommit();
223 EXPECT_TRUE(state
.BeginFrameNeeded());
225 // Commit to the pending tree.
226 state
.OnBeginImplFrame();
227 EXPECT_ACTION_UPDATE_STATE(
228 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
229 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
231 state
.NotifyBeginMainFrameStarted();
232 state
.NotifyReadyToCommit();
233 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
234 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
235 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
237 state
.OnBeginImplFrameDeadline();
238 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
240 // Verify that the next commit starts while there is still a pending tree.
241 state
.SetNeedsCommit();
242 state
.OnBeginImplFrame();
243 EXPECT_ACTION_UPDATE_STATE(
244 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
245 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
247 // Verify the pending commit doesn't overwrite the pending
248 // tree until the pending tree has been activated.
249 state
.NotifyBeginMainFrameStarted();
250 state
.NotifyReadyToCommit();
251 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
253 // Verify NotifyReadyToActivate unblocks activation, draw, and
254 // commit in that order.
255 state
.NotifyReadyToActivate();
256 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE
);
257 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
259 EXPECT_TRUE(state
.ShouldTriggerBeginImplFrameDeadlineImmediately());
260 state
.OnBeginImplFrameDeadline();
261 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
262 EXPECT_ACTION_UPDATE_STATE(
263 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
264 state
.DidSwapBuffers();
265 state
.DidSwapBuffersComplete();
266 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
267 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
268 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
271 TEST(SchedulerStateMachineTest
,
272 TestFailedDrawForAnimationCheckerboardSetsNeedsCommitAndDoesNotDrawAgain
) {
273 SchedulerSettings default_scheduler_settings
;
274 StateMachine
state(default_scheduler_settings
);
276 state
.SetNeedsRedraw(true);
277 EXPECT_TRUE(state
.RedrawPending());
278 EXPECT_TRUE(state
.BeginFrameNeeded());
279 state
.OnBeginImplFrame();
280 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
281 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
282 state
.OnBeginImplFrameDeadline();
284 // We're drawing now.
285 EXPECT_ACTION_UPDATE_STATE(
286 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
287 state
.DidSwapBuffers();
288 state
.DidSwapBuffersComplete();
289 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
291 EXPECT_FALSE(state
.RedrawPending());
292 EXPECT_FALSE(state
.CommitPending());
294 // Failing the draw makes us require a commit.
295 state
.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
);
296 state
.OnBeginImplFrame();
297 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
298 EXPECT_ACTION_UPDATE_STATE(
299 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
300 EXPECT_TRUE(state
.RedrawPending());
301 EXPECT_TRUE(state
.CommitPending());
304 TEST(SchedulerStateMachineTest
, TestFailedDrawForMissingHighResNeedsCommit
) {
305 SchedulerSettings default_scheduler_settings
;
306 StateMachine
state(default_scheduler_settings
);
308 state
.SetNeedsRedraw(true);
309 EXPECT_TRUE(state
.RedrawPending());
310 EXPECT_TRUE(state
.BeginFrameNeeded());
312 state
.OnBeginImplFrame();
313 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
314 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
315 state
.OnBeginImplFrameDeadline();
316 EXPECT_ACTION_UPDATE_STATE(
317 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
318 state
.DidSwapBuffers();
319 state
.DidSwapBuffersComplete();
320 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
321 EXPECT_FALSE(state
.RedrawPending());
322 EXPECT_FALSE(state
.CommitPending());
324 // Missing high res content requires a commit (but not a redraw)
325 state
.DidDrawIfPossibleCompleted(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
);
326 state
.OnBeginImplFrame();
327 EXPECT_ACTION_UPDATE_STATE(
328 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
329 EXPECT_FALSE(state
.RedrawPending());
330 EXPECT_TRUE(state
.CommitPending());
333 TEST(SchedulerStateMachineTest
,
334 TestsetNeedsRedrawDuringFailedDrawDoesNotRemoveNeedsRedraw
) {
335 SchedulerSettings default_scheduler_settings
;
336 StateMachine
state(default_scheduler_settings
);
338 state
.SetNeedsRedraw(true);
339 EXPECT_TRUE(state
.RedrawPending());
340 EXPECT_TRUE(state
.BeginFrameNeeded());
341 state
.OnBeginImplFrame();
342 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
343 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
344 state
.OnBeginImplFrameDeadline();
346 // We're drawing now.
347 EXPECT_ACTION_UPDATE_STATE(
348 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
349 state
.DidSwapBuffers();
350 state
.DidSwapBuffersComplete();
351 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
352 EXPECT_FALSE(state
.RedrawPending());
353 EXPECT_FALSE(state
.CommitPending());
355 // While still in the same BeginMainFrame callback on the main thread,
356 // set needs redraw again. This should not redraw.
357 state
.SetNeedsRedraw(true);
358 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
360 // Failing the draw for animation checkerboards makes us require a commit.
361 state
.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
);
362 state
.OnBeginImplFrame();
363 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
364 EXPECT_ACTION_UPDATE_STATE(
365 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
366 EXPECT_TRUE(state
.RedrawPending());
369 TEST(SchedulerStateMachineTest
,
370 TestFailedDrawsEventuallyForceDrawAfterNextCommit
) {
371 SchedulerSettings scheduler_settings
;
372 scheduler_settings
.maximum_number_of_failed_draws_before_draw_is_forced_
= 1;
373 StateMachine
state(scheduler_settings
);
377 state
.SetNeedsCommit();
378 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
379 state
.OnBeginImplFrame();
380 EXPECT_ACTION_UPDATE_STATE(
381 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
382 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
383 EXPECT_TRUE(state
.CommitPending());
385 // Then initiate a draw.
386 state
.SetNeedsRedraw(true);
387 state
.OnBeginImplFrameDeadline();
388 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
389 EXPECT_ACTION_UPDATE_STATE(
390 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
393 state
.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
);
394 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
395 EXPECT_TRUE(state
.BeginFrameNeeded());
396 EXPECT_TRUE(state
.RedrawPending());
397 // But the commit is ongoing.
398 EXPECT_TRUE(state
.CommitPending());
400 // Finish the commit. Note, we should not yet be forcing a draw, but should
401 // continue the commit as usual.
402 state
.NotifyBeginMainFrameStarted();
403 state
.NotifyReadyToCommit();
404 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
405 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
406 EXPECT_TRUE(state
.RedrawPending());
408 // The redraw should be forced at the end of the next BeginImplFrame.
409 state
.OnBeginImplFrame();
410 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
411 EXPECT_ACTION_UPDATE_STATE(
412 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
413 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
414 state
.OnBeginImplFrameDeadline();
415 EXPECT_ACTION_UPDATE_STATE(
416 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED
);
417 state
.DidSwapBuffers();
418 state
.DidSwapBuffersComplete();
421 TEST(SchedulerStateMachineTest
, TestFailedDrawsDoNotRestartForcedDraw
) {
422 SchedulerSettings scheduler_settings
;
424 scheduler_settings
.maximum_number_of_failed_draws_before_draw_is_forced_
=
426 scheduler_settings
.impl_side_painting
= true;
427 StateMachine
state(scheduler_settings
);
431 state
.SetNeedsCommit();
432 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
433 state
.OnBeginImplFrame();
434 EXPECT_ACTION_UPDATE_STATE(
435 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
436 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
437 EXPECT_TRUE(state
.CommitPending());
439 // Then initiate a draw.
440 state
.SetNeedsRedraw(true);
441 state
.OnBeginImplFrameDeadline();
442 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
443 EXPECT_ACTION_UPDATE_STATE(
444 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
446 // Fail the draw enough times to force a redraw,
447 // then once more for good measure.
448 for (int i
= 0; i
< draw_limit
+ 1; ++i
)
449 state
.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
);
450 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
451 EXPECT_TRUE(state
.BeginFrameNeeded());
452 EXPECT_TRUE(state
.RedrawPending());
453 // But the commit is ongoing.
454 EXPECT_TRUE(state
.CommitPending());
455 EXPECT_TRUE(state
.ForcedRedrawState() ==
456 SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_COMMIT
);
458 state
.NotifyBeginMainFrameStarted();
459 state
.NotifyReadyToCommit();
460 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
461 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
462 EXPECT_TRUE(state
.RedrawPending());
463 EXPECT_FALSE(state
.CommitPending());
465 // Now force redraw should be in waiting for activation
466 EXPECT_TRUE(state
.ForcedRedrawState() ==
467 SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION
);
469 // After failing additional draws, we should still be in a forced
470 // redraw, but not back in WAITING_FOR_COMMIT.
471 for (int i
= 0; i
< draw_limit
+ 1; ++i
)
472 state
.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
);
473 EXPECT_TRUE(state
.RedrawPending());
474 EXPECT_TRUE(state
.ForcedRedrawState() ==
475 SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION
);
478 TEST(SchedulerStateMachineTest
, TestFailedDrawIsRetriedInNextBeginImplFrame
) {
479 SchedulerSettings default_scheduler_settings
;
480 StateMachine
state(default_scheduler_settings
);
484 state
.SetNeedsRedraw(true);
485 EXPECT_TRUE(state
.BeginFrameNeeded());
486 state
.OnBeginImplFrame();
487 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
488 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
489 state
.OnBeginImplFrameDeadline();
490 EXPECT_TRUE(state
.RedrawPending());
491 EXPECT_ACTION_UPDATE_STATE(
492 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
494 // Failing the draw for animation checkerboards makes us require a commit.
495 state
.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
);
496 EXPECT_ACTION_UPDATE_STATE(
497 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
498 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
499 EXPECT_TRUE(state
.RedrawPending());
501 // We should not be trying to draw again now, but we have a commit pending.
502 EXPECT_TRUE(state
.BeginFrameNeeded());
503 state
.OnBeginImplFrame();
504 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
505 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
507 // We should try to draw again at the end of the next BeginImplFrame on
509 state
.OnBeginImplFrameDeadline();
510 EXPECT_ACTION_UPDATE_STATE(
511 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
512 state
.DidSwapBuffers();
513 state
.DidSwapBuffersComplete();
514 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
517 TEST(SchedulerStateMachineTest
, TestDoestDrawTwiceInSameFrame
) {
518 SchedulerSettings default_scheduler_settings
;
519 StateMachine
state(default_scheduler_settings
);
521 state
.SetNeedsRedraw(true);
523 // Draw the first frame.
524 EXPECT_TRUE(state
.BeginFrameNeeded());
525 state
.OnBeginImplFrame();
526 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
527 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
529 state
.OnBeginImplFrameDeadline();
530 EXPECT_ACTION_UPDATE_STATE(
531 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
532 state
.DidSwapBuffers();
533 state
.DidDrawIfPossibleCompleted(DRAW_SUCCESS
);
534 state
.DidSwapBuffersComplete();
535 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
537 // Before the next BeginImplFrame, set needs redraw again.
538 // This should not redraw until the next BeginImplFrame.
539 state
.SetNeedsRedraw(true);
540 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
542 // Move to another frame. This should now draw.
543 EXPECT_TRUE(state
.BeginFrameNeeded());
544 state
.OnBeginImplFrame();
546 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
547 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
549 state
.OnBeginImplFrameDeadline();
550 EXPECT_ACTION_UPDATE_STATE(
551 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
552 state
.DidSwapBuffers();
553 state
.DidDrawIfPossibleCompleted(DRAW_SUCCESS
);
554 state
.DidSwapBuffersComplete();
555 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
557 // We just swapped, so we should proactively request another BeginImplFrame.
558 EXPECT_TRUE(state
.BeginFrameNeeded());
561 TEST(SchedulerStateMachineTest
, TestNextActionDrawsOnBeginImplFrame
) {
562 SchedulerSettings default_scheduler_settings
;
564 // When not in BeginImplFrame deadline, or in BeginImplFrame deadline
565 // but not visible, don't draw.
566 size_t num_commit_states
=
567 sizeof(all_commit_states
) / sizeof(SchedulerStateMachine::CommitState
);
568 size_t num_begin_impl_frame_states
=
569 sizeof(all_begin_impl_frame_states
) /
570 sizeof(SchedulerStateMachine::BeginImplFrameState
);
571 for (size_t i
= 0; i
< num_commit_states
; ++i
) {
572 for (size_t j
= 0; j
< num_begin_impl_frame_states
; ++j
) {
573 StateMachine
state(default_scheduler_settings
);
575 state
.UpdateState(state
.NextAction());
576 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
577 state
.SetCommitState(all_commit_states
[i
]);
578 state
.SetBeginImplFrameState(all_begin_impl_frame_states
[j
]);
580 (all_begin_impl_frame_states
[j
] !=
581 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
);
582 state
.SetVisible(visible
);
584 // Case 1: needs_commit=false
585 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
,
588 // Case 2: needs_commit=true
589 state
.SetNeedsCommit();
590 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
,
592 << state
.AsValue()->ToString();
596 // When in BeginImplFrame deadline we should always draw for SetNeedsRedraw
597 // except if we're ready to commit, in which case we expect a commit first.
598 for (size_t i
= 0; i
< num_commit_states
; ++i
) {
599 StateMachine
state(default_scheduler_settings
);
601 state
.UpdateState(state
.NextAction());
602 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
603 state
.SetCanDraw(true);
604 state
.SetCommitState(all_commit_states
[i
]);
605 state
.SetBeginImplFrameState(
606 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
);
608 state
.SetNeedsRedraw(true);
609 state
.SetVisible(true);
611 SchedulerStateMachine::Action expected_action
;
612 if (all_commit_states
[i
] ==
613 SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
) {
614 expected_action
= SchedulerStateMachine::ACTION_COMMIT
;
616 expected_action
= SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
;
617 EXPECT_ACTION(SchedulerStateMachine::ACTION_ANIMATE
);
618 state
.UpdateState(state
.NextAction());
621 // Case 1: needs_commit=false.
622 EXPECT_ACTION(expected_action
);
624 // Case 2: needs_commit=true.
625 state
.SetNeedsCommit();
626 EXPECT_ACTION(expected_action
);
630 TEST(SchedulerStateMachineTest
, TestNoCommitStatesRedrawWhenInvisible
) {
631 SchedulerSettings default_scheduler_settings
;
633 size_t num_commit_states
=
634 sizeof(all_commit_states
) / sizeof(SchedulerStateMachine::CommitState
);
635 for (size_t i
= 0; i
< num_commit_states
; ++i
) {
636 // There shouldn't be any drawing regardless of BeginImplFrame.
637 for (size_t j
= 0; j
< 2; ++j
) {
638 StateMachine
state(default_scheduler_settings
);
640 state
.UpdateState(state
.NextAction());
641 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
642 state
.SetCommitState(all_commit_states
[i
]);
643 state
.SetVisible(false);
644 state
.SetNeedsRedraw(true);
646 state
.SetBeginImplFrameState(
647 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
);
650 // Case 1: needs_commit=false.
651 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
,
654 // Case 2: needs_commit=true.
655 state
.SetNeedsCommit();
656 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
,
658 << state
.AsValue()->ToString();
663 TEST(SchedulerStateMachineTest
, TestCanRedraw_StopsDraw
) {
664 SchedulerSettings default_scheduler_settings
;
666 size_t num_commit_states
=
667 sizeof(all_commit_states
) / sizeof(SchedulerStateMachine::CommitState
);
668 for (size_t i
= 0; i
< num_commit_states
; ++i
) {
669 // There shouldn't be any drawing regardless of BeginImplFrame.
670 for (size_t j
= 0; j
< 2; ++j
) {
671 StateMachine
state(default_scheduler_settings
);
673 state
.UpdateState(state
.NextAction());
674 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
675 state
.SetCommitState(all_commit_states
[i
]);
676 state
.SetVisible(false);
677 state
.SetNeedsRedraw(true);
679 state
.OnBeginImplFrame();
681 state
.SetCanDraw(false);
682 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
,
688 TEST(SchedulerStateMachineTest
,
689 TestCanRedrawWithWaitingForFirstDrawMakesProgress
) {
690 SchedulerSettings default_scheduler_settings
;
691 StateMachine
state(default_scheduler_settings
);
693 state
.UpdateState(state
.NextAction());
694 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
696 state
.SetActiveTreeNeedsFirstDraw(true);
697 state
.SetNeedsCommit();
698 state
.SetNeedsRedraw(true);
699 state
.SetVisible(true);
700 state
.SetCanDraw(false);
701 state
.OnBeginImplFrame();
702 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
703 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT
);
704 EXPECT_ACTION_UPDATE_STATE(
705 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
706 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
707 state
.NotifyBeginMainFrameStarted();
708 state
.NotifyReadyToCommit();
709 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
710 state
.OnBeginImplFrameDeadline();
711 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
712 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT
);
713 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
716 TEST(SchedulerStateMachineTest
, TestSetNeedsCommitIsNotLost
) {
717 SchedulerSettings scheduler_settings
;
718 StateMachine
state(scheduler_settings
);
720 state
.SetNeedsCommit();
722 EXPECT_TRUE(state
.BeginFrameNeeded());
725 state
.OnBeginImplFrame();
726 EXPECT_ACTION_UPDATE_STATE(
727 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
729 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
731 // Now, while the frame is in progress, set another commit.
732 state
.SetNeedsCommit();
733 EXPECT_TRUE(state
.NeedsCommit());
735 // Let the frame finish.
736 state
.NotifyBeginMainFrameStarted();
737 state
.NotifyReadyToCommit();
738 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
);
740 // Expect to commit regardless of BeginImplFrame state.
741 EXPECT_IMPL_FRAME_STATE(
742 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING
);
743 EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT
);
745 state
.OnBeginImplFrameDeadlinePending();
746 EXPECT_IMPL_FRAME_STATE(
747 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME
);
748 EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT
);
750 state
.OnBeginImplFrameDeadline();
751 EXPECT_IMPL_FRAME_STATE(
752 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
);
753 EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT
);
755 state
.OnBeginImplFrameIdle();
756 EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE
);
757 EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT
);
759 state
.OnBeginImplFrame();
760 EXPECT_IMPL_FRAME_STATE(
761 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING
);
762 EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT
);
764 // Finish the commit, then make sure we start the next commit immediately
765 // and draw on the next BeginImplFrame.
766 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
767 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
768 EXPECT_ACTION_UPDATE_STATE(
769 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
770 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
772 state
.OnBeginImplFrameDeadline();
774 EXPECT_TRUE(state
.active_tree_needs_first_draw());
775 EXPECT_ACTION_UPDATE_STATE(
776 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
777 state
.DidSwapBuffers();
778 state
.DidDrawIfPossibleCompleted(DRAW_SUCCESS
);
779 state
.DidSwapBuffersComplete();
780 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
783 TEST(SchedulerStateMachineTest
, TestFullCycle
) {
784 SchedulerSettings default_scheduler_settings
;
785 StateMachine
state(default_scheduler_settings
);
788 // Start clean and set commit.
789 state
.SetNeedsCommit();
792 state
.OnBeginImplFrame();
793 EXPECT_ACTION_UPDATE_STATE(
794 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
796 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
797 EXPECT_FALSE(state
.NeedsCommit());
798 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
800 // Tell the scheduler the frame finished.
801 state
.NotifyBeginMainFrameStarted();
802 state
.NotifyReadyToCommit();
803 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
);
806 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
807 EXPECT_TRUE(state
.active_tree_needs_first_draw());
808 EXPECT_TRUE(state
.needs_redraw());
810 // Expect to do nothing until BeginImplFrame deadline
811 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
813 // At BeginImplFrame deadline, draw.
814 state
.OnBeginImplFrameDeadline();
815 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
816 EXPECT_ACTION_UPDATE_STATE(
817 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
818 state
.DidSwapBuffers();
819 state
.DidDrawIfPossibleCompleted(DRAW_SUCCESS
);
820 state
.DidSwapBuffersComplete();
822 // Should be synchronized, no draw needed, no action needed.
823 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
824 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
825 EXPECT_FALSE(state
.needs_redraw());
828 TEST(SchedulerStateMachineTest
, TestFullCycleWithMainThreadLowLatencyMode
) {
829 SchedulerSettings scheduler_settings
;
830 scheduler_settings
.main_thread_should_always_be_low_latency
= true;
831 StateMachine
state(scheduler_settings
);
834 // Start clean and set commit.
835 state
.SetNeedsCommit();
838 state
.OnBeginImplFrame();
839 EXPECT_ACTION_UPDATE_STATE(
840 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
842 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
843 EXPECT_FALSE(state
.NeedsCommit());
844 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
846 // Tell the scheduler the frame finished.
847 state
.NotifyBeginMainFrameStarted();
848 state
.NotifyReadyToCommit();
849 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
);
852 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
853 EXPECT_TRUE(state
.active_tree_needs_first_draw());
854 EXPECT_TRUE(state
.needs_redraw());
856 // Now commit should wait for draw.
857 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_DRAW
);
859 // Swap throttled. Do not draw.
860 state
.DidSwapBuffers();
861 state
.OnBeginImplFrameDeadline();
862 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
863 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
864 state
.DidSwapBuffersComplete();
866 // Haven't draw since last commit, do not begin new main frame.
867 state
.SetNeedsCommit();
868 state
.OnBeginImplFrame();
869 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
870 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
872 // At BeginImplFrame deadline, draw.
873 state
.OnBeginImplFrameDeadline();
874 EXPECT_ACTION_UPDATE_STATE(
875 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
876 state
.DidSwapBuffers();
877 state
.DidDrawIfPossibleCompleted(DRAW_SUCCESS
);
878 state
.DidSwapBuffersComplete();
880 // Now will be able to start main frame.
881 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
882 EXPECT_FALSE(state
.needs_redraw());
883 EXPECT_ACTION_UPDATE_STATE(
884 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
887 TEST(SchedulerStateMachineTest
,
888 TestFullCycleWithMainThreadLowLatencyMode_ImplSidePaint
) {
889 SchedulerSettings scheduler_settings
;
890 scheduler_settings
.main_thread_should_always_be_low_latency
= true;
891 scheduler_settings
.impl_side_painting
= true;
892 StateMachine
state(scheduler_settings
);
895 // Start clean and set commit.
896 state
.SetNeedsCommit();
899 state
.OnBeginImplFrame();
900 EXPECT_ACTION_UPDATE_STATE(
901 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
903 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
904 EXPECT_FALSE(state
.NeedsCommit());
905 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
907 // Tell the scheduler the frame finished.
908 state
.NotifyBeginMainFrameStarted();
909 state
.NotifyReadyToCommit();
910 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
);
913 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
915 // Now commit should wait for activation.
917 SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_ACTIVATION
);
919 // No activation yet, so this commit is not drawn yet. Force to draw this
920 // frame, and still block BeginMainFrame.
921 state
.SetNeedsRedraw(true);
922 state
.SetNeedsCommit();
923 state
.OnBeginImplFrameDeadline();
924 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
925 EXPECT_ACTION_UPDATE_STATE(
926 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
927 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
929 // Cannot BeginMainFrame yet since last commit is not yet activated and drawn.
930 state
.OnBeginImplFrame();
932 SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_ACTIVATION
);
933 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
935 // Now activate sync tree.
936 state
.NotifyReadyToActivate();
937 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE
);
938 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
939 EXPECT_TRUE(state
.active_tree_needs_first_draw());
940 EXPECT_TRUE(state
.needs_redraw());
941 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_DRAW
);
943 // Swap throttled. Do not draw.
944 state
.DidSwapBuffers();
945 state
.OnBeginImplFrameDeadline();
946 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
947 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
948 state
.DidSwapBuffersComplete();
950 // Haven't draw since last commit, do not begin new main frame.
951 state
.OnBeginImplFrame();
952 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
953 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
955 // At BeginImplFrame deadline, draw. This draws unblocks BeginMainFrame.
956 state
.OnBeginImplFrameDeadline();
957 EXPECT_ACTION_UPDATE_STATE(
958 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
959 state
.DidSwapBuffers();
960 state
.DidDrawIfPossibleCompleted(DRAW_SUCCESS
);
961 state
.DidSwapBuffersComplete();
963 // Now will be able to start main frame.
964 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
965 EXPECT_FALSE(state
.needs_redraw());
966 EXPECT_ACTION_UPDATE_STATE(
967 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
970 TEST(SchedulerStateMachineTest
, TestFullCycleWithCommitRequestInbetween
) {
971 SchedulerSettings default_scheduler_settings
;
972 StateMachine
state(default_scheduler_settings
);
975 // Start clean and set commit.
976 state
.SetNeedsCommit();
979 state
.OnBeginImplFrame();
980 EXPECT_ACTION_UPDATE_STATE(
981 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
983 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
984 EXPECT_FALSE(state
.NeedsCommit());
985 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
987 // Request another commit while the commit is in flight.
988 state
.SetNeedsCommit();
989 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
991 // Tell the scheduler the frame finished.
992 state
.NotifyBeginMainFrameStarted();
993 state
.NotifyReadyToCommit();
994 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
);
997 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
998 EXPECT_TRUE(state
.active_tree_needs_first_draw());
999 EXPECT_TRUE(state
.needs_redraw());
1001 // Expect to do nothing until BeginImplFrame deadline.
1002 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1004 // At BeginImplFrame deadline, draw.
1005 state
.OnBeginImplFrameDeadline();
1006 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1007 EXPECT_ACTION_UPDATE_STATE(
1008 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1009 state
.DidSwapBuffers();
1010 state
.DidDrawIfPossibleCompleted(DRAW_SUCCESS
);
1011 state
.DidSwapBuffersComplete();
1013 // Should be synchronized, no draw needed, no action needed.
1014 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1015 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
1016 EXPECT_FALSE(state
.needs_redraw());
1018 // Next BeginImplFrame should initiate second commit.
1019 state
.OnBeginImplFrame();
1020 EXPECT_ACTION_UPDATE_STATE(
1021 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1024 TEST(SchedulerStateMachineTest
, TestRequestCommitInvisible
) {
1025 SchedulerSettings default_scheduler_settings
;
1026 StateMachine
state(default_scheduler_settings
);
1027 state
.SetCanStart();
1028 state
.UpdateState(state
.NextAction());
1029 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1030 state
.SetNeedsCommit();
1031 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1034 // See ThreadProxy::BeginMainFrame "EarlyOut_NotVisible" /
1035 // "EarlyOut_OutputSurfaceLost" cases.
1036 TEST(SchedulerStateMachineTest
, TestAbortBeginMainFrameBecauseInvisible
) {
1037 SchedulerSettings default_scheduler_settings
;
1038 StateMachine
state(default_scheduler_settings
);
1041 // Start clean and set commit.
1042 state
.SetNeedsCommit();
1044 // Begin the frame while visible.
1045 state
.OnBeginImplFrame();
1046 EXPECT_ACTION_UPDATE_STATE(
1047 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1048 EXPECT_COMMIT_STATE(
1049 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
1050 EXPECT_FALSE(state
.NeedsCommit());
1051 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1053 // Become invisible and abort BeginMainFrame.
1054 state
.SetVisible(false);
1055 state
.BeginMainFrameAborted(CommitEarlyOutReason::ABORTED_NOT_VISIBLE
);
1057 // NeedsCommit should now be true again because we never actually did a
1059 EXPECT_TRUE(state
.NeedsCommit());
1061 // We should now be back in the idle state as if we never started the frame.
1062 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
1063 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1065 // We shouldn't do anything on the BeginImplFrame deadline.
1066 state
.OnBeginImplFrameDeadline();
1067 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1069 // Become visible again.
1070 state
.SetVisible(true);
1072 // Although we have aborted on this frame and haven't cancelled the commit
1073 // (i.e. need another), don't send another BeginMainFrame yet.
1074 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
1075 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1076 EXPECT_TRUE(state
.NeedsCommit());
1078 // Start a new frame.
1079 state
.OnBeginImplFrame();
1080 EXPECT_ACTION_UPDATE_STATE(
1081 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1083 // We should be starting the commit now.
1084 EXPECT_COMMIT_STATE(
1085 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
1086 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1089 // See ThreadProxy::BeginMainFrame "EarlyOut_NoUpdates" case.
1090 TEST(SchedulerStateMachineTest
, TestAbortBeginMainFrameBecauseCommitNotNeeded
) {
1091 SchedulerSettings default_scheduler_settings
;
1092 StateMachine
state(default_scheduler_settings
);
1093 state
.SetCanStart();
1094 state
.UpdateState(state
.NextAction());
1095 state
.DidCreateAndInitializeOutputSurface();
1096 state
.SetVisible(true);
1097 state
.SetCanDraw(true);
1099 // Get into a begin frame / commit state.
1100 state
.SetNeedsCommit();
1101 state
.OnBeginImplFrame();
1102 EXPECT_ACTION_UPDATE_STATE(
1103 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1104 EXPECT_COMMIT_STATE(
1105 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
1106 EXPECT_FALSE(state
.NeedsCommit());
1107 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1109 // Abort the commit, true means that the BeginMainFrame was sent but there
1110 // was no work to do on the main thread.
1111 state
.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES
);
1113 // NeedsCommit should now be false because the commit was actually handled.
1114 EXPECT_FALSE(state
.NeedsCommit());
1116 // Even though the commit was aborted, we still expect to draw the new frame.
1117 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1118 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1119 state
.OnBeginImplFrameDeadline();
1120 EXPECT_ACTION_UPDATE_STATE(
1121 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1122 state
.DidSwapBuffers();
1123 state
.DidSwapBuffersComplete();
1124 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1126 // Verify another commit doesn't start on another frame either.
1127 EXPECT_FALSE(state
.NeedsCommit());
1128 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
1130 state
.OnBeginImplFrame();
1131 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1132 state
.OnBeginImplFrameDeadline();
1133 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1135 // Verify another commit can start if requested, though.
1136 state
.SetNeedsCommit();
1137 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
1138 state
.OnBeginImplFrame();
1139 EXPECT_ACTION(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1142 TEST(SchedulerStateMachineTest
, TestFirstContextCreation
) {
1143 SchedulerSettings default_scheduler_settings
;
1144 StateMachine
state(default_scheduler_settings
);
1145 state
.SetCanStart();
1146 state
.SetVisible(true);
1147 state
.SetCanDraw(true);
1149 EXPECT_ACTION_UPDATE_STATE(
1150 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
);
1151 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1152 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1154 // Check that the first init does not SetNeedsCommit.
1155 state
.OnBeginImplFrame();
1156 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1157 state
.OnBeginImplFrameDeadline();
1158 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1160 // Check that a needs commit initiates a BeginMainFrame.
1161 state
.SetNeedsCommit();
1162 state
.OnBeginImplFrame();
1163 EXPECT_ACTION_UPDATE_STATE(
1164 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1167 TEST(SchedulerStateMachineTest
, TestContextLostWhenCompletelyIdle
) {
1168 SchedulerSettings default_scheduler_settings
;
1169 StateMachine
state(default_scheduler_settings
);
1172 EXPECT_NE(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
,
1173 state
.NextAction());
1174 state
.DidLoseOutputSurface();
1176 EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
);
1177 state
.UpdateState(state
.NextAction());
1179 // Once context recreation begins, nothing should happen.
1180 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1182 // Recreate the context.
1183 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1185 // When the context is recreated, we should begin a commit.
1186 state
.OnBeginImplFrame();
1187 EXPECT_ACTION_UPDATE_STATE(
1188 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1191 TEST(SchedulerStateMachineTest
,
1192 TestContextLostWhenIdleAndCommitRequestedWhileRecreating
) {
1193 SchedulerSettings default_scheduler_settings
;
1194 // We use impl side painting because it's the more complicated version.
1195 default_scheduler_settings
.impl_side_painting
= true;
1196 StateMachine
state(default_scheduler_settings
);
1199 EXPECT_NE(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
,
1200 state
.NextAction());
1201 state
.DidLoseOutputSurface();
1202 EXPECT_EQ(state
.output_surface_state(),
1203 SchedulerStateMachine::OUTPUT_SURFACE_LOST
);
1205 EXPECT_ACTION_UPDATE_STATE(
1206 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
);
1207 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1209 // Once context recreation begins, nothing should happen.
1210 state
.OnBeginImplFrame();
1211 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1212 state
.OnBeginImplFrameDeadline();
1213 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1215 // While context is recreating, commits shouldn't begin.
1216 state
.SetNeedsCommit();
1217 state
.OnBeginImplFrame();
1218 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1219 state
.OnBeginImplFrameDeadline();
1220 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1222 // Recreate the context
1223 state
.DidCreateAndInitializeOutputSurface();
1224 EXPECT_EQ(state
.output_surface_state(),
1225 SchedulerStateMachine::OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT
);
1226 EXPECT_FALSE(state
.RedrawPending());
1228 // When the context is recreated, we wait until the next BeginImplFrame
1230 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1232 // When the BeginFrame comes in we should begin a commit
1233 state
.OnBeginImplFrame();
1234 EXPECT_ACTION_UPDATE_STATE(
1235 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1236 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1237 EXPECT_COMMIT_STATE(
1238 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
1240 // Until that commit finishes, we shouldn't be drawing or animate.
1241 state
.OnBeginImplFrameDeadline();
1242 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1244 // Finish the commit, which should make the surface active.
1245 state
.NotifyBeginMainFrameStarted();
1246 state
.NotifyReadyToCommit();
1247 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
1248 EXPECT_EQ(state
.output_surface_state(),
1249 SchedulerStateMachine::OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION
);
1250 state
.NotifyReadyToActivate();
1251 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE
);
1252 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1253 EXPECT_EQ(state
.output_surface_state(),
1254 SchedulerStateMachine::OUTPUT_SURFACE_ACTIVE
);
1256 // Finishing the first commit after initializing an output surface should
1257 // automatically cause a redraw.
1258 EXPECT_TRUE(state
.RedrawPending());
1259 state
.OnBeginImplFrame();
1260 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1261 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1262 state
.OnBeginImplFrameDeadline();
1263 EXPECT_ACTION_UPDATE_STATE(
1264 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1265 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1266 EXPECT_FALSE(state
.RedrawPending());
1268 // Next frame as no work to do.
1269 state
.OnBeginImplFrame();
1270 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1271 state
.OnBeginImplFrameDeadline();
1272 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1274 // Once the context is recreated, whether we draw should be based on
1275 // SetCanDraw if waiting on first draw after activate.
1276 state
.SetNeedsRedraw(true);
1277 state
.OnBeginImplFrame();
1278 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1279 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1280 state
.OnBeginImplFrameDeadline();
1281 EXPECT_ACTION(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1282 state
.SetCanDraw(false);
1283 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1284 state
.SetCanDraw(true);
1285 EXPECT_ACTION_UPDATE_STATE(
1286 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1287 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1289 // Once the context is recreated, whether we draw should be based on
1290 // SetCanDraw if waiting on first draw after activate.
1291 state
.SetNeedsRedraw(true);
1292 state
.SetNeedsCommit();
1293 state
.OnBeginImplFrame();
1294 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1295 EXPECT_ACTION_UPDATE_STATE(
1296 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1297 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1298 // Activate so we need the first draw
1299 state
.NotifyBeginMainFrameStarted();
1300 state
.NotifyReadyToCommit();
1301 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
1302 state
.NotifyReadyToActivate();
1303 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE
);
1304 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1305 EXPECT_TRUE(state
.active_tree_needs_first_draw());
1306 EXPECT_TRUE(state
.needs_redraw());
1308 state
.OnBeginImplFrameDeadline();
1309 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1310 EXPECT_ACTION(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1311 state
.SetCanDraw(false);
1312 EXPECT_ACTION(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT
);
1313 state
.SetCanDraw(true);
1314 EXPECT_ACTION(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1317 TEST(SchedulerStateMachineTest
, TestContextLostWhileCommitInProgress
) {
1318 SchedulerSettings scheduler_settings
;
1319 StateMachine
state(scheduler_settings
);
1322 // Get a commit in flight.
1323 state
.SetNeedsCommit();
1325 // Set damage and expect a draw.
1326 state
.SetNeedsRedraw(true);
1327 state
.OnBeginImplFrame();
1328 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1329 EXPECT_ACTION_UPDATE_STATE(
1330 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1331 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1332 state
.OnBeginImplFrameDeadline();
1333 EXPECT_ACTION_UPDATE_STATE(
1334 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1335 state
.DidSwapBuffers();
1336 state
.DidSwapBuffersComplete();
1337 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1339 // Cause a lost context while the BeginMainFrame is in flight.
1340 state
.DidLoseOutputSurface();
1342 // Ask for another draw. Expect nothing happens.
1343 state
.SetNeedsRedraw(true);
1344 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1346 // Finish the frame, and commit.
1347 state
.NotifyBeginMainFrameStarted();
1348 state
.NotifyReadyToCommit();
1349 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
1351 // We will abort the draw when the output surface is lost if we are
1352 // waiting for the first draw to unblock the main thread.
1353 EXPECT_TRUE(state
.active_tree_needs_first_draw());
1354 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT
);
1356 // Expect to begin context recreation only in BEGIN_IMPL_FRAME_STATE_IDLE
1357 EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE
);
1358 EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
);
1360 state
.OnBeginImplFrame();
1361 EXPECT_IMPL_FRAME_STATE(
1362 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING
);
1363 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1365 state
.OnBeginImplFrameDeadlinePending();
1366 EXPECT_IMPL_FRAME_STATE(
1367 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME
);
1368 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1370 state
.OnBeginImplFrameDeadline();
1371 EXPECT_IMPL_FRAME_STATE(
1372 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
);
1373 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1376 TEST(SchedulerStateMachineTest
,
1377 TestContextLostWhileCommitInProgressAndAnotherCommitRequested
) {
1378 SchedulerSettings scheduler_settings
;
1379 StateMachine
state(scheduler_settings
);
1382 // Get a commit in flight.
1383 state
.SetNeedsCommit();
1384 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1386 // Set damage and expect a draw.
1387 state
.SetNeedsRedraw(true);
1388 state
.OnBeginImplFrame();
1389 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1390 EXPECT_ACTION_UPDATE_STATE(
1391 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1392 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1393 state
.OnBeginImplFrameDeadline();
1394 EXPECT_ACTION_UPDATE_STATE(
1395 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1396 state
.DidSwapBuffers();
1397 state
.DidSwapBuffersComplete();
1398 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1400 // Cause a lost context while the BeginMainFrame is in flight.
1401 state
.DidLoseOutputSurface();
1403 // Ask for another draw and also set needs commit. Expect nothing happens.
1404 state
.SetNeedsRedraw(true);
1405 state
.SetNeedsCommit();
1406 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1408 // Finish the frame, and commit.
1409 state
.NotifyBeginMainFrameStarted();
1410 state
.NotifyReadyToCommit();
1411 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
1412 EXPECT_TRUE(state
.active_tree_needs_first_draw());
1414 // Because the output surface is missing, we expect the draw to abort.
1415 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT
);
1417 // Expect to begin context recreation only in BEGIN_IMPL_FRAME_STATE_IDLE
1418 EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE
);
1419 EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
);
1421 state
.OnBeginImplFrame();
1422 EXPECT_IMPL_FRAME_STATE(
1423 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING
);
1424 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1426 state
.OnBeginImplFrameDeadlinePending();
1427 EXPECT_IMPL_FRAME_STATE(
1428 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME
);
1429 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1431 state
.OnBeginImplFrameDeadline();
1432 EXPECT_IMPL_FRAME_STATE(
1433 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
);
1434 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1436 state
.OnBeginImplFrameIdle();
1437 EXPECT_ACTION_UPDATE_STATE(
1438 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
);
1440 // After we get a new output surface, the commit flow should start.
1441 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1442 state
.OnBeginImplFrame();
1443 EXPECT_ACTION_UPDATE_STATE(
1444 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1445 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1446 state
.NotifyBeginMainFrameStarted();
1447 state
.NotifyReadyToCommit();
1448 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
1449 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1450 state
.OnBeginImplFrameDeadline();
1451 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1452 EXPECT_ACTION_UPDATE_STATE(
1453 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1454 state
.DidSwapBuffers();
1455 state
.DidSwapBuffersComplete();
1456 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1459 TEST(SchedulerStateMachineTest
, DontDrawBeforeCommitAfterLostOutputSurface
) {
1460 SchedulerSettings default_scheduler_settings
;
1461 StateMachine
state(default_scheduler_settings
);
1464 state
.SetNeedsRedraw(true);
1466 // Cause a lost output surface, and restore it.
1467 state
.DidLoseOutputSurface();
1468 EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
);
1469 state
.UpdateState(state
.NextAction());
1470 state
.DidCreateAndInitializeOutputSurface();
1472 EXPECT_FALSE(state
.RedrawPending());
1473 state
.OnBeginImplFrame();
1474 EXPECT_ACTION(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1477 TEST(SchedulerStateMachineTest
,
1478 TestPendingActivationsShouldBeForcedAfterLostOutputSurface
) {
1479 SchedulerSettings settings
;
1480 settings
.impl_side_painting
= true;
1481 StateMachine
state(settings
);
1484 state
.SetCommitState(
1485 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
1487 // Cause a lost context.
1488 state
.DidLoseOutputSurface();
1490 state
.NotifyBeginMainFrameStarted();
1491 state
.NotifyReadyToCommit();
1492 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
1494 EXPECT_TRUE(state
.PendingActivationsShouldBeForced());
1495 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE
);
1497 EXPECT_TRUE(state
.PendingDrawsShouldBeAborted());
1498 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT
);
1501 TEST(SchedulerStateMachineTest
, TestNoBeginMainFrameWhenInvisible
) {
1502 SchedulerSettings default_scheduler_settings
;
1503 StateMachine
state(default_scheduler_settings
);
1504 state
.SetCanStart();
1505 state
.UpdateState(state
.NextAction());
1506 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1507 state
.SetVisible(false);
1508 state
.SetNeedsCommit();
1509 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1512 TEST(SchedulerStateMachineTest
, TestFinishCommitWhenCommitInProgress
) {
1513 SchedulerSettings default_scheduler_settings
;
1514 StateMachine
state(default_scheduler_settings
);
1515 state
.SetCanStart();
1516 state
.UpdateState(state
.NextAction());
1517 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1518 state
.SetVisible(false);
1519 state
.SetCommitState(
1520 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
1521 state
.SetNeedsCommit();
1523 state
.NotifyBeginMainFrameStarted();
1524 state
.NotifyReadyToCommit();
1525 EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT
);
1526 state
.UpdateState(state
.NextAction());
1528 EXPECT_TRUE(state
.active_tree_needs_first_draw());
1529 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT
);
1532 TEST(SchedulerStateMachineTest
, TestInitialActionsWhenContextLost
) {
1533 SchedulerSettings default_scheduler_settings
;
1534 StateMachine
state(default_scheduler_settings
);
1536 state
.SetNeedsCommit();
1537 state
.DidLoseOutputSurface();
1539 // When we are visible, we normally want to begin output surface creation
1540 // as soon as possible.
1541 EXPECT_ACTION_UPDATE_STATE(
1542 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
);
1544 state
.DidCreateAndInitializeOutputSurface();
1545 EXPECT_EQ(state
.output_surface_state(),
1546 SchedulerStateMachine::OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT
);
1548 // We should not send a BeginMainFrame when we are invisible, even if we've
1549 // lost the output surface and are trying to get the first commit, since the
1550 // main thread will just abort anyway.
1551 state
.SetVisible(false);
1552 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1555 TEST(SchedulerStateMachineTest
, ReportIfNotDrawing
) {
1556 SchedulerSettings default_scheduler_settings
;
1557 StateMachine
state(default_scheduler_settings
);
1559 EXPECT_FALSE(state
.PendingDrawsShouldBeAborted());
1561 state
.SetCanDraw(false);
1562 state
.SetVisible(true);
1563 EXPECT_TRUE(state
.PendingDrawsShouldBeAborted());
1565 state
.SetCanDraw(true);
1566 state
.SetVisible(false);
1567 EXPECT_TRUE(state
.PendingDrawsShouldBeAborted());
1569 state
.SetCanDraw(false);
1570 state
.SetVisible(false);
1571 EXPECT_TRUE(state
.PendingDrawsShouldBeAborted());
1573 state
.SetCanDraw(true);
1574 state
.SetVisible(true);
1575 EXPECT_FALSE(state
.PendingDrawsShouldBeAborted());
1578 TEST(SchedulerStateMachineTest
,
1579 TestTriggerDeadlineImmediatelyAfterAbortedCommit
) {
1580 SchedulerSettings settings
;
1581 settings
.impl_side_painting
= true;
1582 StateMachine
state(settings
);
1585 // This test mirrors what happens during the first frame of a scroll gesture.
1586 // First we get the input event and a BeginFrame.
1587 state
.OnBeginImplFrame();
1589 // As a response the compositor requests a redraw and a commit to tell the
1590 // main thread about the new scroll offset.
1591 state
.SetNeedsRedraw(true);
1592 state
.SetNeedsCommit();
1594 // We should start the commit normally.
1595 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1596 EXPECT_ACTION_UPDATE_STATE(
1597 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1598 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1600 // Since only the scroll offset changed, the main thread will abort the
1602 state
.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES
);
1604 // Since the commit was aborted, we should draw right away instead of waiting
1605 // for the deadline.
1606 EXPECT_TRUE(state
.ShouldTriggerBeginImplFrameDeadlineImmediately());
1609 void FinishPreviousCommitAndDrawWithoutExitingDeadline(
1610 StateMachine
* state_ptr
) {
1611 // Gross, but allows us to use macros below.
1612 StateMachine
& state
= *state_ptr
;
1614 state
.NotifyBeginMainFrameStarted();
1615 state
.NotifyReadyToCommit();
1616 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
1617 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1618 state
.NotifyReadyToActivate();
1619 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE
);
1620 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1622 state
.OnBeginImplFrame();
1623 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1624 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1626 EXPECT_TRUE(state
.ShouldTriggerBeginImplFrameDeadlineImmediately());
1627 state
.OnBeginImplFrameDeadline();
1628 EXPECT_ACTION_UPDATE_STATE(
1629 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1630 state
.DidSwapBuffers();
1633 TEST(SchedulerStateMachineTest
, TestImplLatencyTakesPriority
) {
1634 SchedulerSettings settings
;
1635 settings
.impl_side_painting
= true;
1636 StateMachine
state(settings
);
1639 // This test ensures that impl-draws are prioritized over main thread updates
1640 // in prefer impl latency mode.
1641 state
.SetNeedsRedraw(true);
1642 state
.SetNeedsCommit();
1643 state
.OnBeginImplFrame();
1644 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1645 EXPECT_ACTION_UPDATE_STATE(
1646 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1647 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1649 // Verify the deadline is not triggered early until we enter
1650 // prefer impl latency mode.
1651 EXPECT_FALSE(state
.ShouldTriggerBeginImplFrameDeadlineImmediately());
1652 state
.SetImplLatencyTakesPriority(true);
1653 EXPECT_TRUE(state
.ShouldTriggerBeginImplFrameDeadlineImmediately());
1655 // Trigger the deadline.
1656 state
.OnBeginImplFrameDeadline();
1657 EXPECT_ACTION_UPDATE_STATE(
1658 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1659 state
.DidSwapBuffers();
1660 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1661 state
.DidSwapBuffersComplete();
1663 // Request a new commit and finish the previous one.
1664 state
.SetNeedsCommit();
1665 FinishPreviousCommitAndDrawWithoutExitingDeadline(&state
);
1666 EXPECT_ACTION_UPDATE_STATE(
1667 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1668 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1669 state
.DidSwapBuffersComplete();
1670 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1672 // Finish the previous commit and draw it.
1673 FinishPreviousCommitAndDrawWithoutExitingDeadline(&state
);
1674 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1676 // Verify we do not send another BeginMainFrame if was are swap throttled
1677 // and did not just swap.
1678 state
.SetNeedsCommit();
1679 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1680 state
.OnBeginImplFrame();
1681 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1682 EXPECT_FALSE(state
.ShouldTriggerBeginImplFrameDeadlineImmediately());
1683 state
.OnBeginImplFrameDeadline();
1684 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1687 TEST(SchedulerStateMachineTest
,
1688 TestTriggerDeadlineImmediatelyOnLostOutputSurface
) {
1689 SchedulerSettings default_scheduler_settings
;
1690 StateMachine
state(default_scheduler_settings
);
1693 state
.SetNeedsCommit();
1695 state
.OnBeginImplFrame();
1696 EXPECT_ACTION_UPDATE_STATE(
1697 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1698 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1699 EXPECT_FALSE(state
.ShouldTriggerBeginImplFrameDeadlineImmediately());
1701 state
.DidLoseOutputSurface();
1702 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1703 // The deadline should be triggered immediately when output surface is lost.
1704 EXPECT_TRUE(state
.ShouldTriggerBeginImplFrameDeadlineImmediately());
1707 TEST(SchedulerStateMachineTest
, TestSetNeedsAnimate
) {
1708 SchedulerSettings settings
;
1709 settings
.impl_side_painting
= true;
1710 StateMachine
state(settings
);
1713 // Test requesting an animation that, when run, causes us to draw.
1714 state
.SetNeedsAnimate();
1715 EXPECT_TRUE(state
.BeginFrameNeeded());
1716 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1718 state
.OnBeginImplFrame();
1719 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1721 state
.OnBeginImplFrameDeadlinePending();
1722 state
.OnBeginImplFrameDeadline();
1723 EXPECT_ACTION_UPDATE_STATE(
1724 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1727 TEST(SchedulerStateMachineTest
, TestAnimateBeforeCommit
) {
1728 SchedulerSettings settings
;
1729 settings
.impl_side_painting
= true;
1730 StateMachine
state(settings
);
1733 // Check that animations are updated before we start a commit.
1734 state
.SetNeedsAnimate();
1735 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1736 state
.SetNeedsCommit();
1737 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1738 EXPECT_TRUE(state
.BeginFrameNeeded());
1740 state
.OnBeginImplFrame();
1741 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1742 EXPECT_ACTION_UPDATE_STATE(
1743 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1745 state
.OnBeginImplFrameDeadlinePending();
1746 state
.OnBeginImplFrameDeadline();
1747 EXPECT_ACTION_UPDATE_STATE(
1748 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1751 TEST(SchedulerStateMachineTest
, TestAnimateAfterCommitBeforeDraw
) {
1752 SchedulerSettings settings
;
1753 settings
.impl_side_painting
= true;
1754 StateMachine
state(settings
);
1757 // Check that animations are updated before we start a commit.
1758 state
.SetNeedsAnimate();
1759 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1760 state
.SetNeedsCommit();
1761 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1762 EXPECT_TRUE(state
.BeginFrameNeeded());
1764 state
.OnBeginImplFrame();
1765 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1766 EXPECT_ACTION_UPDATE_STATE(
1767 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1769 state
.NotifyBeginMainFrameStarted();
1770 state
.NotifyReadyToCommit();
1771 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
1773 state
.OnBeginImplFrameDeadlinePending();
1774 state
.OnBeginImplFrameDeadline();
1775 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1776 EXPECT_ACTION_UPDATE_STATE(
1777 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1780 TEST(SchedulerStateMachineTest
, TestSetNeedsAnimateAfterAnimate
) {
1781 SchedulerSettings settings
;
1782 settings
.impl_side_painting
= true;
1783 StateMachine
state(settings
);
1786 // Test requesting an animation after we have already animated during this
1788 state
.SetNeedsRedraw(true);
1789 EXPECT_TRUE(state
.BeginFrameNeeded());
1790 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1792 state
.OnBeginImplFrame();
1793 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1795 state
.SetNeedsAnimate();
1796 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1798 state
.OnBeginImplFrameDeadline();
1799 EXPECT_ACTION_UPDATE_STATE(
1800 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1803 TEST(SchedulerStateMachineTest
, TestForwardBeginFramesToChildren
) {
1804 SchedulerSettings settings
;
1805 StateMachine
state(settings
);
1808 EXPECT_FALSE(state
.BeginFrameNeeded());
1809 state
.SetChildrenNeedBeginFrames(true);
1810 EXPECT_TRUE(state
.BeginFrameNeeded());
1813 TEST(SchedulerStateMachineTest
, TestDeferCommit
) {
1814 SchedulerSettings settings
;
1815 StateMachine
state(settings
);
1818 state
.SetDeferCommits(true);
1820 state
.SetNeedsCommit();
1821 EXPECT_TRUE(state
.BeginFrameNeeded());
1822 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1824 state
.OnBeginImplFrame();
1825 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1827 state
.OnBeginImplFrameDeadline();
1828 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1830 state
.SetDeferCommits(false);
1831 state
.OnBeginImplFrame();
1832 EXPECT_ACTION_UPDATE_STATE(
1833 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1836 TEST(SchedulerStateMachineTest
, EarlyOutCommitWantsProactiveBeginFrame
) {
1837 SchedulerSettings settings
;
1838 StateMachine
state(settings
);
1839 SET_UP_STATE(state
);
1841 EXPECT_FALSE(state
.ProactiveBeginFrameWanted());
1842 bool commit_has_no_updates
= true;
1843 state
.UpdateStateOnCommit(commit_has_no_updates
);
1844 EXPECT_TRUE(state
.ProactiveBeginFrameWanted());
1845 state
.OnBeginImplFrame();
1846 EXPECT_FALSE(state
.ProactiveBeginFrameWanted());