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.
7 #include "cc/scheduler_state_machine.h"
9 #include "testing/gtest/include/gtest/gtest.h"
15 const SchedulerStateMachine::CommitState allCommitStates
[] = {
16 SchedulerStateMachine::COMMIT_STATE_IDLE
,
17 SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS
,
18 SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
,
19 SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW
22 // Exposes the protected state fields of the SchedulerStateMachine for testing
23 class StateMachine
: public SchedulerStateMachine
{
25 void setCommitState(CommitState cs
) { m_commitState
= cs
; }
26 CommitState
commitState() const { return m_commitState
; }
28 void setNeedsCommit(bool b
) { m_needsCommit
= b
; }
29 bool needsCommit() const { return m_needsCommit
; }
31 void setNeedsForcedCommit(bool b
) { m_needsForcedCommit
= b
; }
32 bool needsForcedCommit() const { return m_needsForcedCommit
; }
34 void setNeedsRedraw(bool b
) { m_needsRedraw
= b
; }
35 bool needsRedraw() const { return m_needsRedraw
; }
37 void setNeedsForcedRedraw(bool b
) { m_needsForcedRedraw
= b
; }
38 bool needsForcedRedraw() const { return m_needsForcedRedraw
; }
40 bool canDraw() const { return m_canDraw
; }
41 bool insideVSync() const { return m_insideVSync
; }
42 bool visible() const { return m_visible
; }
45 TEST(SchedulerStateMachineTest
, TestNextActionBeginsFrameIfNeeded
)
47 // If no commit needed, do nothing
50 state
.setCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE
);
51 state
.setCanBeginFrame(true);
52 state
.setNeedsRedraw(false);
53 state
.setNeedsCommit(false);
54 state
.setVisible(true);
56 EXPECT_FALSE(state
.vsyncCallbackNeeded());
58 state
.didLeaveVSync();
59 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
60 EXPECT_FALSE(state
.vsyncCallbackNeeded());
61 state
.didEnterVSync();
62 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
65 // If commit requested but canBeginFrame is still false, do nothing.
68 state
.setCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE
);
69 state
.setNeedsRedraw(false);
70 state
.setNeedsCommit(false);
71 state
.setVisible(true);
73 EXPECT_FALSE(state
.vsyncCallbackNeeded());
75 state
.didLeaveVSync();
76 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
77 EXPECT_FALSE(state
.vsyncCallbackNeeded());
78 state
.didEnterVSync();
79 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
83 // If commit requested, begin a frame
86 state
.setCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE
);
87 state
.setCanBeginFrame(true);
88 state
.setNeedsRedraw(false);
89 state
.setNeedsCommit(true);
90 state
.setVisible(true);
91 EXPECT_FALSE(state
.vsyncCallbackNeeded());
94 // Begin the frame, make sure needsCommit and commitState update correctly.
97 state
.setCanBeginFrame(true);
98 state
.setVisible(true);
99 state
.updateState(SchedulerStateMachine::ACTION_BEGIN_FRAME
);
100 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS
, state
.commitState());
101 EXPECT_FALSE(state
.needsCommit());
102 EXPECT_FALSE(state
.vsyncCallbackNeeded());
106 TEST(SchedulerStateMachineTest
, TestSetForcedRedrawDoesNotSetsNormalRedraw
)
108 SchedulerStateMachine state
;
109 state
.setCanDraw(true);
110 state
.setNeedsForcedRedraw();
111 EXPECT_FALSE(state
.redrawPending());
112 EXPECT_TRUE(state
.vsyncCallbackNeeded());
115 TEST(SchedulerStateMachineTest
, TestFailedDrawSetsNeedsCommitAndDoesNotDrawAgain
)
117 SchedulerStateMachine state
;
118 state
.setCanBeginFrame(true);
119 state
.setVisible(true);
120 state
.setCanDraw(true);
121 state
.setNeedsRedraw();
122 EXPECT_TRUE(state
.redrawPending());
123 EXPECT_TRUE(state
.vsyncCallbackNeeded());
124 state
.didEnterVSync();
126 // We're drawing now.
127 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
128 state
.updateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
);
129 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
130 EXPECT_FALSE(state
.redrawPending());
131 EXPECT_FALSE(state
.commitPending());
133 // Failing the draw makes us require a commit.
134 state
.didDrawIfPossibleCompleted(false);
135 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
136 state
.updateState(SchedulerStateMachine::ACTION_BEGIN_FRAME
);
137 EXPECT_TRUE(state
.redrawPending());
138 EXPECT_TRUE(state
.commitPending());
141 TEST(SchedulerStateMachineTest
, TestSetNeedsRedrawDuringFailedDrawDoesNotRemoveNeedsRedraw
)
143 SchedulerStateMachine state
;
144 state
.setCanBeginFrame(true);
145 state
.setVisible(true);
146 state
.setCanDraw(true);
147 state
.setNeedsRedraw();
148 EXPECT_TRUE(state
.redrawPending());
149 EXPECT_TRUE(state
.vsyncCallbackNeeded());
150 state
.didEnterVSync();
152 // We're drawing now.
153 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
154 state
.updateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
);
155 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
156 EXPECT_FALSE(state
.redrawPending());
157 EXPECT_FALSE(state
.commitPending());
159 // While still in the same vsync callback, set needs redraw again.
160 // This should not redraw.
161 state
.setNeedsRedraw();
162 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
164 // Failing the draw makes us require a commit.
165 state
.didDrawIfPossibleCompleted(false);
166 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
167 EXPECT_TRUE(state
.redrawPending());
170 TEST(SchedulerStateMachineTest
, TestCommitAfterFailedDrawAllowsDrawInSameFrame
)
172 SchedulerStateMachine state
;
173 state
.setCanBeginFrame(true);
174 state
.setVisible(true);
175 state
.setCanDraw(true);
178 state
.setNeedsCommit();
179 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
180 state
.updateState(SchedulerStateMachine::ACTION_BEGIN_FRAME
);
181 EXPECT_TRUE(state
.commitPending());
183 // Then initiate a draw.
184 state
.setNeedsRedraw();
185 EXPECT_TRUE(state
.vsyncCallbackNeeded());
186 state
.didEnterVSync();
187 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
188 EXPECT_TRUE(state
.redrawPending());
191 state
.updateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
);
192 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
193 state
.didDrawIfPossibleCompleted(false);
194 EXPECT_TRUE(state
.redrawPending());
195 // But the commit is ongoing.
196 EXPECT_TRUE(state
.commitPending());
198 // Finish the commit.
199 state
.beginFrameComplete();
200 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT
, state
.nextAction());
201 state
.updateState(SchedulerStateMachine::ACTION_COMMIT
);
202 EXPECT_TRUE(state
.redrawPending());
204 // And we should be allowed to draw again.
205 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
208 TEST(SchedulerStateMachineTest
, TestCommitAfterFailedAndSuccessfulDrawDoesNotAllowDrawInSameFrame
)
210 SchedulerStateMachine state
;
211 state
.setCanBeginFrame(true);
212 state
.setVisible(true);
213 state
.setCanDraw(true);
216 state
.setNeedsCommit();
217 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
218 state
.updateState(SchedulerStateMachine::ACTION_BEGIN_FRAME
);
219 EXPECT_TRUE(state
.commitPending());
221 // Then initiate a draw.
222 state
.setNeedsRedraw();
223 EXPECT_TRUE(state
.vsyncCallbackNeeded());
224 state
.didEnterVSync();
225 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
226 EXPECT_TRUE(state
.redrawPending());
229 state
.updateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
);
230 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
231 state
.didDrawIfPossibleCompleted(false);
232 EXPECT_TRUE(state
.redrawPending());
233 // But the commit is ongoing.
234 EXPECT_TRUE(state
.commitPending());
237 state
.setNeedsForcedRedraw();
238 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_FORCED
, state
.nextAction());
240 // Do the forced draw.
241 state
.updateState(SchedulerStateMachine::ACTION_DRAW_FORCED
);
242 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
243 EXPECT_FALSE(state
.redrawPending());
244 // And the commit is still ongoing.
245 EXPECT_TRUE(state
.commitPending());
247 // Finish the commit.
248 state
.beginFrameComplete();
249 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT
, state
.nextAction());
250 state
.updateState(SchedulerStateMachine::ACTION_COMMIT
);
251 EXPECT_TRUE(state
.redrawPending());
253 // And we should not be allowed to draw again in the same frame..
254 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
257 TEST(SchedulerStateMachineTest
, TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit
)
259 SchedulerStateMachine state
;
260 state
.setCanBeginFrame(true);
261 state
.setVisible(true);
262 state
.setCanDraw(true);
263 state
.setMaximumNumberOfFailedDrawsBeforeDrawIsForced(1);
266 state
.setNeedsCommit();
267 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
268 state
.updateState(SchedulerStateMachine::ACTION_BEGIN_FRAME
);
269 EXPECT_TRUE(state
.commitPending());
271 // Then initiate a draw.
272 state
.setNeedsRedraw();
273 EXPECT_TRUE(state
.vsyncCallbackNeeded());
274 state
.didEnterVSync();
275 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
276 EXPECT_TRUE(state
.redrawPending());
279 state
.updateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
);
280 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
281 state
.didDrawIfPossibleCompleted(false);
282 EXPECT_TRUE(state
.redrawPending());
283 // But the commit is ongoing.
284 EXPECT_TRUE(state
.commitPending());
286 // Finish the commit. Note, we should not yet be forcing a draw, but should
287 // continue the commit as usual.
288 state
.beginFrameComplete();
289 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT
, state
.nextAction());
290 state
.updateState(SchedulerStateMachine::ACTION_COMMIT
);
291 EXPECT_TRUE(state
.redrawPending());
293 // The redraw should be forced in this case.
294 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_FORCED
, state
.nextAction());
297 TEST(SchedulerStateMachineTest
, TestFailedDrawIsRetriedNextVSync
)
299 SchedulerStateMachine state
;
300 state
.setCanBeginFrame(true);
301 state
.setVisible(true);
302 state
.setCanDraw(true);
305 state
.setNeedsRedraw();
306 EXPECT_TRUE(state
.vsyncCallbackNeeded());
307 state
.didEnterVSync();
308 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
309 EXPECT_TRUE(state
.redrawPending());
312 state
.updateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
);
313 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
314 state
.didDrawIfPossibleCompleted(false);
315 EXPECT_TRUE(state
.redrawPending());
317 // We should not be trying to draw again now, but we have a commit pending.
318 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
320 state
.didLeaveVSync();
321 EXPECT_TRUE(state
.vsyncCallbackNeeded());
322 state
.didEnterVSync();
324 // We should try draw again in the next vsync.
325 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
328 TEST(SchedulerStateMachineTest
, TestDoestDrawTwiceInSameFrame
)
330 SchedulerStateMachine state
;
331 state
.setVisible(true);
332 state
.setCanDraw(true);
333 state
.setNeedsRedraw();
334 EXPECT_TRUE(state
.vsyncCallbackNeeded());
335 state
.didEnterVSync();
336 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
337 state
.updateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
);
339 // While still in the same vsync callback, set needs redraw again.
340 // This should not redraw.
341 state
.setNeedsRedraw();
342 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
344 // Move to another frame. This should now draw.
345 state
.didDrawIfPossibleCompleted(true);
346 state
.didLeaveVSync();
347 EXPECT_TRUE(state
.vsyncCallbackNeeded());
348 state
.didEnterVSync();
350 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
351 state
.updateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
);
352 state
.didDrawIfPossibleCompleted(true);
353 EXPECT_FALSE(state
.vsyncCallbackNeeded());
356 TEST(SchedulerStateMachineTest
, TestNextActionDrawsOnVSync
)
358 // When not on vsync, or on vsync but not visible, don't draw.
359 size_t numCommitStates
= sizeof(allCommitStates
) / sizeof(SchedulerStateMachine::CommitState
);
360 for (size_t i
= 0; i
< numCommitStates
; ++i
) {
361 for (unsigned j
= 0; j
< 2; ++j
) {
363 state
.setCommitState(allCommitStates
[i
]);
366 state
.didEnterVSync();
367 state
.setVisible(false);
369 state
.setVisible(true);
371 // Case 1: needsCommit=false
372 state
.setNeedsCommit(false);
373 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
375 // Case 2: needsCommit=true
376 state
.setNeedsCommit(true);
377 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
381 // When on vsync, or not on vsync but needsForcedRedraw set, should always draw except if you're ready to commit, in which case commit.
382 for (size_t i
= 0; i
< numCommitStates
; ++i
) {
383 for (unsigned j
= 0; j
< 2; ++j
) {
385 state
.setCanDraw(true);
386 state
.setCommitState(allCommitStates
[i
]);
389 state
.didEnterVSync();
390 state
.setNeedsRedraw(true);
391 state
.setVisible(true);
393 state
.setNeedsForcedRedraw(true);
395 SchedulerStateMachine::Action expectedAction
;
396 if (allCommitStates
[i
] != SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
)
397 expectedAction
= forcedDraw
? SchedulerStateMachine::ACTION_DRAW_FORCED
: SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
;
399 expectedAction
= SchedulerStateMachine::ACTION_COMMIT
;
401 // Case 1: needsCommit=false.
402 state
.setNeedsCommit(false);
403 EXPECT_TRUE(state
.vsyncCallbackNeeded());
404 EXPECT_EQ(expectedAction
, state
.nextAction());
406 // Case 2: needsCommit=true.
407 state
.setNeedsCommit(true);
408 EXPECT_TRUE(state
.vsyncCallbackNeeded());
409 EXPECT_EQ(expectedAction
, state
.nextAction());
414 TEST(SchedulerStateMachineTest
, TestNoCommitStatesRedrawWhenInvisible
)
416 size_t numCommitStates
= sizeof(allCommitStates
) / sizeof(SchedulerStateMachine::CommitState
);
417 for (size_t i
= 0; i
< numCommitStates
; ++i
) {
418 // There shouldn't be any drawing regardless of vsync.
419 for (unsigned j
= 0; j
< 2; ++j
) {
421 state
.setCommitState(allCommitStates
[i
]);
422 state
.setVisible(false);
423 state
.setNeedsRedraw(true);
424 state
.setNeedsForcedRedraw(false);
426 state
.didEnterVSync();
428 // Case 1: needsCommit=false.
429 state
.setNeedsCommit(false);
430 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
432 // Case 2: needsCommit=true.
433 state
.setNeedsCommit(true);
434 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
439 TEST(SchedulerStateMachineTest
, TestCanRedraw_StopsDraw
)
441 size_t numCommitStates
= sizeof(allCommitStates
) / sizeof(SchedulerStateMachine::CommitState
);
442 for (size_t i
= 0; i
< numCommitStates
; ++i
) {
443 // There shouldn't be any drawing regardless of vsync.
444 for (unsigned j
= 0; j
< 2; ++j
) {
446 state
.setCommitState(allCommitStates
[i
]);
447 state
.setVisible(false);
448 state
.setNeedsRedraw(true);
449 state
.setNeedsForcedRedraw(false);
451 state
.didEnterVSync();
453 state
.setCanDraw(false);
454 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
459 TEST(SchedulerStateMachineTest
, TestCanRedrawWithWaitingForFirstDrawMakesProgress
)
462 state
.setCommitState(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW
);
463 state
.setCanBeginFrame(true);
464 state
.setNeedsCommit(true);
465 state
.setNeedsRedraw(true);
466 state
.setVisible(true);
467 state
.setCanDraw(false);
468 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
471 TEST(SchedulerStateMachineTest
, TestSetNeedsCommitIsNotLost
)
474 state
.setCanBeginFrame(true);
475 state
.setNeedsCommit(true);
476 state
.setVisible(true);
477 state
.setCanDraw(true);
480 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
481 state
.updateState(state
.nextAction());
482 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS
, state
.commitState());
484 // Now, while the frame is in progress, set another commit.
485 state
.setNeedsCommit(true);
486 EXPECT_TRUE(state
.needsCommit());
488 // Let the frame finish.
489 state
.beginFrameComplete();
490 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
, state
.commitState());
492 // Expect to commit regardless of vsync state.
493 state
.didLeaveVSync();
494 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT
, state
.nextAction());
495 state
.didEnterVSync();
496 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT
, state
.nextAction());
498 // Commit and make sure we draw on next vsync
499 state
.updateState(SchedulerStateMachine::ACTION_COMMIT
);
500 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
501 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW
, state
.commitState());
502 state
.updateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
);
503 state
.didDrawIfPossibleCompleted(true);
505 // Verify that another commit will begin.
506 state
.didLeaveVSync();
507 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
510 TEST(SchedulerStateMachineTest
, TestFullCycle
)
513 state
.setCanBeginFrame(true);
514 state
.setVisible(true);
515 state
.setCanDraw(true);
517 // Start clean and set commit.
518 state
.setNeedsCommit(true);
519 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
522 state
.updateState(SchedulerStateMachine::ACTION_BEGIN_FRAME
);
523 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS
, state
.commitState());
524 EXPECT_FALSE(state
.needsCommit());
525 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
527 // Tell the scheduler the frame finished.
528 state
.beginFrameComplete();
529 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
, state
.commitState());
530 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT
, state
.nextAction());
533 state
.updateState(SchedulerStateMachine::ACTION_COMMIT
);
534 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW
, state
.commitState());
535 EXPECT_TRUE(state
.needsRedraw());
537 // Expect to do nothing until vsync.
538 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
541 state
.didEnterVSync();
542 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
543 state
.updateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
);
544 state
.didDrawIfPossibleCompleted(true);
545 state
.didLeaveVSync();
547 // Should be synchronized, no draw needed, no action needed.
548 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE
, state
.commitState());
549 EXPECT_FALSE(state
.needsRedraw());
550 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
553 TEST(SchedulerStateMachineTest
, TestFullCycleWithCommitRequestInbetween
)
556 state
.setCanBeginFrame(true);
557 state
.setVisible(true);
558 state
.setCanDraw(true);
560 // Start clean and set commit.
561 state
.setNeedsCommit(true);
562 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
565 state
.updateState(SchedulerStateMachine::ACTION_BEGIN_FRAME
);
566 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS
, state
.commitState());
567 EXPECT_FALSE(state
.needsCommit());
568 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
570 // Request another commit while the commit is in flight.
571 state
.setNeedsCommit(true);
572 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
574 // Tell the scheduler the frame finished.
575 state
.beginFrameComplete();
576 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT
, state
.commitState());
577 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT
, state
.nextAction());
580 state
.updateState(SchedulerStateMachine::ACTION_COMMIT
);
581 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW
, state
.commitState());
582 EXPECT_TRUE(state
.needsRedraw());
584 // Expect to do nothing until vsync.
585 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
588 state
.didEnterVSync();
589 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
590 state
.updateState(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
);
591 state
.didDrawIfPossibleCompleted(true);
592 state
.didLeaveVSync();
594 // Should be synchronized, no draw needed, no action needed.
595 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE
, state
.commitState());
596 EXPECT_FALSE(state
.needsRedraw());
597 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
600 TEST(SchedulerStateMachineTest
, TestRequestCommitInvisible
)
603 state
.setNeedsCommit(true);
604 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
607 TEST(SchedulerStateMachineTest
, TestGoesInvisibleBeforeBeginFrameCompletes
)
610 state
.setCanBeginFrame(true);
611 state
.setVisible(true);
612 state
.setCanDraw(true);
614 // Start clean and set commit.
615 state
.setNeedsCommit(true);
616 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
618 // Begin the frame while visible.
619 state
.updateState(SchedulerStateMachine::ACTION_BEGIN_FRAME
);
620 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS
, state
.commitState());
621 EXPECT_FALSE(state
.needsCommit());
622 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
624 // Become invisible and abort the beginFrame.
625 state
.setVisible(false);
626 state
.beginFrameAborted();
628 // We should now be back in the idle state as if we didn't start a frame at all.
629 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE
, state
.commitState());
630 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
632 // Become visible again
633 state
.setVisible(true);
635 // We should be beginning a frame now
636 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE
, state
.commitState());
637 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
640 state
.updateState(state
.nextAction());
642 // We should be starting the commit now
643 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS
, state
.commitState());
646 TEST(SchedulerStateMachineTest
, TestContextLostWhenCompletelyIdle
)
649 state
.setCanBeginFrame(true);
650 state
.setVisible(true);
651 state
.setCanDraw(true);
653 state
.didLoseContext();
655 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION
, state
.nextAction());
656 state
.updateState(state
.nextAction());
658 // Once context recreation begins, nothing should happen.
659 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
661 // Recreate the context
662 state
.didRecreateContext();
664 // When the context is recreated, we should begin a commit
665 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
666 state
.updateState(state
.nextAction());
669 TEST(SchedulerStateMachineTest
, TestContextLostWhenIdleAndCommitRequestedWhileRecreating
)
672 state
.setCanBeginFrame(true);
673 state
.setVisible(true);
674 state
.setCanDraw(true);
676 state
.didLoseContext();
678 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION
, state
.nextAction());
679 state
.updateState(state
.nextAction());
681 // Once context recreation begins, nothing should happen.
682 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
684 // While context is recreating, commits shouldn't begin.
685 state
.setNeedsCommit(true);
686 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
688 // Recreate the context
689 state
.didRecreateContext();
691 // When the context is recreated, we should begin a commit
692 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
693 state
.updateState(state
.nextAction());
695 // Once the context is recreated, whether we draw should be based on
697 state
.setNeedsRedraw(true);
698 state
.didEnterVSync();
699 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
700 state
.setCanDraw(false);
701 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
702 state
.setCanDraw(true);
703 state
.didLeaveVSync();
706 TEST(SchedulerStateMachineTest
, TestContextLostWhileCommitInProgress
)
709 state
.setCanBeginFrame(true);
710 state
.setVisible(true);
711 state
.setCanDraw(true);
713 // Get a commit in flight.
714 state
.setNeedsCommit(true);
715 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
716 state
.updateState(state
.nextAction());
718 // Set damage and expect a draw.
719 state
.setNeedsRedraw(true);
720 state
.didEnterVSync();
721 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
722 state
.updateState(state
.nextAction());
723 state
.didLeaveVSync();
725 // Cause a lost context while the begin frame is in flight.
726 state
.didLoseContext();
728 // Ask for another draw. Expect nothing happens.
729 state
.setNeedsRedraw(true);
730 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
732 // Finish the frame, and commit.
733 state
.beginFrameComplete();
734 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT
, state
.nextAction());
735 state
.updateState(state
.nextAction());
737 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW
, state
.commitState());
739 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
740 state
.updateState(state
.nextAction());
742 // Expect to be told to begin context recreation, independent of vsync state
743 state
.didEnterVSync();
744 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION
, state
.nextAction());
745 state
.didLeaveVSync();
746 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION
, state
.nextAction());
749 TEST(SchedulerStateMachineTest
, TestContextLostWhileCommitInProgressAndAnotherCommitRequested
)
752 state
.setCanBeginFrame(true);
753 state
.setVisible(true);
754 state
.setCanDraw(true);
756 // Get a commit in flight.
757 state
.setNeedsCommit(true);
758 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
759 state
.updateState(state
.nextAction());
761 // Set damage and expect a draw.
762 state
.setNeedsRedraw(true);
763 state
.didEnterVSync();
764 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
765 state
.updateState(state
.nextAction());
766 state
.didLeaveVSync();
768 // Cause a lost context while the begin frame is in flight.
769 state
.didLoseContext();
771 // Ask for another draw and also set needs commit. Expect nothing happens.
772 state
.setNeedsRedraw(true);
773 state
.setNeedsCommit(true);
774 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE
, state
.nextAction());
776 // Finish the frame, and commit.
777 state
.beginFrameComplete();
778 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT
, state
.nextAction());
779 state
.updateState(state
.nextAction());
781 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW
, state
.commitState());
783 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE
, state
.nextAction());
784 state
.updateState(state
.nextAction());
786 // Expect to be told to begin context recreation, independent of vsync state
787 state
.didEnterVSync();
788 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION
, state
.nextAction());
789 state
.didLeaveVSync();
790 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION
, state
.nextAction());
794 TEST(SchedulerStateMachineTest
, TestFinishAllRenderingWhileContextLost
)
797 state
.setVisible(true);
798 state
.setCanDraw(true);
800 // Cause a lost context lost.
801 state
.didLoseContext();
803 // Ask a forced redraw and verify it ocurrs.
804 state
.setNeedsForcedRedraw(true);
805 state
.didEnterVSync();
806 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_FORCED
, state
.nextAction());
807 state
.didLeaveVSync();
809 // Clear the forced redraw bit.
810 state
.setNeedsForcedRedraw(false);
812 // Expect to be told to begin context recreation, independent of vsync state
813 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION
, state
.nextAction());
814 state
.updateState(state
.nextAction());
816 // Ask a forced redraw and verify it ocurrs.
817 state
.setNeedsForcedRedraw(true);
818 state
.didEnterVSync();
819 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_FORCED
, state
.nextAction());
820 state
.didLeaveVSync();
823 TEST(SchedulerStateMachineTest
, TestBeginFrameWhenInvisibleAndForceCommit
)
826 state
.setCanBeginFrame(true);
827 state
.setVisible(false);
828 state
.setNeedsCommit(true);
829 state
.setNeedsForcedCommit(true);
830 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
833 TEST(SchedulerStateMachineTest
, TestBeginFrameWhenCanBeginFrameFalseAndForceCommit
)
836 state
.setVisible(true);
837 state
.setCanDraw(true);
838 state
.setNeedsCommit(true);
839 state
.setNeedsForcedCommit(true);
840 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
843 TEST(SchedulerStateMachineTest
, TestBeginFrameWhenCommitInProgress
)
846 state
.setCanBeginFrame(true);
847 state
.setVisible(false);
848 state
.setCommitState(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS
);
849 state
.setNeedsCommit(true);
850 state
.setNeedsForcedCommit(true);
852 state
.beginFrameComplete();
853 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT
, state
.nextAction());
854 state
.updateState(state
.nextAction());
856 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW
, state
.commitState());
858 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
861 TEST(SchedulerStateMachineTest
, TestBeginFrameWhenContextLost
)
864 state
.setCanBeginFrame(true);
865 state
.setVisible(true);
866 state
.setCanDraw(true);
867 state
.setNeedsCommit(true);
868 state
.setNeedsForcedCommit(true);
869 state
.didLoseContext();
870 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_FRAME
, state
.nextAction());
873 } // anonymous namespace