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
;
137 TEST(SchedulerStateMachineTest
, TestNextActionBeginsMainFrameIfNeeded
) {
138 SchedulerSettings default_scheduler_settings
;
140 // If no commit needed, do nothing.
142 StateMachine
state(default_scheduler_settings
);
144 EXPECT_ACTION_UPDATE_STATE(
145 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
)
146 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
147 state
.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE
);
148 state
.SetNeedsRedraw(false);
149 state
.SetVisible(true);
151 EXPECT_FALSE(state
.BeginFrameNeeded());
153 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
154 EXPECT_FALSE(state
.BeginFrameNeeded());
155 state
.OnBeginImplFrame();
157 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
158 state
.OnBeginImplFrameDeadline();
161 // If commit requested but can_start is still false, do nothing.
163 StateMachine
state(default_scheduler_settings
);
164 state
.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE
);
165 state
.SetNeedsRedraw(false);
166 state
.SetVisible(true);
167 state
.SetNeedsCommit();
169 EXPECT_FALSE(state
.BeginFrameNeeded());
171 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
172 EXPECT_FALSE(state
.BeginFrameNeeded());
173 state
.OnBeginImplFrame();
174 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
175 state
.OnBeginImplFrameDeadline();
178 // If commit requested, begin a main frame.
180 StateMachine
state(default_scheduler_settings
);
181 state
.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE
);
183 state
.UpdateState(state
.NextAction());
184 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
185 state
.SetNeedsRedraw(false);
186 state
.SetVisible(true);
187 state
.SetNeedsCommit();
189 EXPECT_TRUE(state
.BeginFrameNeeded());
191 state
.OnBeginImplFrame();
192 EXPECT_ACTION_UPDATE_STATE(
193 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
196 // Begin the frame, make sure needs_commit and commit_state update correctly.
198 StateMachine
state(default_scheduler_settings
);
200 state
.UpdateState(state
.NextAction());
201 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
202 state
.SetVisible(true);
203 state
.UpdateState(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
205 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
206 EXPECT_FALSE(state
.NeedsCommit());
210 // Explicitly test main_frame_before_activation_enabled = true
211 TEST(SchedulerStateMachineTest
, MainFrameBeforeActivationEnabled
) {
212 SchedulerSettings scheduler_settings
;
213 scheduler_settings
.impl_side_painting
= true;
214 scheduler_settings
.main_frame_before_activation_enabled
= true;
215 StateMachine
state(scheduler_settings
);
216 state
.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE
);
218 state
.SetNeedsRedraw(false);
219 state
.SetNeedsCommit();
221 EXPECT_TRUE(state
.BeginFrameNeeded());
223 // Commit to the pending tree.
224 state
.OnBeginImplFrame();
225 EXPECT_ACTION_UPDATE_STATE(
226 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
227 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
229 state
.NotifyBeginMainFrameStarted();
230 state
.NotifyReadyToCommit();
231 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
232 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
233 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
235 state
.OnBeginImplFrameDeadline();
236 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
238 // Verify that the next commit starts while there is still a pending tree.
239 state
.SetNeedsCommit();
240 state
.OnBeginImplFrame();
241 EXPECT_ACTION_UPDATE_STATE(
242 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
243 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
245 // Verify the pending commit doesn't overwrite the pending
246 // tree until the pending tree has been activated.
247 state
.NotifyBeginMainFrameStarted();
248 state
.NotifyReadyToCommit();
249 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
251 // Verify NotifyReadyToActivate unblocks activation, draw, and
252 // commit in that order.
253 state
.NotifyReadyToActivate();
254 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE
);
255 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
257 EXPECT_TRUE(state
.ShouldTriggerBeginImplFrameDeadlineImmediately());
258 state
.OnBeginImplFrameDeadline();
259 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
260 EXPECT_ACTION_UPDATE_STATE(
261 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
262 state
.DidSwapBuffers();
263 state
.DidSwapBuffersComplete();
264 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
265 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
266 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
269 TEST(SchedulerStateMachineTest
,
270 TestFailedDrawForAnimationCheckerboardSetsNeedsCommitAndDoesNotDrawAgain
) {
271 SchedulerSettings default_scheduler_settings
;
272 StateMachine
state(default_scheduler_settings
);
274 state
.SetNeedsRedraw(true);
275 EXPECT_TRUE(state
.RedrawPending());
276 EXPECT_TRUE(state
.BeginFrameNeeded());
277 state
.OnBeginImplFrame();
278 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
279 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
280 state
.OnBeginImplFrameDeadline();
282 // We're drawing now.
283 EXPECT_ACTION_UPDATE_STATE(
284 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
285 state
.DidSwapBuffers();
286 state
.DidSwapBuffersComplete();
287 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
289 EXPECT_FALSE(state
.RedrawPending());
290 EXPECT_FALSE(state
.CommitPending());
292 // Failing the draw makes us require a commit.
293 state
.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
);
294 state
.OnBeginImplFrame();
295 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
296 EXPECT_ACTION_UPDATE_STATE(
297 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
298 EXPECT_TRUE(state
.RedrawPending());
299 EXPECT_TRUE(state
.CommitPending());
302 TEST(SchedulerStateMachineTest
, TestFailedDrawForMissingHighResNeedsCommit
) {
303 SchedulerSettings default_scheduler_settings
;
304 StateMachine
state(default_scheduler_settings
);
306 state
.SetNeedsRedraw(true);
307 EXPECT_TRUE(state
.RedrawPending());
308 EXPECT_TRUE(state
.BeginFrameNeeded());
310 state
.OnBeginImplFrame();
311 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
312 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
313 state
.OnBeginImplFrameDeadline();
314 EXPECT_ACTION_UPDATE_STATE(
315 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
316 state
.DidSwapBuffers();
317 state
.DidSwapBuffersComplete();
318 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
319 EXPECT_FALSE(state
.RedrawPending());
320 EXPECT_FALSE(state
.CommitPending());
322 // Missing high res content requires a commit (but not a redraw)
323 state
.DidDrawIfPossibleCompleted(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
);
324 state
.OnBeginImplFrame();
325 EXPECT_ACTION_UPDATE_STATE(
326 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
327 EXPECT_FALSE(state
.RedrawPending());
328 EXPECT_TRUE(state
.CommitPending());
331 TEST(SchedulerStateMachineTest
,
332 TestsetNeedsRedrawDuringFailedDrawDoesNotRemoveNeedsRedraw
) {
333 SchedulerSettings default_scheduler_settings
;
334 StateMachine
state(default_scheduler_settings
);
336 state
.SetNeedsRedraw(true);
337 EXPECT_TRUE(state
.RedrawPending());
338 EXPECT_TRUE(state
.BeginFrameNeeded());
339 state
.OnBeginImplFrame();
340 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
341 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
342 state
.OnBeginImplFrameDeadline();
344 // We're drawing now.
345 EXPECT_ACTION_UPDATE_STATE(
346 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
347 state
.DidSwapBuffers();
348 state
.DidSwapBuffersComplete();
349 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
350 EXPECT_FALSE(state
.RedrawPending());
351 EXPECT_FALSE(state
.CommitPending());
353 // While still in the same BeginMainFrame callback on the main thread,
354 // set needs redraw again. This should not redraw.
355 state
.SetNeedsRedraw(true);
356 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
358 // Failing the draw for animation checkerboards makes us require a commit.
359 state
.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
);
360 state
.OnBeginImplFrame();
361 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
362 EXPECT_ACTION_UPDATE_STATE(
363 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
364 EXPECT_TRUE(state
.RedrawPending());
367 TEST(SchedulerStateMachineTest
,
368 TestFailedDrawsEventuallyForceDrawAfterNextCommit
) {
369 SchedulerSettings scheduler_settings
;
370 scheduler_settings
.maximum_number_of_failed_draws_before_draw_is_forced_
= 1;
371 StateMachine
state(scheduler_settings
);
375 state
.SetNeedsCommit();
376 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
377 state
.OnBeginImplFrame();
378 EXPECT_ACTION_UPDATE_STATE(
379 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
380 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
381 EXPECT_TRUE(state
.CommitPending());
383 // Then initiate a draw.
384 state
.SetNeedsRedraw(true);
385 state
.OnBeginImplFrameDeadline();
386 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
387 EXPECT_ACTION_UPDATE_STATE(
388 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
391 state
.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
);
392 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
393 EXPECT_TRUE(state
.BeginFrameNeeded());
394 EXPECT_TRUE(state
.RedrawPending());
395 // But the commit is ongoing.
396 EXPECT_TRUE(state
.CommitPending());
398 // Finish the commit. Note, we should not yet be forcing a draw, but should
399 // continue the commit as usual.
400 state
.NotifyBeginMainFrameStarted();
401 state
.NotifyReadyToCommit();
402 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
403 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
404 EXPECT_TRUE(state
.RedrawPending());
406 // The redraw should be forced at the end of the next BeginImplFrame.
407 state
.OnBeginImplFrame();
408 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
409 EXPECT_ACTION_UPDATE_STATE(
410 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
411 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
412 state
.OnBeginImplFrameDeadline();
413 EXPECT_ACTION_UPDATE_STATE(
414 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED
);
415 state
.DidSwapBuffers();
416 state
.DidSwapBuffersComplete();
419 TEST(SchedulerStateMachineTest
, TestFailedDrawsDoNotRestartForcedDraw
) {
420 SchedulerSettings scheduler_settings
;
422 scheduler_settings
.maximum_number_of_failed_draws_before_draw_is_forced_
=
424 scheduler_settings
.impl_side_painting
= true;
425 StateMachine
state(scheduler_settings
);
429 state
.SetNeedsCommit();
430 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
431 state
.OnBeginImplFrame();
432 EXPECT_ACTION_UPDATE_STATE(
433 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
434 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
435 EXPECT_TRUE(state
.CommitPending());
437 // Then initiate a draw.
438 state
.SetNeedsRedraw(true);
439 state
.OnBeginImplFrameDeadline();
440 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
441 EXPECT_ACTION_UPDATE_STATE(
442 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
444 // Fail the draw enough times to force a redraw,
445 // then once more for good measure.
446 for (int i
= 0; i
< draw_limit
+ 1; ++i
)
447 state
.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
);
448 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
449 EXPECT_TRUE(state
.BeginFrameNeeded());
450 EXPECT_TRUE(state
.RedrawPending());
451 // But the commit is ongoing.
452 EXPECT_TRUE(state
.CommitPending());
453 EXPECT_TRUE(state
.ForcedRedrawState() ==
454 SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_COMMIT
);
456 state
.NotifyBeginMainFrameStarted();
457 state
.NotifyReadyToCommit();
458 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
459 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
460 EXPECT_TRUE(state
.RedrawPending());
461 EXPECT_FALSE(state
.CommitPending());
463 // Now force redraw should be in waiting for activation
464 EXPECT_TRUE(state
.ForcedRedrawState() ==
465 SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION
);
467 // After failing additional draws, we should still be in a forced
468 // redraw, but not back in WAITING_FOR_COMMIT.
469 for (int i
= 0; i
< draw_limit
+ 1; ++i
)
470 state
.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
);
471 EXPECT_TRUE(state
.RedrawPending());
472 EXPECT_TRUE(state
.ForcedRedrawState() ==
473 SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION
);
476 TEST(SchedulerStateMachineTest
, TestFailedDrawIsRetriedInNextBeginImplFrame
) {
477 SchedulerSettings default_scheduler_settings
;
478 StateMachine
state(default_scheduler_settings
);
482 state
.SetNeedsRedraw(true);
483 EXPECT_TRUE(state
.BeginFrameNeeded());
484 state
.OnBeginImplFrame();
485 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
486 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
487 state
.OnBeginImplFrameDeadline();
488 EXPECT_TRUE(state
.RedrawPending());
489 EXPECT_ACTION_UPDATE_STATE(
490 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
492 // Failing the draw for animation checkerboards makes us require a commit.
493 state
.DidDrawIfPossibleCompleted(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
);
494 EXPECT_ACTION_UPDATE_STATE(
495 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
496 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
497 EXPECT_TRUE(state
.RedrawPending());
499 // We should not be trying to draw again now, but we have a commit pending.
500 EXPECT_TRUE(state
.BeginFrameNeeded());
501 state
.OnBeginImplFrame();
502 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
503 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
505 // We should try to draw again at the end of the next BeginImplFrame on
507 state
.OnBeginImplFrameDeadline();
508 EXPECT_ACTION_UPDATE_STATE(
509 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
510 state
.DidSwapBuffers();
511 state
.DidSwapBuffersComplete();
512 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
515 TEST(SchedulerStateMachineTest
, TestDoestDrawTwiceInSameFrame
) {
516 SchedulerSettings default_scheduler_settings
;
517 StateMachine
state(default_scheduler_settings
);
519 state
.SetNeedsRedraw(true);
521 // Draw the first frame.
522 EXPECT_TRUE(state
.BeginFrameNeeded());
523 state
.OnBeginImplFrame();
524 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
525 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
527 state
.OnBeginImplFrameDeadline();
528 EXPECT_ACTION_UPDATE_STATE(
529 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
530 state
.DidSwapBuffers();
531 state
.DidDrawIfPossibleCompleted(DRAW_SUCCESS
);
532 state
.DidSwapBuffersComplete();
533 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
535 // Before the next BeginImplFrame, set needs redraw again.
536 // This should not redraw until the next BeginImplFrame.
537 state
.SetNeedsRedraw(true);
538 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
540 // Move to another frame. This should now draw.
541 EXPECT_TRUE(state
.BeginFrameNeeded());
542 state
.OnBeginImplFrame();
544 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
545 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
547 state
.OnBeginImplFrameDeadline();
548 EXPECT_ACTION_UPDATE_STATE(
549 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
550 state
.DidSwapBuffers();
551 state
.DidDrawIfPossibleCompleted(DRAW_SUCCESS
);
552 state
.DidSwapBuffersComplete();
553 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
555 // We just swapped, so we should proactively request another BeginImplFrame.
556 EXPECT_TRUE(state
.BeginFrameNeeded());
559 TEST(SchedulerStateMachineTest
, TestNextActionDrawsOnBeginImplFrame
) {
560 SchedulerSettings default_scheduler_settings
;
562 // When not in BeginImplFrame deadline, or in BeginImplFrame deadline
563 // but not visible, don't draw.
564 size_t num_commit_states
=
565 sizeof(all_commit_states
) / sizeof(SchedulerStateMachine::CommitState
);
566 size_t num_begin_impl_frame_states
=
567 sizeof(all_begin_impl_frame_states
) /
568 sizeof(SchedulerStateMachine::BeginImplFrameState
);
569 for (size_t i
= 0; i
< num_commit_states
; ++i
) {
570 for (size_t j
= 0; j
< num_begin_impl_frame_states
; ++j
) {
571 StateMachine
state(default_scheduler_settings
);
573 state
.UpdateState(state
.NextAction());
574 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
575 state
.SetCommitState(all_commit_states
[i
]);
576 state
.SetBeginImplFrameState(all_begin_impl_frame_states
[j
]);
578 (all_begin_impl_frame_states
[j
] !=
579 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
);
580 state
.SetVisible(visible
);
582 // Case 1: needs_commit=false
583 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
,
586 // Case 2: needs_commit=true
587 state
.SetNeedsCommit();
588 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
,
590 << state
.AsValue()->ToString();
594 // When in BeginImplFrame deadline we should always draw for SetNeedsRedraw
595 // except if we're ready to commit, in which case we expect a commit first.
596 for (size_t i
= 0; i
< num_commit_states
; ++i
) {
597 StateMachine
state(default_scheduler_settings
);
599 state
.UpdateState(state
.NextAction());
600 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
601 state
.SetCanDraw(true);
602 state
.SetCommitState(all_commit_states
[i
]);
603 state
.SetBeginImplFrameState(
604 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
);
606 state
.SetNeedsRedraw(true);
607 state
.SetVisible(true);
609 SchedulerStateMachine::Action expected_action
;
610 if (all_commit_states
[i
] ==
611 SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
) {
612 expected_action
= SchedulerStateMachine::ACTION_COMMIT
;
614 expected_action
= SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
;
615 EXPECT_ACTION(SchedulerStateMachine::ACTION_ANIMATE
);
616 state
.UpdateState(state
.NextAction());
619 // Case 1: needs_commit=false.
620 EXPECT_ACTION(expected_action
);
622 // Case 2: needs_commit=true.
623 state
.SetNeedsCommit();
624 EXPECT_ACTION(expected_action
);
628 TEST(SchedulerStateMachineTest
, TestNoCommitStatesRedrawWhenInvisible
) {
629 SchedulerSettings default_scheduler_settings
;
631 size_t num_commit_states
=
632 sizeof(all_commit_states
) / sizeof(SchedulerStateMachine::CommitState
);
633 for (size_t i
= 0; i
< num_commit_states
; ++i
) {
634 // There shouldn't be any drawing regardless of BeginImplFrame.
635 for (size_t j
= 0; j
< 2; ++j
) {
636 StateMachine
state(default_scheduler_settings
);
638 state
.UpdateState(state
.NextAction());
639 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
640 state
.SetCommitState(all_commit_states
[i
]);
641 state
.SetVisible(false);
642 state
.SetNeedsRedraw(true);
644 state
.SetBeginImplFrameState(
645 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
);
648 // Case 1: needs_commit=false.
649 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
,
652 // Case 2: needs_commit=true.
653 state
.SetNeedsCommit();
654 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
,
656 << state
.AsValue()->ToString();
661 TEST(SchedulerStateMachineTest
, TestCanRedraw_StopsDraw
) {
662 SchedulerSettings default_scheduler_settings
;
664 size_t num_commit_states
=
665 sizeof(all_commit_states
) / sizeof(SchedulerStateMachine::CommitState
);
666 for (size_t i
= 0; i
< num_commit_states
; ++i
) {
667 // There shouldn't be any drawing regardless of BeginImplFrame.
668 for (size_t j
= 0; j
< 2; ++j
) {
669 StateMachine
state(default_scheduler_settings
);
671 state
.UpdateState(state
.NextAction());
672 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
673 state
.SetCommitState(all_commit_states
[i
]);
674 state
.SetVisible(false);
675 state
.SetNeedsRedraw(true);
677 state
.OnBeginImplFrame();
679 state
.SetCanDraw(false);
680 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
,
686 TEST(SchedulerStateMachineTest
,
687 TestCanRedrawWithWaitingForFirstDrawMakesProgress
) {
688 SchedulerSettings default_scheduler_settings
;
689 StateMachine
state(default_scheduler_settings
);
691 state
.UpdateState(state
.NextAction());
692 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
694 state
.SetActiveTreeNeedsFirstDraw(true);
695 state
.SetNeedsCommit();
696 state
.SetNeedsRedraw(true);
697 state
.SetVisible(true);
698 state
.SetCanDraw(false);
699 state
.OnBeginImplFrame();
700 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
701 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT
);
702 EXPECT_ACTION_UPDATE_STATE(
703 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
704 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
705 state
.NotifyBeginMainFrameStarted();
706 state
.NotifyReadyToCommit();
707 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
708 state
.OnBeginImplFrameDeadline();
709 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
710 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT
);
711 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
714 TEST(SchedulerStateMachineTest
, TestSetNeedsCommitIsNotLost
) {
715 SchedulerSettings scheduler_settings
;
716 StateMachine
state(scheduler_settings
);
718 state
.SetNeedsCommit();
720 EXPECT_TRUE(state
.BeginFrameNeeded());
723 state
.OnBeginImplFrame();
724 EXPECT_ACTION_UPDATE_STATE(
725 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
727 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
729 // Now, while the frame is in progress, set another commit.
730 state
.SetNeedsCommit();
731 EXPECT_TRUE(state
.NeedsCommit());
733 // Let the frame finish.
734 state
.NotifyBeginMainFrameStarted();
735 state
.NotifyReadyToCommit();
736 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
);
738 // Expect to commit regardless of BeginImplFrame state.
739 EXPECT_IMPL_FRAME_STATE(
740 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING
);
741 EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT
);
743 state
.OnBeginImplFrameDeadlinePending();
744 EXPECT_IMPL_FRAME_STATE(
745 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME
);
746 EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT
);
748 state
.OnBeginImplFrameDeadline();
749 EXPECT_IMPL_FRAME_STATE(
750 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
);
751 EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT
);
753 state
.OnBeginImplFrameIdle();
754 EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE
);
755 EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT
);
757 state
.OnBeginImplFrame();
758 EXPECT_IMPL_FRAME_STATE(
759 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING
);
760 EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT
);
762 // Finish the commit, then make sure we start the next commit immediately
763 // and draw on the next BeginImplFrame.
764 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
765 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
766 EXPECT_ACTION_UPDATE_STATE(
767 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
768 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
770 state
.OnBeginImplFrameDeadline();
772 EXPECT_TRUE(state
.active_tree_needs_first_draw());
773 EXPECT_ACTION_UPDATE_STATE(
774 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
775 state
.DidSwapBuffers();
776 state
.DidDrawIfPossibleCompleted(DRAW_SUCCESS
);
777 state
.DidSwapBuffersComplete();
778 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
781 TEST(SchedulerStateMachineTest
, TestFullCycle
) {
782 SchedulerSettings default_scheduler_settings
;
783 StateMachine
state(default_scheduler_settings
);
786 // Start clean and set commit.
787 state
.SetNeedsCommit();
790 state
.OnBeginImplFrame();
791 EXPECT_ACTION_UPDATE_STATE(
792 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
794 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
795 EXPECT_FALSE(state
.NeedsCommit());
796 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
798 // Tell the scheduler the frame finished.
799 state
.NotifyBeginMainFrameStarted();
800 state
.NotifyReadyToCommit();
801 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
);
804 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
805 EXPECT_TRUE(state
.active_tree_needs_first_draw());
806 EXPECT_TRUE(state
.needs_redraw());
808 // Expect to do nothing until BeginImplFrame deadline
809 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
811 // At BeginImplFrame deadline, draw.
812 state
.OnBeginImplFrameDeadline();
813 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
814 EXPECT_ACTION_UPDATE_STATE(
815 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
816 state
.DidSwapBuffers();
817 state
.DidDrawIfPossibleCompleted(DRAW_SUCCESS
);
818 state
.DidSwapBuffersComplete();
820 // Should be synchronized, no draw needed, no action needed.
821 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
822 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
823 EXPECT_FALSE(state
.needs_redraw());
826 TEST(SchedulerStateMachineTest
, TestFullCycleWithMainThreadLowLatencyMode
) {
827 SchedulerSettings scheduler_settings
;
828 scheduler_settings
.main_thread_should_always_be_low_latency
= true;
829 StateMachine
state(scheduler_settings
);
832 // Start clean and set commit.
833 state
.SetNeedsCommit();
836 state
.OnBeginImplFrame();
837 EXPECT_ACTION_UPDATE_STATE(
838 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
840 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
841 EXPECT_FALSE(state
.NeedsCommit());
842 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
844 // Tell the scheduler the frame finished.
845 state
.NotifyBeginMainFrameStarted();
846 state
.NotifyReadyToCommit();
847 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
);
850 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
851 EXPECT_TRUE(state
.active_tree_needs_first_draw());
852 EXPECT_TRUE(state
.needs_redraw());
854 // Now commit should wait for draw.
855 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_DRAW
);
857 // Swap throttled. Do not draw.
858 state
.DidSwapBuffers();
859 state
.OnBeginImplFrameDeadline();
860 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
861 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
862 state
.DidSwapBuffersComplete();
864 // Haven't draw since last commit, do not begin new main frame.
865 state
.SetNeedsCommit();
866 state
.OnBeginImplFrame();
867 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
868 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
870 // At BeginImplFrame deadline, draw.
871 state
.OnBeginImplFrameDeadline();
872 EXPECT_ACTION_UPDATE_STATE(
873 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
874 state
.DidSwapBuffers();
875 state
.DidDrawIfPossibleCompleted(DRAW_SUCCESS
);
876 state
.DidSwapBuffersComplete();
878 // Now will be able to start main frame.
879 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
880 EXPECT_FALSE(state
.needs_redraw());
881 EXPECT_ACTION_UPDATE_STATE(
882 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
885 TEST(SchedulerStateMachineTest
,
886 TestFullCycleWithMainThreadLowLatencyMode_ImplSidePaint
) {
887 SchedulerSettings scheduler_settings
;
888 scheduler_settings
.main_thread_should_always_be_low_latency
= true;
889 scheduler_settings
.impl_side_painting
= true;
890 StateMachine
state(scheduler_settings
);
893 // Start clean and set commit.
894 state
.SetNeedsCommit();
897 state
.OnBeginImplFrame();
898 EXPECT_ACTION_UPDATE_STATE(
899 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
901 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
902 EXPECT_FALSE(state
.NeedsCommit());
903 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
905 // Tell the scheduler the frame finished.
906 state
.NotifyBeginMainFrameStarted();
907 state
.NotifyReadyToCommit();
908 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
);
911 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
913 // Now commit should wait for activation.
915 SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_ACTIVATION
);
917 // No activation yet, so this commit is not drawn yet. Force to draw this
918 // frame, and still block BeginMainFrame.
919 state
.SetNeedsRedraw(true);
920 state
.SetNeedsCommit();
921 state
.OnBeginImplFrameDeadline();
922 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
923 EXPECT_ACTION_UPDATE_STATE(
924 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
925 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
927 // Cannot BeginMainFrame yet since last commit is not yet activated and drawn.
928 state
.OnBeginImplFrame();
930 SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_ACTIVATION
);
931 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
933 // Now activate sync tree.
934 state
.NotifyReadyToActivate();
935 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE
);
936 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
937 EXPECT_TRUE(state
.active_tree_needs_first_draw());
938 EXPECT_TRUE(state
.needs_redraw());
939 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_DRAW
);
941 // Swap throttled. Do not draw.
942 state
.DidSwapBuffers();
943 state
.OnBeginImplFrameDeadline();
944 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
945 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
946 state
.DidSwapBuffersComplete();
948 // Haven't draw since last commit, do not begin new main frame.
949 state
.OnBeginImplFrame();
950 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
951 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
953 // At BeginImplFrame deadline, draw. This draws unblocks BeginMainFrame.
954 state
.OnBeginImplFrameDeadline();
955 EXPECT_ACTION_UPDATE_STATE(
956 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
957 state
.DidSwapBuffers();
958 state
.DidDrawIfPossibleCompleted(DRAW_SUCCESS
);
959 state
.DidSwapBuffersComplete();
961 // Now will be able to start main frame.
962 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
963 EXPECT_FALSE(state
.needs_redraw());
964 EXPECT_ACTION_UPDATE_STATE(
965 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
968 TEST(SchedulerStateMachineTest
, TestFullCycleWithCommitRequestInbetween
) {
969 SchedulerSettings default_scheduler_settings
;
970 StateMachine
state(default_scheduler_settings
);
973 // Start clean and set commit.
974 state
.SetNeedsCommit();
977 state
.OnBeginImplFrame();
978 EXPECT_ACTION_UPDATE_STATE(
979 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
981 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
982 EXPECT_FALSE(state
.NeedsCommit());
983 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
985 // Request another commit while the commit is in flight.
986 state
.SetNeedsCommit();
987 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
989 // Tell the scheduler the frame finished.
990 state
.NotifyBeginMainFrameStarted();
991 state
.NotifyReadyToCommit();
992 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
);
995 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
996 EXPECT_TRUE(state
.active_tree_needs_first_draw());
997 EXPECT_TRUE(state
.needs_redraw());
999 // Expect to do nothing until BeginImplFrame deadline.
1000 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1002 // At BeginImplFrame deadline, draw.
1003 state
.OnBeginImplFrameDeadline();
1004 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1005 EXPECT_ACTION_UPDATE_STATE(
1006 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1007 state
.DidSwapBuffers();
1008 state
.DidDrawIfPossibleCompleted(DRAW_SUCCESS
);
1009 state
.DidSwapBuffersComplete();
1011 // Should be synchronized, no draw needed, no action needed.
1012 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1013 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
1014 EXPECT_FALSE(state
.needs_redraw());
1016 // Next BeginImplFrame should initiate second commit.
1017 state
.OnBeginImplFrame();
1018 EXPECT_ACTION_UPDATE_STATE(
1019 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1022 TEST(SchedulerStateMachineTest
, TestRequestCommitInvisible
) {
1023 SchedulerSettings default_scheduler_settings
;
1024 StateMachine
state(default_scheduler_settings
);
1025 state
.SetCanStart();
1026 state
.UpdateState(state
.NextAction());
1027 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1028 state
.SetNeedsCommit();
1029 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1032 // See ThreadProxy::BeginMainFrame "EarlyOut_NotVisible" /
1033 // "EarlyOut_OutputSurfaceLost" cases.
1034 TEST(SchedulerStateMachineTest
, TestAbortBeginMainFrameBecauseInvisible
) {
1035 SchedulerSettings default_scheduler_settings
;
1036 StateMachine
state(default_scheduler_settings
);
1039 // Start clean and set commit.
1040 state
.SetNeedsCommit();
1042 // Begin the frame while visible.
1043 state
.OnBeginImplFrame();
1044 EXPECT_ACTION_UPDATE_STATE(
1045 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1046 EXPECT_COMMIT_STATE(
1047 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
1048 EXPECT_FALSE(state
.NeedsCommit());
1049 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1051 // Become invisible and abort BeginMainFrame.
1052 state
.SetVisible(false);
1053 state
.BeginMainFrameAborted(CommitEarlyOutReason::ABORTED_NOT_VISIBLE
);
1055 // NeedsCommit should now be true again because we never actually did a
1057 EXPECT_TRUE(state
.NeedsCommit());
1059 // We should now be back in the idle state as if we never started the frame.
1060 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
1061 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1063 // We shouldn't do anything on the BeginImplFrame deadline.
1064 state
.OnBeginImplFrameDeadline();
1065 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1067 // Become visible again.
1068 state
.SetVisible(true);
1070 // Although we have aborted on this frame and haven't cancelled the commit
1071 // (i.e. need another), don't send another BeginMainFrame yet.
1072 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
1073 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1074 EXPECT_TRUE(state
.NeedsCommit());
1076 // Start a new frame.
1077 state
.OnBeginImplFrame();
1078 EXPECT_ACTION_UPDATE_STATE(
1079 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1081 // We should be starting the commit now.
1082 EXPECT_COMMIT_STATE(
1083 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
1084 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1087 // See ThreadProxy::BeginMainFrame "EarlyOut_NoUpdates" case.
1088 TEST(SchedulerStateMachineTest
, TestAbortBeginMainFrameBecauseCommitNotNeeded
) {
1089 SchedulerSettings default_scheduler_settings
;
1090 StateMachine
state(default_scheduler_settings
);
1091 state
.SetCanStart();
1092 state
.UpdateState(state
.NextAction());
1093 state
.DidCreateAndInitializeOutputSurface();
1094 state
.SetVisible(true);
1095 state
.SetCanDraw(true);
1097 // Get into a begin frame / commit state.
1098 state
.SetNeedsCommit();
1099 state
.OnBeginImplFrame();
1100 EXPECT_ACTION_UPDATE_STATE(
1101 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1102 EXPECT_COMMIT_STATE(
1103 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
1104 EXPECT_FALSE(state
.NeedsCommit());
1105 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1107 // Abort the commit, true means that the BeginMainFrame was sent but there
1108 // was no work to do on the main thread.
1109 state
.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES
);
1111 // NeedsCommit should now be false because the commit was actually handled.
1112 EXPECT_FALSE(state
.NeedsCommit());
1114 // Even though the commit was aborted, we still expect to draw the new frame.
1115 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1116 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1117 state
.OnBeginImplFrameDeadline();
1118 EXPECT_ACTION_UPDATE_STATE(
1119 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1120 state
.DidSwapBuffers();
1121 state
.DidSwapBuffersComplete();
1122 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1124 // Verify another commit doesn't start on another frame either.
1125 EXPECT_FALSE(state
.NeedsCommit());
1126 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
1128 state
.OnBeginImplFrame();
1129 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1130 state
.OnBeginImplFrameDeadline();
1131 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1133 // Verify another commit can start if requested, though.
1134 state
.SetNeedsCommit();
1135 EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE
);
1136 state
.OnBeginImplFrame();
1137 EXPECT_ACTION(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1140 TEST(SchedulerStateMachineTest
, TestFirstContextCreation
) {
1141 SchedulerSettings default_scheduler_settings
;
1142 StateMachine
state(default_scheduler_settings
);
1143 state
.SetCanStart();
1144 state
.SetVisible(true);
1145 state
.SetCanDraw(true);
1147 EXPECT_ACTION_UPDATE_STATE(
1148 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
);
1149 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1150 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1152 // Check that the first init does not SetNeedsCommit.
1153 state
.OnBeginImplFrame();
1154 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1155 state
.OnBeginImplFrameDeadline();
1156 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1158 // Check that a needs commit initiates a BeginMainFrame.
1159 state
.SetNeedsCommit();
1160 state
.OnBeginImplFrame();
1161 EXPECT_ACTION_UPDATE_STATE(
1162 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1165 TEST(SchedulerStateMachineTest
, TestContextLostWhenCompletelyIdle
) {
1166 SchedulerSettings default_scheduler_settings
;
1167 StateMachine
state(default_scheduler_settings
);
1170 EXPECT_NE(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
,
1171 state
.NextAction());
1172 state
.DidLoseOutputSurface();
1174 EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
);
1175 state
.UpdateState(state
.NextAction());
1177 // Once context recreation begins, nothing should happen.
1178 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1180 // Recreate the context.
1181 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1183 // When the context is recreated, we should begin a commit.
1184 state
.OnBeginImplFrame();
1185 EXPECT_ACTION_UPDATE_STATE(
1186 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1189 TEST(SchedulerStateMachineTest
,
1190 TestContextLostWhenIdleAndCommitRequestedWhileRecreating
) {
1191 SchedulerSettings default_scheduler_settings
;
1192 // We use impl side painting because it's the more complicated version.
1193 default_scheduler_settings
.impl_side_painting
= true;
1194 StateMachine
state(default_scheduler_settings
);
1197 EXPECT_NE(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
,
1198 state
.NextAction());
1199 state
.DidLoseOutputSurface();
1200 EXPECT_EQ(state
.output_surface_state(),
1201 SchedulerStateMachine::OUTPUT_SURFACE_LOST
);
1203 EXPECT_ACTION_UPDATE_STATE(
1204 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
);
1205 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1207 // Once context recreation begins, nothing should happen.
1208 state
.OnBeginImplFrame();
1209 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1210 state
.OnBeginImplFrameDeadline();
1211 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1213 // While context is recreating, commits shouldn't begin.
1214 state
.SetNeedsCommit();
1215 state
.OnBeginImplFrame();
1216 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1217 state
.OnBeginImplFrameDeadline();
1218 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1220 // Recreate the context
1221 state
.DidCreateAndInitializeOutputSurface();
1222 EXPECT_EQ(state
.output_surface_state(),
1223 SchedulerStateMachine::OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT
);
1224 EXPECT_FALSE(state
.RedrawPending());
1226 // When the context is recreated, we wait until the next BeginImplFrame
1228 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1230 // When the BeginFrame comes in we should begin a commit
1231 state
.OnBeginImplFrame();
1232 EXPECT_ACTION_UPDATE_STATE(
1233 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1234 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1235 EXPECT_COMMIT_STATE(
1236 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
1238 // Until that commit finishes, we shouldn't be drawing or animate.
1239 state
.OnBeginImplFrameDeadline();
1240 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1242 // Finish the commit, which should make the surface active.
1243 state
.NotifyBeginMainFrameStarted();
1244 state
.NotifyReadyToCommit();
1245 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
1246 EXPECT_EQ(state
.output_surface_state(),
1247 SchedulerStateMachine::OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION
);
1248 state
.NotifyReadyToActivate();
1249 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE
);
1250 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1251 EXPECT_EQ(state
.output_surface_state(),
1252 SchedulerStateMachine::OUTPUT_SURFACE_ACTIVE
);
1254 // Finishing the first commit after initializing an output surface should
1255 // automatically cause a redraw.
1256 EXPECT_TRUE(state
.RedrawPending());
1257 state
.OnBeginImplFrame();
1258 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1259 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1260 state
.OnBeginImplFrameDeadline();
1261 EXPECT_ACTION_UPDATE_STATE(
1262 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1263 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1264 EXPECT_FALSE(state
.RedrawPending());
1266 // Next frame as no work to do.
1267 state
.OnBeginImplFrame();
1268 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1269 state
.OnBeginImplFrameDeadline();
1270 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1272 // Once the context is recreated, whether we draw should be based on
1273 // SetCanDraw if waiting on first draw after activate.
1274 state
.SetNeedsRedraw(true);
1275 state
.OnBeginImplFrame();
1276 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1277 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1278 state
.OnBeginImplFrameDeadline();
1279 EXPECT_ACTION(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1280 state
.SetCanDraw(false);
1281 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1282 state
.SetCanDraw(true);
1283 EXPECT_ACTION_UPDATE_STATE(
1284 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1285 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1287 // Once the context is recreated, whether we draw should be based on
1288 // SetCanDraw if waiting on first draw after activate.
1289 state
.SetNeedsRedraw(true);
1290 state
.SetNeedsCommit();
1291 state
.OnBeginImplFrame();
1292 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1293 EXPECT_ACTION_UPDATE_STATE(
1294 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1295 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1296 // Activate so we need the first draw
1297 state
.NotifyBeginMainFrameStarted();
1298 state
.NotifyReadyToCommit();
1299 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
1300 state
.NotifyReadyToActivate();
1301 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE
);
1302 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1303 EXPECT_TRUE(state
.active_tree_needs_first_draw());
1304 EXPECT_TRUE(state
.needs_redraw());
1306 state
.OnBeginImplFrameDeadline();
1307 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1308 EXPECT_ACTION(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1309 state
.SetCanDraw(false);
1310 EXPECT_ACTION(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT
);
1311 state
.SetCanDraw(true);
1312 EXPECT_ACTION(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1315 TEST(SchedulerStateMachineTest
, TestContextLostWhileCommitInProgress
) {
1316 SchedulerSettings scheduler_settings
;
1317 StateMachine
state(scheduler_settings
);
1320 // Get a commit in flight.
1321 state
.SetNeedsCommit();
1323 // Set damage and expect a draw.
1324 state
.SetNeedsRedraw(true);
1325 state
.OnBeginImplFrame();
1326 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1327 EXPECT_ACTION_UPDATE_STATE(
1328 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1329 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1330 state
.OnBeginImplFrameDeadline();
1331 EXPECT_ACTION_UPDATE_STATE(
1332 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1333 state
.DidSwapBuffers();
1334 state
.DidSwapBuffersComplete();
1335 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1337 // Cause a lost context while the BeginMainFrame is in flight.
1338 state
.DidLoseOutputSurface();
1340 // Ask for another draw. Expect nothing happens.
1341 state
.SetNeedsRedraw(true);
1342 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1344 // Finish the frame, and commit.
1345 state
.NotifyBeginMainFrameStarted();
1346 state
.NotifyReadyToCommit();
1347 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
1349 // We will abort the draw when the output surface is lost if we are
1350 // waiting for the first draw to unblock the main thread.
1351 EXPECT_TRUE(state
.active_tree_needs_first_draw());
1352 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT
);
1354 // Expect to begin context recreation only in BEGIN_IMPL_FRAME_STATE_IDLE
1355 EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE
);
1356 EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
);
1358 state
.OnBeginImplFrame();
1359 EXPECT_IMPL_FRAME_STATE(
1360 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING
);
1361 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1363 state
.OnBeginImplFrameDeadlinePending();
1364 EXPECT_IMPL_FRAME_STATE(
1365 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME
);
1366 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1368 state
.OnBeginImplFrameDeadline();
1369 EXPECT_IMPL_FRAME_STATE(
1370 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
);
1371 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1374 TEST(SchedulerStateMachineTest
,
1375 TestContextLostWhileCommitInProgressAndAnotherCommitRequested
) {
1376 SchedulerSettings scheduler_settings
;
1377 StateMachine
state(scheduler_settings
);
1380 // Get a commit in flight.
1381 state
.SetNeedsCommit();
1382 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1384 // Set damage and expect a draw.
1385 state
.SetNeedsRedraw(true);
1386 state
.OnBeginImplFrame();
1387 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1388 EXPECT_ACTION_UPDATE_STATE(
1389 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1390 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1391 state
.OnBeginImplFrameDeadline();
1392 EXPECT_ACTION_UPDATE_STATE(
1393 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1394 state
.DidSwapBuffers();
1395 state
.DidSwapBuffersComplete();
1396 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1398 // Cause a lost context while the BeginMainFrame is in flight.
1399 state
.DidLoseOutputSurface();
1401 // Ask for another draw and also set needs commit. Expect nothing happens.
1402 state
.SetNeedsRedraw(true);
1403 state
.SetNeedsCommit();
1404 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1406 // Finish the frame, and commit.
1407 state
.NotifyBeginMainFrameStarted();
1408 state
.NotifyReadyToCommit();
1409 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
1410 EXPECT_TRUE(state
.active_tree_needs_first_draw());
1412 // Because the output surface is missing, we expect the draw to abort.
1413 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT
);
1415 // Expect to begin context recreation only in BEGIN_IMPL_FRAME_STATE_IDLE
1416 EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE
);
1417 EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
);
1419 state
.OnBeginImplFrame();
1420 EXPECT_IMPL_FRAME_STATE(
1421 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING
);
1422 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1424 state
.OnBeginImplFrameDeadlinePending();
1425 EXPECT_IMPL_FRAME_STATE(
1426 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME
);
1427 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1429 state
.OnBeginImplFrameDeadline();
1430 EXPECT_IMPL_FRAME_STATE(
1431 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE
);
1432 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1434 state
.OnBeginImplFrameIdle();
1435 EXPECT_ACTION_UPDATE_STATE(
1436 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
);
1438 // After we get a new output surface, the commit flow should start.
1439 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1440 state
.OnBeginImplFrame();
1441 EXPECT_ACTION_UPDATE_STATE(
1442 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1443 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1444 state
.NotifyBeginMainFrameStarted();
1445 state
.NotifyReadyToCommit();
1446 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
1447 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1448 state
.OnBeginImplFrameDeadline();
1449 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1450 EXPECT_ACTION_UPDATE_STATE(
1451 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1452 state
.DidSwapBuffers();
1453 state
.DidSwapBuffersComplete();
1454 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1457 TEST(SchedulerStateMachineTest
, DontDrawBeforeCommitAfterLostOutputSurface
) {
1458 SchedulerSettings default_scheduler_settings
;
1459 StateMachine
state(default_scheduler_settings
);
1462 state
.SetNeedsRedraw(true);
1464 // Cause a lost output surface, and restore it.
1465 state
.DidLoseOutputSurface();
1466 EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
);
1467 state
.UpdateState(state
.NextAction());
1468 state
.DidCreateAndInitializeOutputSurface();
1470 EXPECT_FALSE(state
.RedrawPending());
1471 state
.OnBeginImplFrame();
1472 EXPECT_ACTION(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1475 TEST(SchedulerStateMachineTest
,
1476 TestPendingActivationsShouldBeForcedAfterLostOutputSurface
) {
1477 SchedulerSettings settings
;
1478 settings
.impl_side_painting
= true;
1479 StateMachine
state(settings
);
1482 state
.SetCommitState(
1483 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
1485 // Cause a lost context.
1486 state
.DidLoseOutputSurface();
1488 state
.NotifyBeginMainFrameStarted();
1489 state
.NotifyReadyToCommit();
1490 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
1492 EXPECT_TRUE(state
.PendingActivationsShouldBeForced());
1493 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE
);
1495 EXPECT_TRUE(state
.PendingDrawsShouldBeAborted());
1496 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT
);
1499 TEST(SchedulerStateMachineTest
, TestNoBeginMainFrameWhenInvisible
) {
1500 SchedulerSettings default_scheduler_settings
;
1501 StateMachine
state(default_scheduler_settings
);
1502 state
.SetCanStart();
1503 state
.UpdateState(state
.NextAction());
1504 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1505 state
.SetVisible(false);
1506 state
.SetNeedsCommit();
1507 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1510 TEST(SchedulerStateMachineTest
, TestFinishCommitWhenCommitInProgress
) {
1511 SchedulerSettings default_scheduler_settings
;
1512 StateMachine
state(default_scheduler_settings
);
1513 state
.SetCanStart();
1514 state
.UpdateState(state
.NextAction());
1515 state
.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1516 state
.SetVisible(false);
1517 state
.SetCommitState(
1518 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT
);
1519 state
.SetNeedsCommit();
1521 state
.NotifyBeginMainFrameStarted();
1522 state
.NotifyReadyToCommit();
1523 EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT
);
1524 state
.UpdateState(state
.NextAction());
1526 EXPECT_TRUE(state
.active_tree_needs_first_draw());
1527 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT
);
1530 TEST(SchedulerStateMachineTest
, TestInitialActionsWhenContextLost
) {
1531 SchedulerSettings default_scheduler_settings
;
1532 StateMachine
state(default_scheduler_settings
);
1534 state
.SetNeedsCommit();
1535 state
.DidLoseOutputSurface();
1537 // When we are visible, we normally want to begin output surface creation
1538 // as soon as possible.
1539 EXPECT_ACTION_UPDATE_STATE(
1540 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION
);
1542 state
.DidCreateAndInitializeOutputSurface();
1543 EXPECT_EQ(state
.output_surface_state(),
1544 SchedulerStateMachine::OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT
);
1546 // We should not send a BeginMainFrame when we are invisible, even if we've
1547 // lost the output surface and are trying to get the first commit, since the
1548 // main thread will just abort anyway.
1549 state
.SetVisible(false);
1550 EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE
);
1553 TEST(SchedulerStateMachineTest
, ReportIfNotDrawing
) {
1554 SchedulerSettings default_scheduler_settings
;
1555 StateMachine
state(default_scheduler_settings
);
1557 EXPECT_FALSE(state
.PendingDrawsShouldBeAborted());
1559 state
.SetCanDraw(false);
1560 state
.SetVisible(true);
1561 EXPECT_TRUE(state
.PendingDrawsShouldBeAborted());
1563 state
.SetCanDraw(true);
1564 state
.SetVisible(false);
1565 EXPECT_TRUE(state
.PendingDrawsShouldBeAborted());
1567 state
.SetCanDraw(false);
1568 state
.SetVisible(false);
1569 EXPECT_TRUE(state
.PendingDrawsShouldBeAborted());
1571 state
.SetCanDraw(true);
1572 state
.SetVisible(true);
1573 EXPECT_FALSE(state
.PendingDrawsShouldBeAborted());
1576 TEST(SchedulerStateMachineTest
,
1577 TestTriggerDeadlineImmediatelyAfterAbortedCommit
) {
1578 SchedulerSettings settings
;
1579 settings
.impl_side_painting
= true;
1580 StateMachine
state(settings
);
1583 // This test mirrors what happens during the first frame of a scroll gesture.
1584 // First we get the input event and a BeginFrame.
1585 state
.OnBeginImplFrame();
1587 // As a response the compositor requests a redraw and a commit to tell the
1588 // main thread about the new scroll offset.
1589 state
.SetNeedsRedraw(true);
1590 state
.SetNeedsCommit();
1592 // We should start the commit normally.
1593 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1594 EXPECT_ACTION_UPDATE_STATE(
1595 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1596 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1598 // Since only the scroll offset changed, the main thread will abort the
1600 state
.BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES
);
1602 // Since the commit was aborted, we should draw right away instead of waiting
1603 // for the deadline.
1604 EXPECT_TRUE(state
.ShouldTriggerBeginImplFrameDeadlineImmediately());
1607 void FinishPreviousCommitAndDrawWithoutExitingDeadline(
1608 StateMachine
* state_ptr
) {
1609 // Gross, but allows us to use macros below.
1610 StateMachine
& state
= *state_ptr
;
1612 state
.NotifyBeginMainFrameStarted();
1613 state
.NotifyReadyToCommit();
1614 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
1615 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1616 state
.NotifyReadyToActivate();
1617 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE
);
1618 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1620 state
.OnBeginImplFrame();
1621 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1622 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1624 EXPECT_TRUE(state
.ShouldTriggerBeginImplFrameDeadlineImmediately());
1625 state
.OnBeginImplFrameDeadline();
1626 EXPECT_ACTION_UPDATE_STATE(
1627 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1628 state
.DidSwapBuffers();
1631 TEST(SchedulerStateMachineTest
, TestImplLatencyTakesPriority
) {
1632 SchedulerSettings settings
;
1633 settings
.impl_side_painting
= true;
1634 StateMachine
state(settings
);
1637 // This test ensures that impl-draws are prioritized over main thread updates
1638 // in prefer impl latency mode.
1639 state
.SetNeedsRedraw(true);
1640 state
.SetNeedsCommit();
1641 state
.OnBeginImplFrame();
1642 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1643 EXPECT_ACTION_UPDATE_STATE(
1644 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1645 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1647 // Verify the deadline is not triggered early until we enter
1648 // prefer impl latency mode.
1649 EXPECT_FALSE(state
.ShouldTriggerBeginImplFrameDeadlineImmediately());
1650 state
.SetImplLatencyTakesPriority(true);
1651 EXPECT_TRUE(state
.ShouldTriggerBeginImplFrameDeadlineImmediately());
1653 // Trigger the deadline.
1654 state
.OnBeginImplFrameDeadline();
1655 EXPECT_ACTION_UPDATE_STATE(
1656 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1657 state
.DidSwapBuffers();
1658 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1659 state
.DidSwapBuffersComplete();
1661 // Request a new commit and finish the previous one.
1662 state
.SetNeedsCommit();
1663 FinishPreviousCommitAndDrawWithoutExitingDeadline(&state
);
1664 EXPECT_ACTION_UPDATE_STATE(
1665 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1666 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1667 state
.DidSwapBuffersComplete();
1668 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1670 // Finish the previous commit and draw it.
1671 FinishPreviousCommitAndDrawWithoutExitingDeadline(&state
);
1672 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1674 // Verify we do not send another BeginMainFrame if was are swap throttled
1675 // and did not just swap.
1676 state
.SetNeedsCommit();
1677 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1678 state
.OnBeginImplFrame();
1679 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1680 EXPECT_FALSE(state
.ShouldTriggerBeginImplFrameDeadlineImmediately());
1681 state
.OnBeginImplFrameDeadline();
1682 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1685 TEST(SchedulerStateMachineTest
,
1686 TestTriggerDeadlineImmediatelyOnLostOutputSurface
) {
1687 SchedulerSettings default_scheduler_settings
;
1688 StateMachine
state(default_scheduler_settings
);
1691 state
.SetNeedsCommit();
1693 state
.OnBeginImplFrame();
1694 EXPECT_ACTION_UPDATE_STATE(
1695 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1696 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1697 EXPECT_FALSE(state
.ShouldTriggerBeginImplFrameDeadlineImmediately());
1699 state
.DidLoseOutputSurface();
1700 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1701 // The deadline should be triggered immediately when output surface is lost.
1702 EXPECT_TRUE(state
.ShouldTriggerBeginImplFrameDeadlineImmediately());
1705 TEST(SchedulerStateMachineTest
, TestSetNeedsAnimate
) {
1706 SchedulerSettings settings
;
1707 settings
.impl_side_painting
= true;
1708 StateMachine
state(settings
);
1711 // Test requesting an animation that, when run, causes us to draw.
1712 state
.SetNeedsAnimate();
1713 EXPECT_TRUE(state
.BeginFrameNeeded());
1714 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1716 state
.OnBeginImplFrame();
1717 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1719 state
.OnBeginImplFrameDeadlinePending();
1720 state
.OnBeginImplFrameDeadline();
1721 EXPECT_ACTION_UPDATE_STATE(
1722 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1725 TEST(SchedulerStateMachineTest
, TestAnimateBeforeCommit
) {
1726 SchedulerSettings settings
;
1727 settings
.impl_side_painting
= true;
1728 StateMachine
state(settings
);
1731 // Check that animations are updated before we start a commit.
1732 state
.SetNeedsAnimate();
1733 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1734 state
.SetNeedsCommit();
1735 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1736 EXPECT_TRUE(state
.BeginFrameNeeded());
1738 state
.OnBeginImplFrame();
1739 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1740 EXPECT_ACTION_UPDATE_STATE(
1741 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1743 state
.OnBeginImplFrameDeadlinePending();
1744 state
.OnBeginImplFrameDeadline();
1745 EXPECT_ACTION_UPDATE_STATE(
1746 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1749 TEST(SchedulerStateMachineTest
, TestAnimateAfterCommitBeforeDraw
) {
1750 SchedulerSettings settings
;
1751 settings
.impl_side_painting
= true;
1752 StateMachine
state(settings
);
1755 // Check that animations are updated before we start a commit.
1756 state
.SetNeedsAnimate();
1757 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1758 state
.SetNeedsCommit();
1759 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1760 EXPECT_TRUE(state
.BeginFrameNeeded());
1762 state
.OnBeginImplFrame();
1763 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1764 EXPECT_ACTION_UPDATE_STATE(
1765 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);
1767 state
.NotifyBeginMainFrameStarted();
1768 state
.NotifyReadyToCommit();
1769 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT
);
1771 state
.OnBeginImplFrameDeadlinePending();
1772 state
.OnBeginImplFrameDeadline();
1773 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1774 EXPECT_ACTION_UPDATE_STATE(
1775 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1778 TEST(SchedulerStateMachineTest
, TestSetNeedsAnimateAfterAnimate
) {
1779 SchedulerSettings settings
;
1780 settings
.impl_side_painting
= true;
1781 StateMachine
state(settings
);
1784 // Test requesting an animation after we have already animated during this
1786 state
.SetNeedsRedraw(true);
1787 EXPECT_TRUE(state
.BeginFrameNeeded());
1788 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1790 state
.OnBeginImplFrame();
1791 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE
);
1793 state
.SetNeedsAnimate();
1794 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1796 state
.OnBeginImplFrameDeadline();
1797 EXPECT_ACTION_UPDATE_STATE(
1798 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE
);
1801 TEST(SchedulerStateMachineTest
, TestForwardBeginFramesToChildren
) {
1802 SchedulerSettings settings
;
1803 StateMachine
state(settings
);
1806 EXPECT_FALSE(state
.BeginFrameNeeded());
1807 state
.SetChildrenNeedBeginFrames(true);
1808 EXPECT_TRUE(state
.BeginFrameNeeded());
1811 TEST(SchedulerStateMachineTest
, TestDeferCommit
) {
1812 SchedulerSettings settings
;
1813 StateMachine
state(settings
);
1816 state
.SetDeferCommits(true);
1818 state
.SetNeedsCommit();
1819 EXPECT_TRUE(state
.BeginFrameNeeded());
1820 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1822 state
.OnBeginImplFrame();
1823 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1825 state
.OnBeginImplFrameDeadline();
1826 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE
);
1828 state
.SetDeferCommits(false);
1829 state
.OnBeginImplFrame();
1830 EXPECT_ACTION_UPDATE_STATE(
1831 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME
);