1 // Copyright 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "cc/scheduler/scheduler_state_machine.h" 6 7 #include "cc/scheduler/scheduler.h" 8 #include "testing/gtest/include/gtest/gtest.h" 9 10 #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()) \ 18 return; \ 19 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, \ 20 state.begin_impl_frame_state()) \ 21 << *state.AsValue(); \ 22 } \ 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(); \ 31 } 32 33 namespace cc { 34 35 namespace { 36 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, }; 42 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, }; 48 49 // Exposes the protected state fields of the SchedulerStateMachine for testing 50 class StateMachine : public SchedulerStateMachine { 51 public: 52 explicit StateMachine(const SchedulerSettings& scheduler_settings) 53 : SchedulerStateMachine(scheduler_settings) {} 54 55 void CreateAndInitializeOutputSurfaceWithActivatedCommit() { 56 DidCreateAndInitializeOutputSurface(); 57 output_surface_state_ = OUTPUT_SURFACE_ACTIVE; 58 } 59 60 void SetCommitState(CommitState cs) { commit_state_ = cs; } 61 CommitState CommitState() const { return commit_state_; } 62 63 ForcedRedrawOnTimeoutState ForcedRedrawState() const { 64 return forced_redraw_state_; 65 } 66 67 void SetBeginImplFrameState(BeginImplFrameState bifs) { 68 begin_impl_frame_state_ = bifs; 69 } 70 71 BeginImplFrameState begin_impl_frame_state() const { 72 return begin_impl_frame_state_; 73 } 74 75 OutputSurfaceState output_surface_state() const { 76 return output_surface_state_; 77 } 78 79 bool NeedsCommit() const { return needs_commit_; } 80 81 void SetNeedsRedraw(bool b) { needs_redraw_ = b; } 82 83 void SetNeedsForcedRedrawForTimeout(bool b) { 84 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT; 85 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW; 86 } 87 bool NeedsForcedRedrawForTimeout() const { 88 return forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE; 89 } 90 91 void SetNeedsForcedRedrawForReadback() { 92 readback_state_ = READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK; 93 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW; 94 } 95 96 bool NeedsForcedRedrawForReadback() const { 97 return readback_state_ != READBACK_STATE_IDLE; 98 } 99 100 void SetActiveTreeNeedsFirstDraw(bool needs_first_draw) { 101 active_tree_needs_first_draw_ = needs_first_draw; 102 } 103 104 bool CanDraw() const { return can_draw_; } 105 bool Visible() const { return visible_; } 106 107 bool PendingActivationsShouldBeForced() const { 108 return SchedulerStateMachine::PendingActivationsShouldBeForced(); 109 } 110 }; 111 112 TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) { 113 SchedulerSettings default_scheduler_settings; 114 115 // If no commit needed, do nothing. 116 { 117 StateMachine state(default_scheduler_settings); 118 state.SetCanStart(); 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); 125 126 EXPECT_FALSE(state.BeginImplFrameNeeded()); 127 128 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 129 EXPECT_FALSE(state.BeginImplFrameNeeded()); 130 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 131 132 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 133 state.OnBeginImplFrameDeadline(); 134 } 135 136 // If commit requested but can_start is still false, do nothing. 137 { 138 StateMachine state(default_scheduler_settings); 139 state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE); 140 state.SetNeedsRedraw(false); 141 state.SetVisible(true); 142 143 EXPECT_FALSE(state.BeginImplFrameNeeded()); 144 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(); 150 } 151 152 // If commit requested, begin a main frame. 153 { 154 StateMachine state(default_scheduler_settings); 155 state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE); 156 state.SetCanStart(); 157 state.SetNeedsRedraw(false); 158 state.SetVisible(true); 159 EXPECT_FALSE(state.BeginImplFrameNeeded()); 160 } 161 162 // Begin the frame, make sure needs_commit and commit_state update correctly. 163 { 164 StateMachine state(default_scheduler_settings); 165 state.SetCanStart(); 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()); 173 } 174 } 175 176 TEST(SchedulerStateMachineTest, 177 TestFailedDrawSetsNeedsCommitAndDoesNotDrawAgain) { 178 SchedulerSettings default_scheduler_settings; 179 StateMachine state(default_scheduler_settings); 180 state.SetCanStart(); 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(); 191 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); 196 197 EXPECT_FALSE(state.RedrawPending()); 198 EXPECT_FALSE(state.CommitPending()); 199 200 // Failing the draw makes us require a commit. 201 state.DidDrawIfPossibleCompleted(false); 202 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 203 EXPECT_ACTION_UPDATE_STATE( 204 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 205 EXPECT_TRUE(state.RedrawPending()); 206 EXPECT_TRUE(state.CommitPending()); 207 } 208 209 TEST(SchedulerStateMachineTest, 210 TestsetNeedsRedrawDuringFailedDrawDoesNotRemoveNeedsRedraw) { 211 SchedulerSettings default_scheduler_settings; 212 StateMachine state(default_scheduler_settings); 213 state.SetCanStart(); 214 state.UpdateState(state.NextAction()); 215 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 216 217 state.SetVisible(true); 218 state.SetCanDraw(true); 219 state.SetNeedsRedraw(true); 220 EXPECT_TRUE(state.RedrawPending()); 221 EXPECT_TRUE(state.BeginImplFrameNeeded()); 222 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 223 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 224 state.OnBeginImplFrameDeadline(); 225 226 // We're drawing now. 227 EXPECT_ACTION_UPDATE_STATE( 228 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); 229 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 230 EXPECT_FALSE(state.RedrawPending()); 231 EXPECT_FALSE(state.CommitPending()); 232 233 // While still in the same BeginMainFrame callback on the main thread, 234 // set needs redraw again. This should not redraw. 235 state.SetNeedsRedraw(true); 236 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 237 238 // Failing the draw makes us require a commit. 239 state.DidDrawIfPossibleCompleted(false); 240 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 241 EXPECT_ACTION_UPDATE_STATE( 242 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 243 EXPECT_TRUE(state.RedrawPending()); 244 } 245 246 void TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit( 247 bool deadline_scheduling_enabled) { 248 SchedulerSettings scheduler_settings; 249 scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ = 1; 250 scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled; 251 StateMachine state(scheduler_settings); 252 state.SetCanStart(); 253 state.UpdateState(state.NextAction()); 254 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 255 state.SetVisible(true); 256 state.SetCanDraw(true); 257 258 // Start a commit. 259 state.SetNeedsCommit(); 260 if (!deadline_scheduling_enabled) { 261 EXPECT_ACTION_UPDATE_STATE( 262 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 263 } 264 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 265 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 266 if (deadline_scheduling_enabled) { 267 EXPECT_ACTION_UPDATE_STATE( 268 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 269 } 270 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 271 EXPECT_TRUE(state.CommitPending()); 272 273 // Then initiate a draw. 274 state.SetNeedsRedraw(true); 275 state.OnBeginImplFrameDeadline(); 276 EXPECT_ACTION_UPDATE_STATE( 277 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); 278 279 // Fail the draw. 280 state.DidDrawIfPossibleCompleted(false); 281 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 282 EXPECT_TRUE(state.BeginImplFrameNeeded()); 283 EXPECT_TRUE(state.RedrawPending()); 284 // But the commit is ongoing. 285 EXPECT_TRUE(state.CommitPending()); 286 287 // Finish the commit. Note, we should not yet be forcing a draw, but should 288 // continue the commit as usual. 289 state.FinishCommit(); 290 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 291 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 292 EXPECT_TRUE(state.RedrawPending()); 293 294 // The redraw should be forced at the end of the next BeginImplFrame. 295 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 296 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 297 state.OnBeginImplFrameDeadline(); 298 EXPECT_ACTION_UPDATE_STATE( 299 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED); 300 } 301 302 TEST(SchedulerStateMachineTest, 303 TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit) { 304 bool deadline_scheduling_enabled = false; 305 TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit( 306 deadline_scheduling_enabled); 307 } 308 309 TEST(SchedulerStateMachineTest, 310 TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit_Deadline) { 311 bool deadline_scheduling_enabled = true; 312 TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit( 313 deadline_scheduling_enabled); 314 } 315 316 void TestFailedDrawsDoNotRestartForcedDraw( 317 bool deadline_scheduling_enabled) { 318 SchedulerSettings scheduler_settings; 319 int drawLimit = 1; 320 scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ = 321 drawLimit; 322 scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled; 323 scheduler_settings.impl_side_painting = true; 324 StateMachine state(scheduler_settings); 325 state.SetCanStart(); 326 state.UpdateState(state.NextAction()); 327 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 328 state.SetVisible(true); 329 state.SetCanDraw(true); 330 331 // Start a commit. 332 state.SetNeedsCommit(); 333 if (!deadline_scheduling_enabled) { 334 EXPECT_ACTION_UPDATE_STATE( 335 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 336 } 337 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 338 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 339 if (deadline_scheduling_enabled) { 340 EXPECT_ACTION_UPDATE_STATE( 341 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 342 } 343 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 344 EXPECT_TRUE(state.CommitPending()); 345 346 // Then initiate a draw. 347 state.SetNeedsRedraw(true); 348 state.OnBeginImplFrameDeadline(); 349 EXPECT_ACTION_UPDATE_STATE( 350 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); 351 352 // Fail the draw enough times to force a redraw, 353 // then once more for good measure. 354 for (int i = 0; i < drawLimit; ++i) 355 state.DidDrawIfPossibleCompleted(false); 356 state.DidDrawIfPossibleCompleted(false); 357 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 358 EXPECT_TRUE(state.BeginImplFrameNeeded()); 359 EXPECT_TRUE(state.RedrawPending()); 360 // But the commit is ongoing. 361 EXPECT_TRUE(state.CommitPending()); 362 EXPECT_TRUE(state.ForcedRedrawState() == 363 SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_COMMIT); 364 365 state.FinishCommit(); 366 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 367 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 368 EXPECT_TRUE(state.RedrawPending()); 369 EXPECT_FALSE(state.CommitPending()); 370 371 // Now force redraw should be in waiting for activation 372 EXPECT_TRUE(state.ForcedRedrawState() == 373 SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION); 374 375 // After failing additional draws, we should still be in a forced 376 // redraw, but not back in WAITING_FOR_COMMIT. 377 for (int i = 0; i < drawLimit; ++i) 378 state.DidDrawIfPossibleCompleted(false); 379 state.DidDrawIfPossibleCompleted(false); 380 EXPECT_TRUE(state.RedrawPending()); 381 EXPECT_TRUE(state.ForcedRedrawState() == 382 SchedulerStateMachine::FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION); 383 } 384 385 TEST(SchedulerStateMachineTest, 386 TestFailedDrawsDoNotRestartForcedDraw) { 387 bool deadline_scheduling_enabled = false; 388 TestFailedDrawsDoNotRestartForcedDraw( 389 deadline_scheduling_enabled); 390 } 391 392 TEST(SchedulerStateMachineTest, 393 TestFailedDrawsDoNotRestartForcedDraw_Deadline) { 394 bool deadline_scheduling_enabled = true; 395 TestFailedDrawsDoNotRestartForcedDraw( 396 deadline_scheduling_enabled); 397 } 398 399 TEST(SchedulerStateMachineTest, TestFailedDrawIsRetriedInNextBeginImplFrame) { 400 SchedulerSettings default_scheduler_settings; 401 StateMachine state(default_scheduler_settings); 402 state.SetCanStart(); 403 state.UpdateState(state.NextAction()); 404 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 405 state.SetVisible(true); 406 state.SetCanDraw(true); 407 408 // Start a draw. 409 state.SetNeedsRedraw(true); 410 EXPECT_TRUE(state.BeginImplFrameNeeded()); 411 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 412 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 413 state.OnBeginImplFrameDeadline(); 414 EXPECT_TRUE(state.RedrawPending()); 415 EXPECT_ACTION_UPDATE_STATE( 416 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); 417 418 // Fail the draw 419 state.DidDrawIfPossibleCompleted(false); 420 EXPECT_ACTION_UPDATE_STATE( 421 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 422 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 423 EXPECT_TRUE(state.RedrawPending()); 424 425 // We should not be trying to draw again now, but we have a commit pending. 426 EXPECT_TRUE(state.BeginImplFrameNeeded()); 427 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 428 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 429 430 // We should try to draw again at the end of the next BeginImplFrame on 431 // the impl thread. 432 state.OnBeginImplFrameDeadline(); 433 EXPECT_ACTION_UPDATE_STATE( 434 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); 435 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 436 } 437 438 TEST(SchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame) { 439 SchedulerSettings default_scheduler_settings; 440 StateMachine state(default_scheduler_settings); 441 state.SetCanStart(); 442 state.UpdateState(state.NextAction()); 443 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 444 state.SetVisible(true); 445 state.SetCanDraw(true); 446 state.SetNeedsRedraw(true); 447 448 // Draw the first frame. 449 EXPECT_TRUE(state.BeginImplFrameNeeded()); 450 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 451 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 452 453 state.OnBeginImplFrameDeadline(); 454 EXPECT_ACTION_UPDATE_STATE( 455 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); 456 state.DidDrawIfPossibleCompleted(true); 457 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 458 459 // Before the next BeginImplFrame, set needs redraw again. 460 // This should not redraw until the next BeginImplFrame. 461 state.SetNeedsRedraw(true); 462 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 463 464 // Move to another frame. This should now draw. 465 EXPECT_TRUE(state.BeginImplFrameNeeded()); 466 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 467 468 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 469 470 state.OnBeginImplFrameDeadline(); 471 EXPECT_ACTION_UPDATE_STATE( 472 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); 473 state.DidDrawIfPossibleCompleted(true); 474 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 475 476 // We just swapped, so we should proactively request another BeginImplFrame. 477 EXPECT_TRUE(state.BeginImplFrameNeeded()); 478 } 479 480 TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginImplFrame) { 481 SchedulerSettings default_scheduler_settings; 482 483 // When not in BeginImplFrame deadline, or in BeginImplFrame deadline 484 // but not visible, don't draw. 485 size_t num_commit_states = 486 sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState); 487 size_t num_begin_impl_frame_states = 488 sizeof(all_begin_impl_frame_states) / 489 sizeof(SchedulerStateMachine::BeginImplFrameState); 490 for (size_t i = 0; i < num_commit_states; ++i) { 491 for (size_t j = 0; j < num_begin_impl_frame_states; ++j) { 492 StateMachine state(default_scheduler_settings); 493 state.SetCanStart(); 494 state.UpdateState(state.NextAction()); 495 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 496 state.SetCommitState(all_commit_states[i]); 497 state.SetBeginImplFrameState(all_begin_impl_frame_states[j]); 498 bool visible = 499 (all_begin_impl_frame_states[j] != 500 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE); 501 state.SetVisible(visible); 502 503 // Case 1: needs_commit=false 504 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE, 505 state.NextAction()); 506 507 // Case 2: needs_commit=true 508 state.SetNeedsCommit(); 509 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE, 510 state.NextAction()) 511 << *state.AsValue(); 512 } 513 } 514 515 // When in BeginImplFrame deadline we should always draw for SetNeedsRedraw or 516 // SetNeedsForcedRedrawForReadback have been called... except if we're 517 // ready to commit, in which case we expect a commit first. 518 for (size_t i = 0; i < num_commit_states; ++i) { 519 for (size_t j = 0; j < 2; ++j) { 520 bool request_readback = j; 521 522 // Skip invalid states 523 if (request_readback && 524 (SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW != 525 all_commit_states[i])) 526 continue; 527 528 StateMachine state(default_scheduler_settings); 529 state.SetCanStart(); 530 state.UpdateState(state.NextAction()); 531 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 532 state.SetCanDraw(true); 533 state.SetCommitState(all_commit_states[i]); 534 state.SetBeginImplFrameState( 535 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE); 536 if (request_readback) { 537 state.SetNeedsForcedRedrawForReadback(); 538 } else { 539 state.SetNeedsRedraw(true); 540 state.SetVisible(true); 541 } 542 543 SchedulerStateMachine::Action expected_action; 544 if (all_commit_states[i] == 545 SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT) { 546 expected_action = SchedulerStateMachine::ACTION_COMMIT; 547 } else if (request_readback) { 548 if (all_commit_states[i] == 549 SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW) 550 expected_action = SchedulerStateMachine::ACTION_DRAW_AND_READBACK; 551 else 552 expected_action = SchedulerStateMachine::ACTION_NONE; 553 } else { 554 expected_action = 555 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE; 556 } 557 558 // Case 1: needs_commit=false. 559 EXPECT_NE(state.BeginImplFrameNeeded(), request_readback) 560 << *state.AsValue(); 561 EXPECT_EQ(expected_action, state.NextAction()) << *state.AsValue(); 562 563 // Case 2: needs_commit=true. 564 state.SetNeedsCommit(); 565 EXPECT_NE(state.BeginImplFrameNeeded(), request_readback) 566 << *state.AsValue(); 567 EXPECT_EQ(expected_action, state.NextAction()) << *state.AsValue(); 568 } 569 } 570 } 571 572 TEST(SchedulerStateMachineTest, TestNoCommitStatesRedrawWhenInvisible) { 573 SchedulerSettings default_scheduler_settings; 574 575 size_t num_commit_states = 576 sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState); 577 for (size_t i = 0; i < num_commit_states; ++i) { 578 // There shouldn't be any drawing regardless of BeginImplFrame. 579 for (size_t j = 0; j < 2; ++j) { 580 StateMachine state(default_scheduler_settings); 581 state.SetCanStart(); 582 state.UpdateState(state.NextAction()); 583 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 584 state.SetCommitState(all_commit_states[i]); 585 state.SetVisible(false); 586 state.SetNeedsRedraw(true); 587 if (j == 1) { 588 state.SetBeginImplFrameState( 589 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE); 590 } 591 592 // Case 1: needs_commit=false. 593 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE, 594 state.NextAction()); 595 596 // Case 2: needs_commit=true. 597 state.SetNeedsCommit(); 598 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE, 599 state.NextAction()) 600 << *state.AsValue(); 601 } 602 } 603 } 604 605 TEST(SchedulerStateMachineTest, TestCanRedraw_StopsDraw) { 606 SchedulerSettings default_scheduler_settings; 607 608 size_t num_commit_states = 609 sizeof(all_commit_states) / sizeof(SchedulerStateMachine::CommitState); 610 for (size_t i = 0; i < num_commit_states; ++i) { 611 // There shouldn't be any drawing regardless of BeginImplFrame. 612 for (size_t j = 0; j < 2; ++j) { 613 StateMachine state(default_scheduler_settings); 614 state.SetCanStart(); 615 state.UpdateState(state.NextAction()); 616 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 617 state.SetCommitState(all_commit_states[i]); 618 state.SetVisible(false); 619 state.SetNeedsRedraw(true); 620 if (j == 1) 621 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 622 623 state.SetCanDraw(false); 624 EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE, 625 state.NextAction()); 626 } 627 } 628 } 629 630 TEST(SchedulerStateMachineTest, 631 TestCanRedrawWithWaitingForFirstDrawMakesProgress) { 632 SchedulerSettings default_scheduler_settings; 633 StateMachine state(default_scheduler_settings); 634 state.SetCanStart(); 635 state.UpdateState(state.NextAction()); 636 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 637 638 state.SetCommitState( 639 SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW); 640 state.SetActiveTreeNeedsFirstDraw(true); 641 state.SetNeedsCommit(); 642 state.SetNeedsRedraw(true); 643 state.SetVisible(true); 644 state.SetCanDraw(false); 645 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 646 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT); 647 EXPECT_ACTION_UPDATE_STATE( 648 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 649 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 650 state.FinishCommit(); 651 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 652 state.OnBeginImplFrameDeadline(); 653 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT); 654 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 655 } 656 657 TEST(SchedulerStateMachineTest, TestsetNeedsCommitIsNotLost) { 658 SchedulerSettings default_scheduler_settings; 659 StateMachine state(default_scheduler_settings); 660 state.SetCanStart(); 661 state.UpdateState(state.NextAction()); 662 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 663 state.SetNeedsCommit(); 664 state.SetVisible(true); 665 state.SetCanDraw(true); 666 667 EXPECT_TRUE(state.BeginImplFrameNeeded()); 668 669 // Begin the frame. 670 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 671 EXPECT_ACTION_UPDATE_STATE( 672 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 673 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, 674 state.CommitState()); 675 676 // Now, while the frame is in progress, set another commit. 677 state.SetNeedsCommit(); 678 EXPECT_TRUE(state.NeedsCommit()); 679 680 // Let the frame finish. 681 state.FinishCommit(); 682 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT, 683 state.CommitState()); 684 685 // Expect to commit regardless of BeginImplFrame state. 686 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING, 687 state.begin_impl_frame_state()); 688 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction()); 689 690 state.OnBeginImplFrameDeadlinePending(); 691 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME, 692 state.begin_impl_frame_state()); 693 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction()); 694 695 state.OnBeginImplFrameDeadline(); 696 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, 697 state.begin_impl_frame_state()); 698 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction()); 699 700 state.OnBeginImplFrameIdle(); 701 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE, 702 state.begin_impl_frame_state()); 703 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction()); 704 705 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 706 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING, 707 state.begin_impl_frame_state()); 708 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction()); 709 710 // Commit and make sure we draw on next BeginImplFrame 711 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 712 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 713 state.OnBeginImplFrameDeadline(); 714 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, 715 state.CommitState()); 716 EXPECT_ACTION_UPDATE_STATE( 717 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); 718 state.DidDrawIfPossibleCompleted(true); 719 720 // Verify that another commit will start immediately after draw. 721 EXPECT_ACTION_UPDATE_STATE( 722 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 723 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 724 } 725 726 TEST(SchedulerStateMachineTest, TestFullCycle) { 727 SchedulerSettings default_scheduler_settings; 728 StateMachine state(default_scheduler_settings); 729 state.SetCanStart(); 730 state.UpdateState(state.NextAction()); 731 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 732 state.SetVisible(true); 733 state.SetCanDraw(true); 734 735 // Start clean and set commit. 736 state.SetNeedsCommit(); 737 738 // Begin the frame. 739 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 740 EXPECT_ACTION_UPDATE_STATE( 741 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 742 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, 743 state.CommitState()); 744 EXPECT_FALSE(state.NeedsCommit()); 745 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 746 747 // Tell the scheduler the frame finished. 748 state.FinishCommit(); 749 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT, 750 state.CommitState()); 751 752 // Commit. 753 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 754 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, 755 state.CommitState()); 756 EXPECT_TRUE(state.needs_redraw()); 757 758 // Expect to do nothing until BeginImplFrame deadline 759 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 760 761 // At BeginImplFrame deadline, draw. 762 state.OnBeginImplFrameDeadline(); 763 EXPECT_ACTION_UPDATE_STATE( 764 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); 765 state.DidDrawIfPossibleCompleted(true); 766 767 // Should be synchronized, no draw needed, no action needed. 768 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 769 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); 770 EXPECT_FALSE(state.needs_redraw()); 771 } 772 773 TEST(SchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween) { 774 SchedulerSettings default_scheduler_settings; 775 StateMachine state(default_scheduler_settings); 776 state.SetCanStart(); 777 state.UpdateState(state.NextAction()); 778 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 779 state.SetVisible(true); 780 state.SetCanDraw(true); 781 782 // Start clean and set commit. 783 state.SetNeedsCommit(); 784 785 // Begin the frame. 786 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 787 EXPECT_ACTION_UPDATE_STATE( 788 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 789 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, 790 state.CommitState()); 791 EXPECT_FALSE(state.NeedsCommit()); 792 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 793 794 // Request another commit while the commit is in flight. 795 state.SetNeedsCommit(); 796 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 797 798 // Tell the scheduler the frame finished. 799 state.FinishCommit(); 800 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT, 801 state.CommitState()); 802 803 // First commit. 804 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 805 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, 806 state.CommitState()); 807 EXPECT_TRUE(state.needs_redraw()); 808 809 // Expect to do nothing until BeginImplFrame deadline. 810 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 811 812 // At BeginImplFrame deadline, draw. 813 state.OnBeginImplFrameDeadline(); 814 EXPECT_ACTION_UPDATE_STATE( 815 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); 816 state.DidDrawIfPossibleCompleted(true); 817 818 // Should be synchronized, no draw needed, no action needed. 819 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 820 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); 821 EXPECT_FALSE(state.needs_redraw()); 822 823 // Next BeginImplFrame should initiate second commit. 824 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 825 EXPECT_ACTION_UPDATE_STATE( 826 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 827 } 828 829 TEST(SchedulerStateMachineTest, TestRequestCommitInvisible) { 830 SchedulerSettings default_scheduler_settings; 831 StateMachine state(default_scheduler_settings); 832 state.SetCanStart(); 833 state.UpdateState(state.NextAction()); 834 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 835 state.SetNeedsCommit(); 836 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 837 } 838 839 TEST(SchedulerStateMachineTest, TestGoesInvisibleBeforeFinishCommit) { 840 SchedulerSettings default_scheduler_settings; 841 StateMachine state(default_scheduler_settings); 842 state.SetCanStart(); 843 state.UpdateState(state.NextAction()); 844 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 845 state.SetVisible(true); 846 state.SetCanDraw(true); 847 848 // Start clean and set commit. 849 state.SetNeedsCommit(); 850 851 // Begin the frame while visible. 852 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 853 EXPECT_ACTION_UPDATE_STATE( 854 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 855 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, 856 state.CommitState()); 857 EXPECT_FALSE(state.NeedsCommit()); 858 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 859 860 // Become invisible and abort BeginMainFrame. 861 state.SetVisible(false); 862 state.BeginMainFrameAborted(false); 863 864 // We should now be back in the idle state as if we never started the frame. 865 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); 866 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 867 868 // We shouldn't do anything on the BeginImplFrame deadline. 869 state.OnBeginImplFrameDeadline(); 870 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 871 872 // Become visible again. 873 state.SetVisible(true); 874 875 // Although we have aborted on this frame and haven't cancelled the commit 876 // (i.e. need another), don't send another BeginMainFrame yet. 877 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); 878 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); 879 EXPECT_TRUE(state.NeedsCommit()); 880 881 // Start a new frame. 882 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 883 EXPECT_ACTION_UPDATE_STATE( 884 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 885 886 // We should be starting the commit now. 887 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, 888 state.CommitState()); 889 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 890 } 891 892 TEST(SchedulerStateMachineTest, AbortBeginMainFrameAndCancelCommit) { 893 SchedulerSettings default_scheduler_settings; 894 StateMachine state(default_scheduler_settings); 895 state.SetCanStart(); 896 state.UpdateState(state.NextAction()); 897 state.DidCreateAndInitializeOutputSurface(); 898 state.SetVisible(true); 899 state.SetCanDraw(true); 900 901 // Get into a begin frame / commit state. 902 state.SetNeedsCommit(); 903 904 EXPECT_ACTION_UPDATE_STATE( 905 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 906 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, 907 state.CommitState()); 908 EXPECT_FALSE(state.NeedsCommit()); 909 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); 910 911 // Abort the commit, cancelling future commits. 912 state.BeginMainFrameAborted(true); 913 914 // Verify that another commit doesn't start on the same frame. 915 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); 916 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); 917 EXPECT_FALSE(state.NeedsCommit()); 918 919 // Start a new frame; draw because this is the first frame since output 920 // surface init'd. 921 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 922 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 923 state.OnBeginImplFrameDeadline(); 924 EXPECT_ACTION_UPDATE_STATE( 925 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); 926 927 // Verify another commit doesn't start on another frame either. 928 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); 929 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); 930 EXPECT_FALSE(state.NeedsCommit()); 931 932 // Verify another commit can start if requested, though. 933 state.SetNeedsCommit(); 934 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); 935 EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME, 936 state.NextAction()); 937 } 938 939 TEST(SchedulerStateMachineTest, TestFirstContextCreation) { 940 SchedulerSettings default_scheduler_settings; 941 StateMachine state(default_scheduler_settings); 942 state.SetCanStart(); 943 state.SetVisible(true); 944 state.SetCanDraw(true); 945 946 EXPECT_ACTION_UPDATE_STATE( 947 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION); 948 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 949 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 950 951 // Check that the first init does not SetNeedsCommit. 952 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 953 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 954 state.OnBeginImplFrameDeadline(); 955 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 956 957 // Check that a needs commit initiates a BeginMainFrame. 958 state.SetNeedsCommit(); 959 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 960 EXPECT_ACTION_UPDATE_STATE( 961 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 962 } 963 964 TEST(SchedulerStateMachineTest, TestContextLostWhenCompletelyIdle) { 965 SchedulerSettings default_scheduler_settings; 966 StateMachine state(default_scheduler_settings); 967 state.SetCanStart(); 968 state.UpdateState(state.NextAction()); 969 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 970 971 state.SetVisible(true); 972 state.SetCanDraw(true); 973 974 EXPECT_NE(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, 975 state.NextAction()); 976 state.DidLoseOutputSurface(); 977 978 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, 979 state.NextAction()); 980 state.UpdateState(state.NextAction()); 981 982 // Once context recreation begins, nothing should happen. 983 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 984 985 // Recreate the context. 986 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 987 988 // When the context is recreated, we should begin a commit. 989 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 990 EXPECT_ACTION_UPDATE_STATE( 991 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 992 } 993 994 TEST(SchedulerStateMachineTest, 995 TestContextLostWhenIdleAndCommitRequestedWhileRecreating) { 996 SchedulerSettings default_scheduler_settings; 997 StateMachine state(default_scheduler_settings); 998 state.SetCanStart(); 999 state.UpdateState(state.NextAction()); 1000 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1001 state.SetVisible(true); 1002 state.SetCanDraw(true); 1003 1004 EXPECT_NE(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, 1005 state.NextAction()); 1006 state.DidLoseOutputSurface(); 1007 1008 EXPECT_ACTION_UPDATE_STATE( 1009 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION); 1010 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1011 1012 // Once context recreation begins, nothing should happen. 1013 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 1014 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1015 state.OnBeginImplFrameDeadline(); 1016 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1017 1018 // While context is recreating, commits shouldn't begin. 1019 state.SetNeedsCommit(); 1020 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 1021 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1022 state.OnBeginImplFrameDeadline(); 1023 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1024 1025 // Recreate the context 1026 state.DidCreateAndInitializeOutputSurface(); 1027 EXPECT_FALSE(state.RedrawPending()); 1028 1029 // When the context is recreated, we should begin a commit 1030 EXPECT_ACTION_UPDATE_STATE( 1031 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 1032 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1033 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, 1034 state.CommitState()); 1035 state.FinishCommit(); 1036 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 1037 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1038 // Finishing the first commit after initializing an output surface should 1039 // automatically cause a redraw. 1040 EXPECT_TRUE(state.RedrawPending()); 1041 1042 // Once the context is recreated, whether we draw should be based on 1043 // SetCanDraw. 1044 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 1045 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1046 state.OnBeginImplFrameDeadline(); 1047 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE, 1048 state.NextAction()); 1049 state.SetCanDraw(false); 1050 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT, 1051 state.NextAction()); 1052 state.SetCanDraw(true); 1053 EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE, 1054 state.NextAction()); 1055 } 1056 1057 void TestContextLostWhileCommitInProgress(bool deadline_scheduling_enabled) { 1058 SchedulerSettings scheduler_settings; 1059 scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled; 1060 StateMachine state(scheduler_settings); 1061 state.SetCanStart(); 1062 state.UpdateState(state.NextAction()); 1063 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1064 state.SetVisible(true); 1065 state.SetCanDraw(true); 1066 1067 // Get a commit in flight. 1068 state.SetNeedsCommit(); 1069 if (!deadline_scheduling_enabled) { 1070 EXPECT_ACTION_UPDATE_STATE( 1071 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 1072 } 1073 1074 // Set damage and expect a draw. 1075 state.SetNeedsRedraw(true); 1076 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 1077 if (deadline_scheduling_enabled) { 1078 EXPECT_ACTION_UPDATE_STATE( 1079 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 1080 } 1081 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1082 state.OnBeginImplFrameDeadline(); 1083 EXPECT_ACTION_UPDATE_STATE( 1084 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); 1085 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1086 1087 // Cause a lost context while the BeginMainFrame is in flight. 1088 state.DidLoseOutputSurface(); 1089 1090 // Ask for another draw. Expect nothing happens. 1091 state.SetNeedsRedraw(true); 1092 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); 1093 1094 // Finish the frame, and commit. 1095 state.FinishCommit(); 1096 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 1097 1098 // We will abort the draw when the output surface is lost if we are 1099 // waiting for the first draw to unblock the main thread. 1100 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, 1101 state.CommitState()); 1102 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT); 1103 1104 // Expect to be told to begin context recreation, independent of 1105 // BeginImplFrame state. 1106 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE, 1107 state.begin_impl_frame_state()); 1108 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, 1109 state.NextAction()); 1110 1111 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 1112 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING, 1113 state.begin_impl_frame_state()); 1114 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, 1115 state.NextAction()); 1116 1117 state.OnBeginImplFrameDeadlinePending(); 1118 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME, 1119 state.begin_impl_frame_state()); 1120 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, 1121 state.NextAction()); 1122 1123 state.OnBeginImplFrameDeadline(); 1124 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, 1125 state.begin_impl_frame_state()); 1126 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, 1127 state.NextAction()); 1128 } 1129 1130 TEST(SchedulerStateMachineTest, TestContextLostWhileCommitInProgress) { 1131 bool deadline_scheduling_enabled = false; 1132 TestContextLostWhileCommitInProgress(deadline_scheduling_enabled); 1133 } 1134 1135 TEST(SchedulerStateMachineTest, TestContextLostWhileCommitInProgress_Deadline) { 1136 bool deadline_scheduling_enabled = true; 1137 TestContextLostWhileCommitInProgress(deadline_scheduling_enabled); 1138 } 1139 1140 void TestContextLostWhileCommitInProgressAndAnotherCommitRequested( 1141 bool deadline_scheduling_enabled) { 1142 SchedulerSettings scheduler_settings; 1143 scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled; 1144 StateMachine state(scheduler_settings); 1145 state.SetCanStart(); 1146 state.UpdateState(state.NextAction()); 1147 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1148 state.SetVisible(true); 1149 state.SetCanDraw(true); 1150 1151 // Get a commit in flight. 1152 state.SetNeedsCommit(); 1153 if (!deadline_scheduling_enabled) { 1154 EXPECT_ACTION_UPDATE_STATE( 1155 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 1156 } 1157 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1158 1159 // Set damage and expect a draw. 1160 state.SetNeedsRedraw(true); 1161 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 1162 if (deadline_scheduling_enabled) { 1163 EXPECT_ACTION_UPDATE_STATE( 1164 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 1165 } 1166 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1167 state.OnBeginImplFrameDeadline(); 1168 EXPECT_ACTION_UPDATE_STATE( 1169 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); 1170 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1171 1172 // Cause a lost context while the BeginMainFrame is in flight. 1173 state.DidLoseOutputSurface(); 1174 1175 // Ask for another draw and also set needs commit. Expect nothing happens. 1176 state.SetNeedsRedraw(true); 1177 state.SetNeedsCommit(); 1178 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1179 1180 // Finish the frame, and commit. 1181 state.FinishCommit(); 1182 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 1183 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, 1184 state.CommitState()); 1185 1186 // Because the output surface is missing, we expect the draw to abort. 1187 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT); 1188 1189 // Expect to be told to begin context recreation, independent of 1190 // BeginImplFrame state 1191 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE, 1192 state.begin_impl_frame_state()); 1193 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, 1194 state.NextAction()); 1195 1196 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 1197 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING, 1198 state.begin_impl_frame_state()); 1199 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, 1200 state.NextAction()); 1201 1202 state.OnBeginImplFrameDeadlinePending(); 1203 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME, 1204 state.begin_impl_frame_state()); 1205 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, 1206 state.NextAction()); 1207 1208 state.OnBeginImplFrameDeadline(); 1209 EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, 1210 state.begin_impl_frame_state()); 1211 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, 1212 state.NextAction()); 1213 1214 // After we get a new output surface, the commit flow should start. 1215 EXPECT_ACTION_UPDATE_STATE( 1216 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION); 1217 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1218 state.OnBeginImplFrameIdle(); 1219 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 1220 EXPECT_ACTION_UPDATE_STATE( 1221 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 1222 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1223 state.FinishCommit(); 1224 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 1225 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1226 state.OnBeginImplFrameDeadline(); 1227 EXPECT_ACTION_UPDATE_STATE( 1228 SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); 1229 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1230 } 1231 1232 TEST(SchedulerStateMachineTest, 1233 TestContextLostWhileCommitInProgressAndAnotherCommitRequested) { 1234 bool deadline_scheduling_enabled = false; 1235 TestContextLostWhileCommitInProgressAndAnotherCommitRequested( 1236 deadline_scheduling_enabled); 1237 } 1238 1239 TEST(SchedulerStateMachineTest, 1240 TestContextLostWhileCommitInProgressAndAnotherCommitRequested_Deadline) { 1241 bool deadline_scheduling_enabled = true; 1242 TestContextLostWhileCommitInProgressAndAnotherCommitRequested( 1243 deadline_scheduling_enabled); 1244 } 1245 1246 TEST(SchedulerStateMachineTest, TestFinishAllRenderingWhileContextLost) { 1247 SchedulerSettings default_scheduler_settings; 1248 StateMachine state(default_scheduler_settings); 1249 state.SetCanStart(); 1250 state.UpdateState(state.NextAction()); 1251 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1252 state.SetVisible(true); 1253 state.SetCanDraw(true); 1254 1255 // Cause a lost context lost. 1256 state.DidLoseOutputSurface(); 1257 1258 // Ask a forced redraw for readback and verify it ocurrs. 1259 state.SetCommitState( 1260 SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW); 1261 state.SetNeedsForcedRedrawForReadback(); 1262 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 1263 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_READBACK); 1264 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1265 1266 // Forced redraws for readbacks need to be followed by a new commit 1267 // to replace the readback commit. 1268 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, 1269 state.CommitState()); 1270 state.FinishCommit(); 1271 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 1272 1273 // We don't yet have an output surface, so we the draw and swap should abort. 1274 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT); 1275 1276 // Expect to be told to begin context recreation, independent of 1277 // BeginImplFrame state 1278 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); 1279 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, 1280 state.NextAction()); 1281 1282 state.OnBeginImplFrameDeadline(); 1283 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, 1284 state.NextAction()); 1285 1286 // Ask a readback and verify it occurs. 1287 state.SetCommitState( 1288 SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW); 1289 state.SetNeedsForcedRedrawForReadback(); 1290 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_READBACK); 1291 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1292 } 1293 1294 TEST(SchedulerStateMachineTest, DontDrawBeforeCommitAfterLostOutputSurface) { 1295 SchedulerSettings default_scheduler_settings; 1296 StateMachine state(default_scheduler_settings); 1297 state.SetCanStart(); 1298 state.UpdateState(state.NextAction()); 1299 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1300 state.SetVisible(true); 1301 state.SetCanDraw(true); 1302 1303 state.SetNeedsRedraw(true); 1304 1305 // Cause a lost output surface, and restore it. 1306 state.DidLoseOutputSurface(); 1307 EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, 1308 state.NextAction()); 1309 state.UpdateState(state.NextAction()); 1310 state.DidCreateAndInitializeOutputSurface(); 1311 1312 EXPECT_FALSE(state.RedrawPending()); 1313 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 1314 EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME, 1315 state.NextAction()); 1316 } 1317 1318 TEST(SchedulerStateMachineTest, 1319 TestSendBeginMainFrameWhenInvisibleAndForceCommit) { 1320 SchedulerSettings default_scheduler_settings; 1321 StateMachine state(default_scheduler_settings); 1322 state.SetCanStart(); 1323 state.UpdateState(state.NextAction()); 1324 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1325 state.SetVisible(false); 1326 state.SetNeedsCommit(); 1327 state.SetNeedsForcedCommitForReadback(); 1328 EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME, 1329 state.NextAction()); 1330 } 1331 1332 TEST(SchedulerStateMachineTest, 1333 TestSendBeginMainFrameWhenCanStartFalseAndForceCommit) { 1334 SchedulerSettings default_scheduler_settings; 1335 StateMachine state(default_scheduler_settings); 1336 state.SetVisible(true); 1337 state.SetCanDraw(true); 1338 state.SetNeedsCommit(); 1339 state.SetNeedsForcedCommitForReadback(); 1340 EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME, 1341 state.NextAction()); 1342 } 1343 1344 TEST(SchedulerStateMachineTest, TestFinishCommitWhenCommitInProgress) { 1345 SchedulerSettings default_scheduler_settings; 1346 StateMachine state(default_scheduler_settings); 1347 state.SetCanStart(); 1348 state.UpdateState(state.NextAction()); 1349 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1350 state.SetVisible(false); 1351 state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS); 1352 state.SetNeedsCommit(); 1353 1354 state.FinishCommit(); 1355 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction()); 1356 state.UpdateState(state.NextAction()); 1357 1358 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, 1359 state.CommitState()); 1360 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT); 1361 } 1362 1363 TEST(SchedulerStateMachineTest, TestFinishCommitWhenForcedCommitInProgress) { 1364 SchedulerSettings default_scheduler_settings; 1365 StateMachine state(default_scheduler_settings); 1366 state.SetCanStart(); 1367 state.UpdateState(state.NextAction()); 1368 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1369 state.SetVisible(false); 1370 state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS); 1371 state.SetNeedsCommit(); 1372 state.SetNeedsForcedCommitForReadback(); 1373 1374 // The commit for readback interupts the normal commit. 1375 state.FinishCommit(); 1376 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 1377 1378 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, 1379 state.CommitState()); 1380 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_READBACK); 1381 1382 // When the readback interrupts the normal commit, we should not get 1383 // another BeginMainFrame when the readback completes. 1384 EXPECT_NE(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME, 1385 state.NextAction()); 1386 1387 // The normal commit can then proceed. 1388 state.FinishCommit(); 1389 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 1390 } 1391 1392 TEST(SchedulerStateMachineTest, TestInitialActionsWhenContextLost) { 1393 SchedulerSettings default_scheduler_settings; 1394 StateMachine state(default_scheduler_settings); 1395 state.SetCanStart(); 1396 state.UpdateState(state.NextAction()); 1397 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1398 state.SetVisible(true); 1399 state.SetCanDraw(true); 1400 state.SetNeedsCommit(); 1401 state.DidLoseOutputSurface(); 1402 1403 // When we are visible, we normally want to begin output surface creation 1404 // as soon as possible. 1405 EXPECT_ACTION_UPDATE_STATE( 1406 SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION); 1407 1408 state.DidCreateAndInitializeOutputSurface(); 1409 EXPECT_EQ(state.output_surface_state(), 1410 SchedulerStateMachine::OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT); 1411 1412 // We should not send a BeginMainFrame when we are invisible, even if we've 1413 // lost the output surface and are trying to get the first commit, since the 1414 // main thread will just abort anyway. 1415 state.SetVisible(false); 1416 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()) 1417 << *state.AsValue(); 1418 1419 // If there is a forced commit, however, we could be blocking a readback 1420 // on the main thread, so we need to unblock it before we can get our 1421 // output surface, even if we are not visible. 1422 state.SetNeedsForcedCommitForReadback(); 1423 EXPECT_EQ( 1424 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME, state.NextAction()) 1425 << *state.AsValue(); 1426 } 1427 1428 TEST(SchedulerStateMachineTest, TestImmediateFinishCommit) { 1429 SchedulerSettings default_scheduler_settings; 1430 StateMachine state(default_scheduler_settings); 1431 state.SetCanStart(); 1432 state.UpdateState(state.NextAction()); 1433 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1434 state.SetVisible(true); 1435 state.SetCanDraw(true); 1436 1437 // Schedule a readback, commit it, draw it. 1438 state.SetNeedsCommit(); 1439 state.SetNeedsForcedCommitForReadback(); 1440 EXPECT_ACTION_UPDATE_STATE( 1441 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 1442 state.FinishCommit(); 1443 1444 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT, 1445 state.CommitState()); 1446 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 1447 1448 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, 1449 state.CommitState()); 1450 1451 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_READBACK); 1452 state.DidDrawIfPossibleCompleted(true); 1453 1454 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1455 1456 // Should be waiting for the normal BeginMainFrame. 1457 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, 1458 state.CommitState()); 1459 } 1460 1461 void TestImmediateFinishCommitDuringCommit(bool deadline_scheduling_enabled) { 1462 SchedulerSettings scheduler_settings; 1463 scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled; 1464 StateMachine state(scheduler_settings); 1465 state.SetCanStart(); 1466 state.UpdateState(state.NextAction()); 1467 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1468 state.SetVisible(true); 1469 state.SetCanDraw(true); 1470 1471 // Start a normal commit. 1472 state.SetNeedsCommit(); 1473 if (!deadline_scheduling_enabled) { 1474 EXPECT_ACTION_UPDATE_STATE( 1475 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 1476 } 1477 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1478 1479 // Schedule a readback, commit it, draw it. 1480 state.SetNeedsForcedCommitForReadback(); 1481 if (deadline_scheduling_enabled) { 1482 EXPECT_ACTION_UPDATE_STATE( 1483 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 1484 } 1485 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1486 state.FinishCommit(); 1487 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT, 1488 state.CommitState()); 1489 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 1490 1491 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, 1492 state.CommitState()); 1493 1494 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_READBACK); 1495 state.DidDrawIfPossibleCompleted(true); 1496 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1497 1498 // Should be waiting for the normal BeginMainFrame. 1499 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, 1500 state.CommitState()) 1501 << *state.AsValue(); 1502 } 1503 1504 TEST(SchedulerStateMachineTest, TestImmediateFinishCommitDuringCommit) { 1505 bool deadline_scheduling_enabled = false; 1506 TestImmediateFinishCommitDuringCommit(deadline_scheduling_enabled); 1507 } 1508 1509 TEST(SchedulerStateMachineTest, 1510 TestImmediateFinishCommitDuringCommit_Deadline) { 1511 bool deadline_scheduling_enabled = true; 1512 TestImmediateFinishCommitDuringCommit(deadline_scheduling_enabled); 1513 } 1514 1515 void ImmediateBeginMainFrameAbortedWhileInvisible( 1516 bool deadline_scheduling_enabled) { 1517 SchedulerSettings scheduler_settings; 1518 scheduler_settings.deadline_scheduling_enabled = deadline_scheduling_enabled; 1519 StateMachine state(scheduler_settings); 1520 state.SetCanStart(); 1521 state.UpdateState(state.NextAction()); 1522 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1523 state.SetVisible(true); 1524 state.SetCanDraw(true); 1525 1526 state.SetNeedsCommit(); 1527 if (!deadline_scheduling_enabled) { 1528 EXPECT_ACTION_UPDATE_STATE( 1529 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 1530 } 1531 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1532 1533 state.SetNeedsCommit(); 1534 state.SetNeedsForcedCommitForReadback(); 1535 if (deadline_scheduling_enabled) { 1536 EXPECT_ACTION_UPDATE_STATE( 1537 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 1538 } 1539 state.FinishCommit(); 1540 1541 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT, 1542 state.CommitState()); 1543 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 1544 1545 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, 1546 state.CommitState()); 1547 1548 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_READBACK); 1549 state.DidDrawIfPossibleCompleted(true); 1550 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1551 1552 // Should be waiting for BeginMainFrame. 1553 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS, 1554 state.CommitState()) 1555 << *state.AsValue(); 1556 1557 // Become invisible and abort BeginMainFrame. 1558 state.SetVisible(false); 1559 state.BeginMainFrameAborted(false); 1560 1561 // Should be back in the idle state, but needing a commit. 1562 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); 1563 EXPECT_TRUE(state.NeedsCommit()); 1564 } 1565 1566 TEST(SchedulerStateMachineTest, 1567 ImmediateBeginMainFrameAbortedWhileInvisible) { 1568 bool deadline_scheduling_enabled = false; 1569 ImmediateBeginMainFrameAbortedWhileInvisible( 1570 deadline_scheduling_enabled); 1571 } 1572 1573 TEST(SchedulerStateMachineTest, 1574 ImmediateBeginMainFrameAbortedWhileInvisible_Deadline) { 1575 bool deadline_scheduling_enabled = true; 1576 ImmediateBeginMainFrameAbortedWhileInvisible( 1577 deadline_scheduling_enabled); 1578 } 1579 1580 TEST(SchedulerStateMachineTest, ImmediateFinishCommitWhileCantDraw) { 1581 SchedulerSettings default_scheduler_settings; 1582 StateMachine state(default_scheduler_settings); 1583 state.SetCanStart(); 1584 state.UpdateState(state.NextAction()); 1585 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1586 state.SetVisible(true); 1587 state.SetCanDraw(false); 1588 1589 state.SetNeedsCommit(); 1590 state.UpdateState(state.NextAction()); 1591 1592 state.SetNeedsCommit(); 1593 state.SetNeedsForcedCommitForReadback(); 1594 state.UpdateState(state.NextAction()); 1595 state.FinishCommit(); 1596 1597 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT, 1598 state.CommitState()); 1599 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); 1600 1601 EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW, 1602 state.CommitState()); 1603 1604 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_READBACK); 1605 state.DidDrawIfPossibleCompleted(true); 1606 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1607 } 1608 1609 TEST(SchedulerStateMachineTest, ReportIfNotDrawing) { 1610 SchedulerSettings default_scheduler_settings; 1611 StateMachine state(default_scheduler_settings); 1612 state.SetCanStart(); 1613 state.UpdateState(state.NextAction()); 1614 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1615 1616 state.SetCanDraw(true); 1617 state.SetVisible(true); 1618 EXPECT_FALSE(state.PendingDrawsShouldBeAborted()); 1619 1620 state.SetCanDraw(false); 1621 state.SetVisible(true); 1622 EXPECT_TRUE(state.PendingDrawsShouldBeAborted()); 1623 1624 state.SetCanDraw(true); 1625 state.SetVisible(false); 1626 EXPECT_TRUE(state.PendingDrawsShouldBeAborted()); 1627 1628 state.SetCanDraw(false); 1629 state.SetVisible(false); 1630 EXPECT_TRUE(state.PendingDrawsShouldBeAborted()); 1631 1632 state.SetCanDraw(true); 1633 state.SetVisible(true); 1634 EXPECT_FALSE(state.PendingDrawsShouldBeAborted()); 1635 } 1636 1637 TEST(SchedulerStateMachineTest, ReportIfNotDrawingFromAcquiredTextures) { 1638 SchedulerSettings default_scheduler_settings; 1639 StateMachine state(default_scheduler_settings); 1640 state.SetCanStart(); 1641 state.UpdateState(state.NextAction()); 1642 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1643 state.SetCanDraw(true); 1644 state.SetVisible(true); 1645 EXPECT_FALSE(state.PendingDrawsShouldBeAborted()); 1646 1647 state.SetMainThreadNeedsLayerTextures(); 1648 EXPECT_ACTION_UPDATE_STATE( 1649 SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD); 1650 EXPECT_TRUE(state.PendingDrawsShouldBeAborted()); 1651 EXPECT_TRUE(state.PendingActivationsShouldBeForced()); 1652 1653 state.SetNeedsCommit(); 1654 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 1655 EXPECT_ACTION_UPDATE_STATE( 1656 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 1657 EXPECT_TRUE(state.PendingDrawsShouldBeAborted()); 1658 EXPECT_TRUE(state.PendingActivationsShouldBeForced()); 1659 1660 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); 1661 1662 state.FinishCommit(); 1663 EXPECT_TRUE(state.PendingDrawsShouldBeAborted()); 1664 1665 EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction()); 1666 1667 state.UpdateState(state.NextAction()); 1668 EXPECT_FALSE(state.PendingDrawsShouldBeAborted()); 1669 } 1670 1671 TEST(SchedulerStateMachineTest, AcquireTexturesWithAbort) { 1672 SchedulerSettings default_scheduler_settings; 1673 StateMachine state(default_scheduler_settings); 1674 state.SetCanStart(); 1675 state.UpdateState(state.NextAction()); 1676 state.DidCreateAndInitializeOutputSurface(); 1677 state.SetCanDraw(true); 1678 state.SetVisible(true); 1679 1680 state.SetMainThreadNeedsLayerTextures(); 1681 EXPECT_EQ( 1682 SchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD, 1683 state.NextAction()); 1684 state.UpdateState(state.NextAction()); 1685 EXPECT_TRUE(state.PendingDrawsShouldBeAborted()); 1686 1687 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); 1688 1689 state.SetNeedsCommit(); 1690 EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME, 1691 state.NextAction()); 1692 state.UpdateState(state.NextAction()); 1693 EXPECT_TRUE(state.PendingDrawsShouldBeAborted()); 1694 1695 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); 1696 1697 state.BeginMainFrameAborted(true); 1698 1699 EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); 1700 EXPECT_FALSE(state.PendingDrawsShouldBeAborted()); 1701 } 1702 1703 TEST(SchedulerStateMachineTest, 1704 TestTriggerDeadlineEarlyAfterAbortedCommit) { 1705 SchedulerSettings settings; 1706 settings.deadline_scheduling_enabled = true; 1707 settings.impl_side_painting = true; 1708 StateMachine state(settings); 1709 state.SetCanStart(); 1710 state.UpdateState(state.NextAction()); 1711 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1712 state.SetVisible(true); 1713 state.SetCanDraw(true); 1714 1715 // This test mirrors what happens during the first frame of a scroll gesture. 1716 // First we get the input event and a BeginFrame. 1717 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 1718 1719 // As a response the compositor requests a redraw and a commit to tell the 1720 // main thread about the new scroll offset. 1721 state.SetNeedsRedraw(true); 1722 state.SetNeedsCommit(); 1723 1724 // We should start the commit normally. 1725 EXPECT_ACTION_UPDATE_STATE( 1726 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 1727 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1728 1729 // Since only the scroll offset changed, the main thread will abort the 1730 // commit. 1731 state.BeginMainFrameAborted(true); 1732 1733 // Since the commit was aborted, we should draw right away instead of waiting 1734 // for the deadline. 1735 EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly()); 1736 } 1737 1738 TEST(SchedulerStateMachineTest, TestTriggerDeadlineEarlyForSmoothness) { 1739 SchedulerSettings settings; 1740 settings.deadline_scheduling_enabled = true; 1741 settings.impl_side_painting = true; 1742 StateMachine state(settings); 1743 state.SetCanStart(); 1744 state.UpdateState(state.NextAction()); 1745 state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); 1746 state.SetVisible(true); 1747 state.SetCanDraw(true); 1748 1749 // This test ensures that impl-draws are prioritized over main thread updates 1750 // in prefer smoothness mode. 1751 state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); 1752 state.SetNeedsRedraw(true); 1753 state.SetNeedsCommit(); 1754 EXPECT_ACTION_UPDATE_STATE( 1755 SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); 1756 EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); 1757 1758 // The deadline is not triggered early until we enter prefer smoothness mode. 1759 EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineEarly()); 1760 state.SetSmoothnessTakesPriority(true); 1761 EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly()); 1762 } 1763 1764 } // namespace 1765 } // namespace cc 1766