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 "cc/scheduler/scheduler.h"
8 #include "testing/gtest/include/gtest/gtest.h"
10 #define EXPECT_ACTION_UPDATE_STATE(action) \
11 EXPECT_EQ(action, state.NextAction()) << *state.AsValue(); \
12 if (action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE || \
13 action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED) { \
14 if (SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW == \
15 state.CommitState() && \
16 SchedulerStateMachine::OUTPUT_SURFACE_ACTIVE != \
17 state.output_surface_state()) \
19 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, \
20 state.begin_impl_frame_state()) \
21 << *state.AsValue(); \
23 state.UpdateState(action); \
24 if (action == SchedulerStateMachine::ACTION_NONE) { \
25 if (state.begin_impl_frame_state() == \
26 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) \
27 state.OnBeginImplFrameDeadlinePending(); \
28 if (state.begin_impl_frame_state() == \
29 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) \
30 state.OnBeginImplFrameIdle(); \
37 const SchedulerStateMachine::BeginImplFrameState all_begin_impl_frame_states[] =
38 {SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE,
39 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
40 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
41 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, };
43 const SchedulerStateMachine::CommitState all_commit_states[] = {
44 SchedulerStateMachine::COMMIT_STATE_IDLE,
45 SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
46 SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
47 SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, };
49 // Exposes the protected state fields of the SchedulerStateMachine for testing
50 class StateMachine : public SchedulerStateMachine {
52 explicit StateMachine(const SchedulerSettings& scheduler_settings)
53 : SchedulerStateMachine(scheduler_settings) {}
55 void CreateAndInitializeOutputSurfaceWithActivatedCommit() {
56 DidCreateAndInitializeOutputSurface();
57 output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
60 void SetCommitState(CommitState cs) { commit_state_ = cs; }
61 CommitState CommitState() const { return commit_state_; }
63 ForcedRedrawOnTimeoutState ForcedRedrawState() const {
64 return forced_redraw_state_;
67 void SetBeginImplFrameState(BeginImplFrameState bifs) {
68 begin_impl_frame_state_ = bifs;
71 BeginImplFrameState begin_impl_frame_state() const {
72 return begin_impl_frame_state_;
75 OutputSurfaceState output_surface_state() const {
76 return output_surface_state_;
79 bool NeedsCommit() const { return needs_commit_; }
81 void SetNeedsRedraw(bool b) { needs_redraw_ = b; }
83 void SetNeedsForcedRedrawForTimeout(bool b) {
84 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT;
85 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
87 bool NeedsForcedRedrawForTimeout() const {
88 return forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE;
91 void SetNeedsForcedRedrawForReadback() {
92 readback_state_ = READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK;
93 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
96 bool NeedsForcedRedrawForReadback() const {
97 return readback_state_ != READBACK_STATE_IDLE;
100 void SetActiveTreeNeedsFirstDraw(bool needs_first_draw) {
101 active_tree_needs_first_draw_ = needs_first_draw;
104 bool CanDraw() const { return can_draw_; }
105 bool Visible() const { return visible_; }
107 bool PendingActivationsShouldBeForced() const {
108 return SchedulerStateMachine::PendingActivationsShouldBeForced();
112 TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) {
113 SchedulerSettings default_scheduler_settings;
115 // If no commit needed, do nothing.
117 StateMachine state(default_scheduler_settings);
119 EXPECT_ACTION_UPDATE_STATE(
120 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION)
121 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
122 state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
123 state.SetNeedsRedraw(false);
124 state.SetVisible(true);
126 EXPECT_FALSE(state.BeginImplFrameNeeded());
128 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
129 EXPECT_FALSE(state.BeginImplFrameNeeded());
130 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
132 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
133 state.OnBeginImplFrameDeadline();
136 // If commit requested but can_start is still false, do nothing.
138 StateMachine state(default_scheduler_settings);
139 state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
140 state.SetNeedsRedraw(false);
141 state.SetVisible(true);
143 EXPECT_FALSE(state.BeginImplFrameNeeded());
145 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
146 EXPECT_FALSE(state.BeginImplFrameNeeded());
147 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
148 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
149 state.OnBeginImplFrameDeadline();
152 // If commit requested, begin a main frame.
154 StateMachine state(default_scheduler_settings);
155 state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE);
157 state.SetNeedsRedraw(false);
158 state.SetVisible(true);
159 EXPECT_FALSE(state.BeginImplFrameNeeded());
162 // Begin the frame, make sure needs_commit and commit_state update correctly.
164 StateMachine state(default_scheduler_settings);
166 state.UpdateState(state.NextAction());
167 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
168 state.SetVisible(true);
169 state.UpdateState(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
170 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
171 state.CommitState());
172 EXPECT_FALSE(state.NeedsCommit());
176 TEST(SchedulerStateMachineTest,
177 TestFailedDrawForAnimationCheckerboardSetsNeedsCommitAndDoesNotDrawAgain) {
178 SchedulerSettings default_scheduler_settings;
179 StateMachine state(default_scheduler_settings);
181 state.UpdateState(state.NextAction());
182 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
183 state.SetVisible(true);
184 state.SetCanDraw(true);
185 state.SetNeedsRedraw(true);
186 EXPECT_TRUE(state.RedrawPending());
187 EXPECT_TRUE(state.BeginImplFrameNeeded());
188 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
189 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
190 state.OnBeginImplFrameDeadline();
192 // We're drawing now.
193 EXPECT_ACTION_UPDATE_STATE(
194 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
195 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
197 EXPECT_FALSE(state.RedrawPending());
198 EXPECT_FALSE(state.CommitPending());
200 // Failing the draw makes us require a commit.
201 state.DidDrawIfPossibleCompleted(
202 DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
203 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
204 EXPECT_ACTION_UPDATE_STATE(
205 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
206 EXPECT_TRUE(state.RedrawPending());
207 EXPECT_TRUE(state.CommitPending());
210 TEST(SchedulerStateMachineTest, TestFailedDrawForMissingHighResNeedsCommit) {
211 SchedulerSettings default_scheduler_settings;
212 StateMachine state(default_scheduler_settings);
214 state.UpdateState(state.NextAction());
215 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
216 state.SetVisible(true);
217 state.SetCanDraw(true);
218 state.SetNeedsRedraw(true);
219 EXPECT_TRUE(state.RedrawPending());
220 EXPECT_TRUE(state.BeginImplFrameNeeded());
222 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
223 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
224 state.OnBeginImplFrameDeadline();
225 EXPECT_ACTION_UPDATE_STATE(
226 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
227 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
228 EXPECT_FALSE(state.RedrawPending());
229 EXPECT_FALSE(state.CommitPending());
231 // Missing high res content requires a commit (but not a redraw)
232 state.DidDrawIfPossibleCompleted(
233 DrawSwapReadbackResult::DRAW_ABORTED_MISSING_HIGH_RES_CONTENT);
234 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
235 EXPECT_ACTION_UPDATE_STATE(
236 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
237 EXPECT_FALSE(state.RedrawPending());
238 EXPECT_TRUE(state.CommitPending());
241 TEST(SchedulerStateMachineTest,
242 TestsetNeedsRedrawDuringFailedDrawDoesNotRemoveNeedsRedraw) {
243 SchedulerSettings default_scheduler_settings;
244 StateMachine state(default_scheduler_settings);
246 state.UpdateState(state.NextAction());
247 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
249 state.SetVisible(true);
250 state.SetCanDraw(true);
251 state.SetNeedsRedraw(true);
252 EXPECT_TRUE(state.RedrawPending());
253 EXPECT_TRUE(state.BeginImplFrameNeeded());
254 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
255 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
256 state.OnBeginImplFrameDeadline();
258 // We're drawing now.
259 EXPECT_ACTION_UPDATE_STATE(
260 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
261 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
262 EXPECT_FALSE(state.RedrawPending());
263 EXPECT_FALSE(state.CommitPending());
265 // While still in the same BeginMainFrame callback on the main thread,
266 // set needs redraw again. This should not redraw.
267 state.SetNeedsRedraw(true);
268 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
270 // Failing the draw for animation checkerboards makes us require a commit.
271 state.DidDrawIfPossibleCompleted(
272 DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
273 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
274 EXPECT_ACTION_UPDATE_STATE(
275 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
276 EXPECT_TRUE(state.RedrawPending());
279 void TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit(
280 bool deadline_scheduling_enabled) {
281 SchedulerSettings scheduler_settings;
282 scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ = 1;
283 scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
284 StateMachine state(scheduler_settings);
286 state.UpdateState(state.NextAction());
287 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
288 state.SetVisible(true);
289 state.SetCanDraw(true);
292 state.SetNeedsCommit();
293 if (!deadline_scheduling_enabled) {
294 EXPECT_ACTION_UPDATE_STATE(
295 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
297 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
298 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
299 if (deadline_scheduling_enabled) {
300 EXPECT_ACTION_UPDATE_STATE(
301 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
303 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
304 EXPECT_TRUE(state.CommitPending());
306 // Then initiate a draw.
307 state.SetNeedsRedraw(true);
308 state.OnBeginImplFrameDeadline();
309 EXPECT_ACTION_UPDATE_STATE(
310 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
313 state.DidDrawIfPossibleCompleted(
314 DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
315 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
316 EXPECT_TRUE(state.BeginImplFrameNeeded());
317 EXPECT_TRUE(state.RedrawPending());
318 // But the commit is ongoing.
319 EXPECT_TRUE(state.CommitPending());
321 // Finish the commit. Note, we should not yet be forcing a draw, but should
322 // continue the commit as usual.
323 state.FinishCommit();
324 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
325 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
326 EXPECT_TRUE(state.RedrawPending());
328 // The redraw should be forced at the end of the next BeginImplFrame.
329 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
330 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
331 state.OnBeginImplFrameDeadline();
332 EXPECT_ACTION_UPDATE_STATE(
333 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED);
336 TEST(SchedulerStateMachineTest,
337 TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit) {
338 bool deadline_scheduling_enabled = false;
339 TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit(
340 deadline_scheduling_enabled);
343 TEST(SchedulerStateMachineTest,
344 TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit_Deadline) {
345 bool deadline_scheduling_enabled = true;
346 TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit(
347 deadline_scheduling_enabled);
350 void TestFailedDrawsDoNotRestartForcedDraw(
351 bool deadline_scheduling_enabled) {
352 SchedulerSettings scheduler_settings;
354 scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ =
356 scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
357 scheduler_settings.impl_side_painting = true;
358 StateMachine state(scheduler_settings);
360 state.UpdateState(state.NextAction());
361 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
362 state.SetVisible(true);
363 state.SetCanDraw(true);
366 state.SetNeedsCommit();
367 if (!deadline_scheduling_enabled) {
368 EXPECT_ACTION_UPDATE_STATE(
369 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
371 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
372 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
373 if (deadline_scheduling_enabled) {
374 EXPECT_ACTION_UPDATE_STATE(
375 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
377 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
378 EXPECT_TRUE(state.CommitPending());
380 // Then initiate a draw.
381 state.SetNeedsRedraw(true);
382 state.OnBeginImplFrameDeadline();
383 EXPECT_ACTION_UPDATE_STATE(
384 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
386 // Fail the draw enough times to force a redraw,
387 // then once more for good measure.
388 for (int i = 0; i < draw_limit + 1; ++i) {
389 state.DidDrawIfPossibleCompleted(
390 DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
392 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
393 EXPECT_TRUE(state.BeginImplFrameNeeded());
394 EXPECT_TRUE(state.RedrawPending());
395 // But the commit is ongoing.
396 EXPECT_TRUE(state.CommitPending());
397 EXPECT_TRUE(state.ForcedRedrawState() ==
398 SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_COMMIT);
400 state.FinishCommit();
401 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
402 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
403 EXPECT_TRUE(state.RedrawPending());
404 EXPECT_FALSE(state.CommitPending());
406 // Now force redraw should be in waiting for activation
407 EXPECT_TRUE(state.ForcedRedrawState() ==
408 SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION);
410 // After failing additional draws, we should still be in a forced
411 // redraw, but not back in WAITING_FOR_COMMIT.
412 for (int i = 0; i < draw_limit + 1; ++i) {
413 state.DidDrawIfPossibleCompleted(
414 DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
416 EXPECT_TRUE(state.RedrawPending());
417 EXPECT_TRUE(state.ForcedRedrawState() ==
418 SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION);
421 TEST(SchedulerStateMachineTest,
422 TestFailedDrawsDoNotRestartForcedDraw) {
423 bool deadline_scheduling_enabled = false;
424 TestFailedDrawsDoNotRestartForcedDraw(
425 deadline_scheduling_enabled);
428 TEST(SchedulerStateMachineTest,
429 TestFailedDrawsDoNotRestartForcedDraw_Deadline) {
430 bool deadline_scheduling_enabled = true;
431 TestFailedDrawsDoNotRestartForcedDraw(
432 deadline_scheduling_enabled);
435 TEST(SchedulerStateMachineTest, TestFailedDrawIsRetriedInNextBeginImplFrame) {
436 SchedulerSettings default_scheduler_settings;
437 StateMachine state(default_scheduler_settings);
439 state.UpdateState(state.NextAction());
440 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
441 state.SetVisible(true);
442 state.SetCanDraw(true);
445 state.SetNeedsRedraw(true);
446 EXPECT_TRUE(state.BeginImplFrameNeeded());
447 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
448 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
449 state.OnBeginImplFrameDeadline();
450 EXPECT_TRUE(state.RedrawPending());
451 EXPECT_ACTION_UPDATE_STATE(
452 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
454 // Failing the draw for animation checkerboards makes us require a commit.
455 state.DidDrawIfPossibleCompleted(
456 DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS);
457 EXPECT_ACTION_UPDATE_STATE(
458 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
459 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
460 EXPECT_TRUE(state.RedrawPending());
462 // We should not be trying to draw again now, but we have a commit pending.
463 EXPECT_TRUE(state.BeginImplFrameNeeded());
464 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
465 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
467 // We should try to draw again at the end of the next BeginImplFrame on
469 state.OnBeginImplFrameDeadline();
470 EXPECT_ACTION_UPDATE_STATE(
471 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
472 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
475 TEST(SchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame) {
476 SchedulerSettings default_scheduler_settings;
477 StateMachine state(default_scheduler_settings);
479 state.UpdateState(state.NextAction());
480 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
481 state.SetVisible(true);
482 state.SetCanDraw(true);
483 state.SetNeedsRedraw(true);
485 // Draw the first frame.
486 EXPECT_TRUE(state.BeginImplFrameNeeded());
487 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
488 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
490 state.OnBeginImplFrameDeadline();
491 EXPECT_ACTION_UPDATE_STATE(
492 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
493 state.DidDrawIfPossibleCompleted(DrawSwapReadbackResult::DRAW_SUCCESS);
494 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
496 // Before the next BeginImplFrame, set needs redraw again.
497 // This should not redraw until the next BeginImplFrame.
498 state.SetNeedsRedraw(true);
499 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
501 // Move to another frame. This should now draw.
502 EXPECT_TRUE(state.BeginImplFrameNeeded());
503 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
505 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
507 state.OnBeginImplFrameDeadline();
508 EXPECT_ACTION_UPDATE_STATE(
509 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
510 state.DidDrawIfPossibleCompleted(DrawSwapReadbackResult::DRAW_SUCCESS);
511 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
513 // We just swapped, so we should proactively request another BeginImplFrame.
514 EXPECT_TRUE(state.BeginImplFrameNeeded());
517 TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginImplFrame) {
518 SchedulerSettings default_scheduler_settings;
520 // When not in BeginImplFrame deadline, or in BeginImplFrame deadline
521 // but not visible, don't draw.
522 size_t num_commit_states =
523 sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
524 size_t num_begin_impl_frame_states =
525 sizeof(all_begin_impl_frame_states) /
526 sizeof(SchedulerStateMachine::BeginImplFrameState);
527 for (size_t i = 0; i < num_commit_states; ++i) {
528 for (size_t j = 0; j < num_begin_impl_frame_states; ++j) {
529 StateMachine state(default_scheduler_settings);
531 state.UpdateState(state.NextAction());
532 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
533 state.SetCommitState(all_commit_states[i]);
534 state.SetBeginImplFrameState(all_begin_impl_frame_states[j]);
536 (all_begin_impl_frame_states[j] !=
537 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
538 state.SetVisible(visible);
540 // Case 1: needs_commit=false
541 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
544 // Case 2: needs_commit=true
545 state.SetNeedsCommit();
546 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
552 // When in BeginImplFrame deadline we should always draw for SetNeedsRedraw or
553 // SetNeedsForcedRedrawForReadback have been called... except if we're
554 // ready to commit, in which case we expect a commit first.
555 for (size_t i = 0; i < num_commit_states; ++i) {
556 for (size_t j = 0; j < 2; ++j) {
557 bool request_readback = j;
559 // Skip invalid states
560 if (request_readback &&
561 (SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW !=
562 all_commit_states[i]))
565 StateMachine state(default_scheduler_settings);
567 state.UpdateState(state.NextAction());
568 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
569 state.SetCanDraw(true);
570 state.SetCommitState(all_commit_states[i]);
571 state.SetBeginImplFrameState(
572 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
573 if (request_readback) {
574 state.SetNeedsForcedRedrawForReadback();
576 state.SetNeedsRedraw(true);
577 state.SetVisible(true);
580 SchedulerStateMachine::Action expected_action;
581 if (all_commit_states[i] ==
582 SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT) {
583 expected_action = SchedulerStateMachine::ACTION_COMMIT;
584 } else if (request_readback) {
585 if (all_commit_states[i] ==
586 SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW)
587 expected_action = SchedulerStateMachine::ACTION_DRAW_AND_READBACK;
589 expected_action = SchedulerStateMachine::ACTION_NONE;
592 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
595 // Case 1: needs_commit=false.
596 EXPECT_NE(state.BeginImplFrameNeeded(), request_readback)
598 EXPECT_EQ(expected_action, state.NextAction()) << *state.AsValue();
600 // Case 2: needs_commit=true.
601 state.SetNeedsCommit();
602 EXPECT_NE(state.BeginImplFrameNeeded(), request_readback)
604 EXPECT_EQ(expected_action, state.NextAction()) << *state.AsValue();
609 TEST(SchedulerStateMachineTest, TestNoCommitStatesRedrawWhenInvisible) {
610 SchedulerSettings default_scheduler_settings;
612 size_t num_commit_states =
613 sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
614 for (size_t i = 0; i < num_commit_states; ++i) {
615 // There shouldn't be any drawing regardless of BeginImplFrame.
616 for (size_t j = 0; j < 2; ++j) {
617 StateMachine state(default_scheduler_settings);
619 state.UpdateState(state.NextAction());
620 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
621 state.SetCommitState(all_commit_states[i]);
622 state.SetVisible(false);
623 state.SetNeedsRedraw(true);
625 state.SetBeginImplFrameState(
626 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE);
629 // Case 1: needs_commit=false.
630 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
633 // Case 2: needs_commit=true.
634 state.SetNeedsCommit();
635 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
642 TEST(SchedulerStateMachineTest, TestCanRedraw_StopsDraw) {
643 SchedulerSettings default_scheduler_settings;
645 size_t num_commit_states =
646 sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState);
647 for (size_t i = 0; i < num_commit_states; ++i) {
648 // There shouldn't be any drawing regardless of BeginImplFrame.
649 for (size_t j = 0; j < 2; ++j) {
650 StateMachine state(default_scheduler_settings);
652 state.UpdateState(state.NextAction());
653 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
654 state.SetCommitState(all_commit_states[i]);
655 state.SetVisible(false);
656 state.SetNeedsRedraw(true);
658 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
660 state.SetCanDraw(false);
661 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
667 TEST(SchedulerStateMachineTest,
668 TestCanRedrawWithWaitingForFirstDrawMakesProgress) {
669 SchedulerSettings default_scheduler_settings;
670 StateMachine state(default_scheduler_settings);
672 state.UpdateState(state.NextAction());
673 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
675 state.SetCommitState(
676 SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
677 state.SetActiveTreeNeedsFirstDraw(true);
678 state.SetNeedsCommit();
679 state.SetNeedsRedraw(true);
680 state.SetVisible(true);
681 state.SetCanDraw(false);
682 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
683 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
684 EXPECT_ACTION_UPDATE_STATE(
685 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
686 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
687 state.FinishCommit();
688 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
689 state.OnBeginImplFrameDeadline();
690 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
691 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
694 TEST(SchedulerStateMachineTest, TestsetNeedsCommitIsNotLost) {
695 SchedulerSettings default_scheduler_settings;
696 StateMachine state(default_scheduler_settings);
698 state.UpdateState(state.NextAction());
699 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
700 state.SetNeedsCommit();
701 state.SetVisible(true);
702 state.SetCanDraw(true);
704 EXPECT_TRUE(state.BeginImplFrameNeeded());
707 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
708 EXPECT_ACTION_UPDATE_STATE(
709 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
710 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
711 state.CommitState());
713 // Now, while the frame is in progress, set another commit.
714 state.SetNeedsCommit();
715 EXPECT_TRUE(state.NeedsCommit());
717 // Let the frame finish.
718 state.FinishCommit();
719 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
720 state.CommitState());
722 // Expect to commit regardless of BeginImplFrame state.
723 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
724 state.begin_impl_frame_state());
725 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
727 state.OnBeginImplFrameDeadlinePending();
728 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
729 state.begin_impl_frame_state());
730 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
732 state.OnBeginImplFrameDeadline();
733 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE,
734 state.begin_impl_frame_state());
735 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
737 state.OnBeginImplFrameIdle();
738 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE,
739 state.begin_impl_frame_state());
740 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
742 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
743 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
744 state.begin_impl_frame_state());
745 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
747 // Commit and make sure we draw on next BeginImplFrame
748 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
749 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
750 state.OnBeginImplFrameDeadline();
751 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
752 state.CommitState());
753 EXPECT_ACTION_UPDATE_STATE(
754 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
755 state.DidDrawIfPossibleCompleted(DrawSwapReadbackResult::DRAW_SUCCESS);
757 // Verify that another commit will start immediately after draw.
758 EXPECT_ACTION_UPDATE_STATE(
759 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
760 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
763 TEST(SchedulerStateMachineTest, TestFullCycle) {
764 SchedulerSettings default_scheduler_settings;
765 StateMachine state(default_scheduler_settings);
767 state.UpdateState(state.NextAction());
768 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
769 state.SetVisible(true);
770 state.SetCanDraw(true);
772 // Start clean and set commit.
773 state.SetNeedsCommit();
776 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
777 EXPECT_ACTION_UPDATE_STATE(
778 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
779 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
780 state.CommitState());
781 EXPECT_FALSE(state.NeedsCommit());
782 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
784 // Tell the scheduler the frame finished.
785 state.FinishCommit();
786 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
787 state.CommitState());
790 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
791 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
792 state.CommitState());
793 EXPECT_TRUE(state.needs_redraw());
795 // Expect to do nothing until BeginImplFrame deadline
796 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
798 // At BeginImplFrame deadline, draw.
799 state.OnBeginImplFrameDeadline();
800 EXPECT_ACTION_UPDATE_STATE(
801 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
802 state.DidDrawIfPossibleCompleted(DrawSwapReadbackResult::DRAW_SUCCESS);
804 // Should be synchronized, no draw needed, no action needed.
805 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
806 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
807 EXPECT_FALSE(state.needs_redraw());
810 TEST(SchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween) {
811 SchedulerSettings default_scheduler_settings;
812 StateMachine state(default_scheduler_settings);
814 state.UpdateState(state.NextAction());
815 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
816 state.SetVisible(true);
817 state.SetCanDraw(true);
819 // Start clean and set commit.
820 state.SetNeedsCommit();
823 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
824 EXPECT_ACTION_UPDATE_STATE(
825 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
826 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
827 state.CommitState());
828 EXPECT_FALSE(state.NeedsCommit());
829 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
831 // Request another commit while the commit is in flight.
832 state.SetNeedsCommit();
833 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
835 // Tell the scheduler the frame finished.
836 state.FinishCommit();
837 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
838 state.CommitState());
841 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
842 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
843 state.CommitState());
844 EXPECT_TRUE(state.needs_redraw());
846 // Expect to do nothing until BeginImplFrame deadline.
847 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
849 // At BeginImplFrame deadline, draw.
850 state.OnBeginImplFrameDeadline();
851 EXPECT_ACTION_UPDATE_STATE(
852 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
853 state.DidDrawIfPossibleCompleted(DrawSwapReadbackResult::DRAW_SUCCESS);
855 // Should be synchronized, no draw needed, no action needed.
856 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
857 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
858 EXPECT_FALSE(state.needs_redraw());
860 // Next BeginImplFrame should initiate second commit.
861 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
862 EXPECT_ACTION_UPDATE_STATE(
863 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
866 TEST(SchedulerStateMachineTest, TestRequestCommitInvisible) {
867 SchedulerSettings default_scheduler_settings;
868 StateMachine state(default_scheduler_settings);
870 state.UpdateState(state.NextAction());
871 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
872 state.SetNeedsCommit();
873 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
876 TEST(SchedulerStateMachineTest, TestGoesInvisibleBeforeFinishCommit) {
877 SchedulerSettings default_scheduler_settings;
878 StateMachine state(default_scheduler_settings);
880 state.UpdateState(state.NextAction());
881 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
882 state.SetVisible(true);
883 state.SetCanDraw(true);
885 // Start clean and set commit.
886 state.SetNeedsCommit();
888 // Begin the frame while visible.
889 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
890 EXPECT_ACTION_UPDATE_STATE(
891 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
892 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
893 state.CommitState());
894 EXPECT_FALSE(state.NeedsCommit());
895 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
897 // Become invisible and abort BeginMainFrame.
898 state.SetVisible(false);
899 state.BeginMainFrameAborted(false);
901 // We should now be back in the idle state as if we never started the frame.
902 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
903 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
905 // We shouldn't do anything on the BeginImplFrame deadline.
906 state.OnBeginImplFrameDeadline();
907 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
909 // Become visible again.
910 state.SetVisible(true);
912 // Although we have aborted on this frame and haven't cancelled the commit
913 // (i.e. need another), don't send another BeginMainFrame yet.
914 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
915 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
916 EXPECT_TRUE(state.NeedsCommit());
918 // Start a new frame.
919 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
920 EXPECT_ACTION_UPDATE_STATE(
921 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
923 // We should be starting the commit now.
924 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
925 state.CommitState());
926 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
929 TEST(SchedulerStateMachineTest, AbortBeginMainFrameAndCancelCommit) {
930 SchedulerSettings default_scheduler_settings;
931 StateMachine state(default_scheduler_settings);
933 state.UpdateState(state.NextAction());
934 state.DidCreateAndInitializeOutputSurface();
935 state.SetVisible(true);
936 state.SetCanDraw(true);
938 // Get into a begin frame / commit state.
939 state.SetNeedsCommit();
941 EXPECT_ACTION_UPDATE_STATE(
942 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
943 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
944 state.CommitState());
945 EXPECT_FALSE(state.NeedsCommit());
946 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
948 // Abort the commit, cancelling future commits.
949 state.BeginMainFrameAborted(true);
951 // Verify that another commit doesn't start on the same frame.
952 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
953 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
954 EXPECT_FALSE(state.NeedsCommit());
956 // Start a new frame; draw because this is the first frame since output
958 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
959 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
960 state.OnBeginImplFrameDeadline();
961 EXPECT_ACTION_UPDATE_STATE(
962 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
964 // Verify another commit doesn't start on another frame either.
965 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
966 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
967 EXPECT_FALSE(state.NeedsCommit());
969 // Verify another commit can start if requested, though.
970 state.SetNeedsCommit();
971 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
972 EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME,
976 TEST(SchedulerStateMachineTest, TestFirstContextCreation) {
977 SchedulerSettings default_scheduler_settings;
978 StateMachine state(default_scheduler_settings);
980 state.SetVisible(true);
981 state.SetCanDraw(true);
983 EXPECT_ACTION_UPDATE_STATE(
984 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
985 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
986 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
988 // Check that the first init does not SetNeedsCommit.
989 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
990 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
991 state.OnBeginImplFrameDeadline();
992 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
994 // Check that a needs commit initiates a BeginMainFrame.
995 state.SetNeedsCommit();
996 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
997 EXPECT_ACTION_UPDATE_STATE(
998 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1001 TEST(SchedulerStateMachineTest, TestContextLostWhenCompletelyIdle) {
1002 SchedulerSettings default_scheduler_settings;
1003 StateMachine state(default_scheduler_settings);
1004 state.SetCanStart();
1005 state.UpdateState(state.NextAction());
1006 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1008 state.SetVisible(true);
1009 state.SetCanDraw(true);
1011 EXPECT_NE(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
1012 state.NextAction());
1013 state.DidLoseOutputSurface();
1015 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
1016 state.NextAction());
1017 state.UpdateState(state.NextAction());
1019 // Once context recreation begins, nothing should happen.
1020 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1022 // Recreate the context.
1023 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1025 // When the context is recreated, we should begin a commit.
1026 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
1027 EXPECT_ACTION_UPDATE_STATE(
1028 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1031 TEST(SchedulerStateMachineTest,
1032 TestContextLostWhenIdleAndCommitRequestedWhileRecreating) {
1033 SchedulerSettings default_scheduler_settings;
1034 StateMachine state(default_scheduler_settings);
1035 state.SetCanStart();
1036 state.UpdateState(state.NextAction());
1037 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1038 state.SetVisible(true);
1039 state.SetCanDraw(true);
1041 EXPECT_NE(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
1042 state.NextAction());
1043 state.DidLoseOutputSurface();
1045 EXPECT_ACTION_UPDATE_STATE(
1046 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
1047 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1049 // Once context recreation begins, nothing should happen.
1050 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
1051 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1052 state.OnBeginImplFrameDeadline();
1053 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1055 // While context is recreating, commits shouldn't begin.
1056 state.SetNeedsCommit();
1057 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
1058 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1059 state.OnBeginImplFrameDeadline();
1060 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1062 // Recreate the context
1063 state.DidCreateAndInitializeOutputSurface();
1064 EXPECT_FALSE(state.RedrawPending());
1066 // When the context is recreated, we should begin a commit
1067 EXPECT_ACTION_UPDATE_STATE(
1068 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1069 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1070 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
1071 state.CommitState());
1072 state.FinishCommit();
1073 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1074 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1075 // Finishing the first commit after initializing an output surface should
1076 // automatically cause a redraw.
1077 EXPECT_TRUE(state.RedrawPending());
1079 // Once the context is recreated, whether we draw should be based on
1081 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
1082 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1083 state.OnBeginImplFrameDeadline();
1084 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
1085 state.NextAction());
1086 state.SetCanDraw(false);
1087 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT,
1088 state.NextAction());
1089 state.SetCanDraw(true);
1090 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
1091 state.NextAction());
1094 void TestContextLostWhileCommitInProgress(bool deadline_scheduling_enabled) {
1095 SchedulerSettings scheduler_settings;
1096 scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
1097 StateMachine state(scheduler_settings);
1098 state.SetCanStart();
1099 state.UpdateState(state.NextAction());
1100 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1101 state.SetVisible(true);
1102 state.SetCanDraw(true);
1104 // Get a commit in flight.
1105 state.SetNeedsCommit();
1106 if (!deadline_scheduling_enabled) {
1107 EXPECT_ACTION_UPDATE_STATE(
1108 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1111 // Set damage and expect a draw.
1112 state.SetNeedsRedraw(true);
1113 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
1114 if (deadline_scheduling_enabled) {
1115 EXPECT_ACTION_UPDATE_STATE(
1116 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
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 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1124 // Cause a lost context while the BeginMainFrame is in flight.
1125 state.DidLoseOutputSurface();
1127 // Ask for another draw. Expect nothing happens.
1128 state.SetNeedsRedraw(true);
1129 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1131 // Finish the frame, and commit.
1132 state.FinishCommit();
1133 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1135 // We will abort the draw when the output surface is lost if we are
1136 // waiting for the first draw to unblock the main thread.
1137 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
1138 state.CommitState());
1139 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
1141 // Expect to begin context recreation only in BEGIN_IMPL_FRAME_STATE_IDLE
1142 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE,
1143 state.begin_impl_frame_state());
1144 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
1145 state.NextAction());
1147 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
1148 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
1149 state.begin_impl_frame_state());
1150 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1152 state.OnBeginImplFrameDeadlinePending();
1153 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
1154 state.begin_impl_frame_state());
1155 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1157 state.OnBeginImplFrameDeadline();
1158 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE,
1159 state.begin_impl_frame_state());
1160 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1163 TEST(SchedulerStateMachineTest, TestContextLostWhileCommitInProgress) {
1164 bool deadline_scheduling_enabled = false;
1165 TestContextLostWhileCommitInProgress(deadline_scheduling_enabled);
1168 TEST(SchedulerStateMachineTest, TestContextLostWhileCommitInProgress_Deadline) {
1169 bool deadline_scheduling_enabled = true;
1170 TestContextLostWhileCommitInProgress(deadline_scheduling_enabled);
1173 void TestContextLostWhileCommitInProgressAndAnotherCommitRequested(
1174 bool deadline_scheduling_enabled) {
1175 SchedulerSettings scheduler_settings;
1176 scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
1177 StateMachine state(scheduler_settings);
1178 state.SetCanStart();
1179 state.UpdateState(state.NextAction());
1180 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1181 state.SetVisible(true);
1182 state.SetCanDraw(true);
1184 // Get a commit in flight.
1185 state.SetNeedsCommit();
1186 if (!deadline_scheduling_enabled) {
1187 EXPECT_ACTION_UPDATE_STATE(
1188 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1190 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1192 // Set damage and expect a draw.
1193 state.SetNeedsRedraw(true);
1194 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
1195 if (deadline_scheduling_enabled) {
1196 EXPECT_ACTION_UPDATE_STATE(
1197 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1199 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1200 state.OnBeginImplFrameDeadline();
1201 EXPECT_ACTION_UPDATE_STATE(
1202 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
1203 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1205 // Cause a lost context while the BeginMainFrame is in flight.
1206 state.DidLoseOutputSurface();
1208 // Ask for another draw and also set needs commit. Expect nothing happens.
1209 state.SetNeedsRedraw(true);
1210 state.SetNeedsCommit();
1211 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1213 // Finish the frame, and commit.
1214 state.FinishCommit();
1215 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1216 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
1217 state.CommitState());
1219 // Because the output surface is missing, we expect the draw to abort.
1220 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
1222 // Expect to begin context recreation only in BEGIN_IMPL_FRAME_STATE_IDLE
1223 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE,
1224 state.begin_impl_frame_state());
1225 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
1226 state.NextAction());
1228 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
1229 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING,
1230 state.begin_impl_frame_state());
1231 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1233 state.OnBeginImplFrameDeadlinePending();
1234 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME,
1235 state.begin_impl_frame_state());
1236 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1238 state.OnBeginImplFrameDeadline();
1239 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE,
1240 state.begin_impl_frame_state());
1241 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1243 state.OnBeginImplFrameIdle();
1244 EXPECT_ACTION_UPDATE_STATE(
1245 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
1247 // After we get a new output surface, the commit flow should start.
1248 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1249 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
1250 EXPECT_ACTION_UPDATE_STATE(
1251 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1252 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1253 state.FinishCommit();
1254 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1255 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1256 state.OnBeginImplFrameDeadline();
1257 EXPECT_ACTION_UPDATE_STATE(
1258 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE);
1259 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1262 TEST(SchedulerStateMachineTest,
1263 TestContextLostWhileCommitInProgressAndAnotherCommitRequested) {
1264 bool deadline_scheduling_enabled = false;
1265 TestContextLostWhileCommitInProgressAndAnotherCommitRequested(
1266 deadline_scheduling_enabled);
1269 TEST(SchedulerStateMachineTest,
1270 TestContextLostWhileCommitInProgressAndAnotherCommitRequested_Deadline) {
1271 bool deadline_scheduling_enabled = true;
1272 TestContextLostWhileCommitInProgressAndAnotherCommitRequested(
1273 deadline_scheduling_enabled);
1276 TEST(SchedulerStateMachineTest, TestFinishAllRenderingWhileContextLost) {
1277 SchedulerSettings default_scheduler_settings;
1278 StateMachine state(default_scheduler_settings);
1279 state.SetCanStart();
1280 state.UpdateState(state.NextAction());
1281 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1282 state.SetVisible(true);
1283 state.SetCanDraw(true);
1285 // Cause a lost context lost.
1286 state.DidLoseOutputSurface();
1288 // Ask a forced redraw for readback and verify it ocurrs.
1289 state.SetCommitState(
1290 SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
1291 state.SetNeedsForcedRedrawForReadback();
1292 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
1293 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_READBACK);
1294 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1296 // Forced redraws for readbacks need to be followed by a new commit
1297 // to replace the readback commit.
1298 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
1299 state.CommitState());
1300 state.FinishCommit();
1301 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1303 // We don't yet have an output surface, so we the draw and swap should abort.
1304 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
1306 // Expect to begin context recreation only in BEGIN_IMPL_FRAME_STATE_IDLE
1307 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1309 state.OnBeginImplFrameDeadline();
1310 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1312 state.OnBeginImplFrameIdle();
1313 EXPECT_ACTION_UPDATE_STATE(
1314 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
1316 // Ask a readback and verify it occurs.
1317 state.SetCommitState(
1318 SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW);
1319 state.SetNeedsForcedRedrawForReadback();
1320 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_READBACK);
1321 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1324 TEST(SchedulerStateMachineTest, DontDrawBeforeCommitAfterLostOutputSurface) {
1325 SchedulerSettings default_scheduler_settings;
1326 StateMachine state(default_scheduler_settings);
1327 state.SetCanStart();
1328 state.UpdateState(state.NextAction());
1329 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1330 state.SetVisible(true);
1331 state.SetCanDraw(true);
1333 state.SetNeedsRedraw(true);
1335 // Cause a lost output surface, and restore it.
1336 state.DidLoseOutputSurface();
1337 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION,
1338 state.NextAction());
1339 state.UpdateState(state.NextAction());
1340 state.DidCreateAndInitializeOutputSurface();
1342 EXPECT_FALSE(state.RedrawPending());
1343 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
1344 EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME,
1345 state.NextAction());
1348 TEST(SchedulerStateMachineTest,
1349 TestSendBeginMainFrameWhenInvisibleAndForceCommit) {
1350 SchedulerSettings default_scheduler_settings;
1351 StateMachine state(default_scheduler_settings);
1352 state.SetCanStart();
1353 state.UpdateState(state.NextAction());
1354 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1355 state.SetVisible(false);
1356 state.SetNeedsCommit();
1357 state.SetNeedsForcedCommitForReadback();
1358 EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME,
1359 state.NextAction());
1362 TEST(SchedulerStateMachineTest,
1363 TestSendBeginMainFrameWhenCanStartFalseAndForceCommit) {
1364 SchedulerSettings default_scheduler_settings;
1365 StateMachine state(default_scheduler_settings);
1366 state.SetVisible(true);
1367 state.SetCanDraw(true);
1368 state.SetNeedsCommit();
1369 state.SetNeedsForcedCommitForReadback();
1370 EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME,
1371 state.NextAction());
1374 TEST(SchedulerStateMachineTest, TestFinishCommitWhenCommitInProgress) {
1375 SchedulerSettings default_scheduler_settings;
1376 StateMachine state(default_scheduler_settings);
1377 state.SetCanStart();
1378 state.UpdateState(state.NextAction());
1379 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1380 state.SetVisible(false);
1381 state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS);
1382 state.SetNeedsCommit();
1384 state.FinishCommit();
1385 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
1386 state.UpdateState(state.NextAction());
1388 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
1389 state.CommitState());
1390 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT);
1393 TEST(SchedulerStateMachineTest, TestFinishCommitWhenForcedCommitInProgress) {
1394 SchedulerSettings default_scheduler_settings;
1395 StateMachine state(default_scheduler_settings);
1396 state.SetCanStart();
1397 state.UpdateState(state.NextAction());
1398 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1399 state.SetVisible(false);
1400 state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS);
1401 state.SetNeedsCommit();
1402 state.SetNeedsForcedCommitForReadback();
1404 // The commit for readback interupts the normal commit.
1405 state.FinishCommit();
1406 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1408 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
1409 state.CommitState());
1410 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_READBACK);
1412 // When the readback interrupts the normal commit, we should not get
1413 // another BeginMainFrame when the readback completes.
1414 EXPECT_NE(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME,
1415 state.NextAction());
1417 // The normal commit can then proceed.
1418 state.FinishCommit();
1419 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1422 TEST(SchedulerStateMachineTest, TestInitialActionsWhenContextLost) {
1423 SchedulerSettings default_scheduler_settings;
1424 StateMachine state(default_scheduler_settings);
1425 state.SetCanStart();
1426 state.UpdateState(state.NextAction());
1427 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1428 state.SetVisible(true);
1429 state.SetCanDraw(true);
1430 state.SetNeedsCommit();
1431 state.DidLoseOutputSurface();
1433 // When we are visible, we normally want to begin output surface creation
1434 // as soon as possible.
1435 EXPECT_ACTION_UPDATE_STATE(
1436 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION);
1438 state.DidCreateAndInitializeOutputSurface();
1439 EXPECT_EQ(state.output_surface_state(),
1440 SchedulerStateMachine::OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT);
1442 // We should not send a BeginMainFrame when we are invisible, even if we've
1443 // lost the output surface and are trying to get the first commit, since the
1444 // main thread will just abort anyway.
1445 state.SetVisible(false);
1446 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction())
1447 << *state.AsValue();
1449 // If there is a forced commit, however, we could be blocking a readback
1450 // on the main thread, so we need to unblock it before we can get our
1451 // output surface, even if we are not visible.
1452 state.SetNeedsForcedCommitForReadback();
1454 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME, state.NextAction())
1455 << *state.AsValue();
1458 TEST(SchedulerStateMachineTest, TestImmediateFinishCommit) {
1459 SchedulerSettings default_scheduler_settings;
1460 StateMachine state(default_scheduler_settings);
1461 state.SetCanStart();
1462 state.UpdateState(state.NextAction());
1463 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1464 state.SetVisible(true);
1465 state.SetCanDraw(true);
1467 // Schedule a readback, commit it, draw it.
1468 state.SetNeedsCommit();
1469 state.SetNeedsForcedCommitForReadback();
1470 EXPECT_ACTION_UPDATE_STATE(
1471 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1472 state.FinishCommit();
1474 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
1475 state.CommitState());
1476 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1478 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
1479 state.CommitState());
1481 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_READBACK);
1482 state.DidDrawIfPossibleCompleted(DrawSwapReadbackResult::DRAW_SUCCESS);
1484 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1486 // Should be waiting for the normal BeginMainFrame.
1487 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
1488 state.CommitState());
1491 void TestImmediateFinishCommitDuringCommit(bool deadline_scheduling_enabled) {
1492 SchedulerSettings scheduler_settings;
1493 scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
1494 StateMachine state(scheduler_settings);
1495 state.SetCanStart();
1496 state.UpdateState(state.NextAction());
1497 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1498 state.SetVisible(true);
1499 state.SetCanDraw(true);
1501 // Start a normal commit.
1502 state.SetNeedsCommit();
1503 if (!deadline_scheduling_enabled) {
1504 EXPECT_ACTION_UPDATE_STATE(
1505 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1507 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1509 // Schedule a readback, commit it, draw it.
1510 state.SetNeedsForcedCommitForReadback();
1511 if (deadline_scheduling_enabled) {
1512 EXPECT_ACTION_UPDATE_STATE(
1513 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1515 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1516 state.FinishCommit();
1517 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
1518 state.CommitState());
1519 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1521 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
1522 state.CommitState());
1524 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_READBACK);
1525 state.DidDrawIfPossibleCompleted(DrawSwapReadbackResult::DRAW_SUCCESS);
1526 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1528 // Should be waiting for the normal BeginMainFrame.
1529 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
1530 state.CommitState())
1531 << *state.AsValue();
1534 TEST(SchedulerStateMachineTest, TestImmediateFinishCommitDuringCommit) {
1535 bool deadline_scheduling_enabled = false;
1536 TestImmediateFinishCommitDuringCommit(deadline_scheduling_enabled);
1539 TEST(SchedulerStateMachineTest,
1540 TestImmediateFinishCommitDuringCommit_Deadline) {
1541 bool deadline_scheduling_enabled = true;
1542 TestImmediateFinishCommitDuringCommit(deadline_scheduling_enabled);
1545 void ImmediateBeginMainFrameAbortedWhileInvisible(
1546 bool deadline_scheduling_enabled) {
1547 SchedulerSettings scheduler_settings;
1548 scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled;
1549 StateMachine state(scheduler_settings);
1550 state.SetCanStart();
1551 state.UpdateState(state.NextAction());
1552 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1553 state.SetVisible(true);
1554 state.SetCanDraw(true);
1556 state.SetNeedsCommit();
1557 if (!deadline_scheduling_enabled) {
1558 EXPECT_ACTION_UPDATE_STATE(
1559 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1561 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1563 state.SetNeedsCommit();
1564 state.SetNeedsForcedCommitForReadback();
1565 if (deadline_scheduling_enabled) {
1566 EXPECT_ACTION_UPDATE_STATE(
1567 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1569 state.FinishCommit();
1571 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
1572 state.CommitState());
1573 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1575 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
1576 state.CommitState());
1578 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_READBACK);
1579 state.DidDrawIfPossibleCompleted(DrawSwapReadbackResult::DRAW_SUCCESS);
1580 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1582 // Should be waiting for BeginMainFrame.
1583 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
1584 state.CommitState())
1585 << *state.AsValue();
1587 // Become invisible and abort BeginMainFrame.
1588 state.SetVisible(false);
1589 state.BeginMainFrameAborted(false);
1591 // Should be back in the idle state, but needing a commit.
1592 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState());
1593 EXPECT_TRUE(state.NeedsCommit());
1596 TEST(SchedulerStateMachineTest,
1597 ImmediateBeginMainFrameAbortedWhileInvisible) {
1598 bool deadline_scheduling_enabled = false;
1599 ImmediateBeginMainFrameAbortedWhileInvisible(
1600 deadline_scheduling_enabled);
1603 TEST(SchedulerStateMachineTest,
1604 ImmediateBeginMainFrameAbortedWhileInvisible_Deadline) {
1605 bool deadline_scheduling_enabled = true;
1606 ImmediateBeginMainFrameAbortedWhileInvisible(
1607 deadline_scheduling_enabled);
1610 TEST(SchedulerStateMachineTest, ImmediateFinishCommitWhileCantDraw) {
1611 SchedulerSettings default_scheduler_settings;
1612 StateMachine state(default_scheduler_settings);
1613 state.SetCanStart();
1614 state.UpdateState(state.NextAction());
1615 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1616 state.SetVisible(true);
1617 state.SetCanDraw(false);
1619 state.SetNeedsCommit();
1620 state.UpdateState(state.NextAction());
1622 state.SetNeedsCommit();
1623 state.SetNeedsForcedCommitForReadback();
1624 state.UpdateState(state.NextAction());
1625 state.FinishCommit();
1627 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT,
1628 state.CommitState());
1629 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT);
1631 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW,
1632 state.CommitState());
1634 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_READBACK);
1635 state.DidDrawIfPossibleCompleted(DrawSwapReadbackResult::DRAW_SUCCESS);
1636 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1639 TEST(SchedulerStateMachineTest, ReportIfNotDrawing) {
1640 SchedulerSettings default_scheduler_settings;
1641 StateMachine state(default_scheduler_settings);
1642 state.SetCanStart();
1643 state.UpdateState(state.NextAction());
1644 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1646 state.SetCanDraw(true);
1647 state.SetVisible(true);
1648 EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
1650 state.SetCanDraw(false);
1651 state.SetVisible(true);
1652 EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
1654 state.SetCanDraw(true);
1655 state.SetVisible(false);
1656 EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
1658 state.SetCanDraw(false);
1659 state.SetVisible(false);
1660 EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
1662 state.SetCanDraw(true);
1663 state.SetVisible(true);
1664 EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
1667 TEST(SchedulerStateMachineTest, ReportIfNotDrawingFromAcquiredTextures) {
1668 SchedulerSettings default_scheduler_settings;
1669 StateMachine state(default_scheduler_settings);
1670 state.SetCanStart();
1671 state.UpdateState(state.NextAction());
1672 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1673 state.SetCanDraw(true);
1674 state.SetVisible(true);
1675 EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
1677 state.SetMainThreadNeedsLayerTextures();
1678 EXPECT_ACTION_UPDATE_STATE(
1679 SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD);
1680 EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
1681 EXPECT_TRUE(state.PendingActivationsShouldBeForced());
1683 state.SetNeedsCommit();
1684 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
1685 EXPECT_ACTION_UPDATE_STATE(
1686 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1687 EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
1688 EXPECT_TRUE(state.PendingActivationsShouldBeForced());
1690 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1692 state.FinishCommit();
1693 EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
1695 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction());
1697 state.UpdateState(state.NextAction());
1698 EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
1701 TEST(SchedulerStateMachineTest, AcquireTexturesWithAbort) {
1702 SchedulerSettings default_scheduler_settings;
1703 StateMachine state(default_scheduler_settings);
1704 state.SetCanStart();
1705 state.UpdateState(state.NextAction());
1706 state.DidCreateAndInitializeOutputSurface();
1707 state.SetCanDraw(true);
1708 state.SetVisible(true);
1710 state.SetMainThreadNeedsLayerTextures();
1712 SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD,
1713 state.NextAction());
1714 state.UpdateState(state.NextAction());
1715 EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
1717 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1719 state.SetNeedsCommit();
1720 EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME,
1721 state.NextAction());
1722 state.UpdateState(state.NextAction());
1723 EXPECT_TRUE(state.PendingDrawsShouldBeAborted());
1725 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1727 state.BeginMainFrameAborted(true);
1729 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction());
1730 EXPECT_FALSE(state.PendingDrawsShouldBeAborted());
1733 TEST(SchedulerStateMachineTest,
1734 TestTriggerDeadlineEarlyAfterAbortedCommit) {
1735 SchedulerSettings settings;
1736 settings.deadline_scheduling_enabled = true;
1737 settings.impl_side_painting = true;
1738 StateMachine state(settings);
1739 state.SetCanStart();
1740 state.UpdateState(state.NextAction());
1741 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1742 state.SetVisible(true);
1743 state.SetCanDraw(true);
1745 // This test mirrors what happens during the first frame of a scroll gesture.
1746 // First we get the input event and a BeginFrame.
1747 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
1749 // As a response the compositor requests a redraw and a commit to tell the
1750 // main thread about the new scroll offset.
1751 state.SetNeedsRedraw(true);
1752 state.SetNeedsCommit();
1754 // We should start the commit normally.
1755 EXPECT_ACTION_UPDATE_STATE(
1756 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1757 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1759 // Since only the scroll offset changed, the main thread will abort the
1761 state.BeginMainFrameAborted(true);
1763 // Since the commit was aborted, we should draw right away instead of waiting
1764 // for the deadline.
1765 EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly());
1768 TEST(SchedulerStateMachineTest, TestTriggerDeadlineEarlyForSmoothness) {
1769 SchedulerSettings settings;
1770 settings.deadline_scheduling_enabled = true;
1771 settings.impl_side_painting = true;
1772 StateMachine state(settings);
1773 state.SetCanStart();
1774 state.UpdateState(state.NextAction());
1775 state.CreateAndInitializeOutputSurfaceWithActivatedCommit();
1776 state.SetVisible(true);
1777 state.SetCanDraw(true);
1779 // This test ensures that impl-draws are prioritized over main thread updates
1780 // in prefer smoothness mode.
1781 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting());
1782 state.SetNeedsRedraw(true);
1783 state.SetNeedsCommit();
1784 EXPECT_ACTION_UPDATE_STATE(
1785 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME);
1786 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE);
1788 // The deadline is not triggered early until we enter prefer smoothness mode.
1789 EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineEarly());
1790 state.SetSmoothnessTakesPriority(true);
1791 EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly());