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 "base/debug/trace_event.h" 8 #include "base/format_macros.h" 9 #include "base/logging.h" 10 #include "base/strings/stringprintf.h" 11 #include "base/values.h" 12 #include "ui/gfx/frame_time.h" 13 14 namespace cc { 15 16 SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) 17 : settings_(settings), 18 output_surface_state_(OUTPUT_SURFACE_LOST), 19 begin_impl_frame_state_(BEGIN_IMPL_FRAME_STATE_IDLE), 20 commit_state_(COMMIT_STATE_IDLE), 21 texture_state_(LAYER_TEXTURE_STATE_UNLOCKED), 22 forced_redraw_state_(FORCED_REDRAW_STATE_IDLE), 23 readback_state_(READBACK_STATE_IDLE), 24 commit_count_(0), 25 current_frame_number_(0), 26 last_frame_number_swap_performed_(-1), 27 last_frame_number_begin_main_frame_sent_(-1), 28 last_frame_number_update_visible_tiles_was_called_(-1), 29 last_frame_number_manage_tiles_called_(-1), 30 consecutive_failed_draws_(0), 31 needs_redraw_(false), 32 needs_manage_tiles_(false), 33 swap_used_incomplete_tile_(false), 34 needs_commit_(false), 35 main_thread_needs_layer_textures_(false), 36 inside_poll_for_anticipated_draw_triggers_(false), 37 visible_(false), 38 can_start_(false), 39 can_draw_(false), 40 has_pending_tree_(false), 41 pending_tree_is_ready_for_activation_(false), 42 active_tree_needs_first_draw_(false), 43 draw_if_possible_failed_(false), 44 did_create_and_initialize_first_output_surface_(false), 45 smoothness_takes_priority_(false), 46 skip_begin_main_frame_to_reduce_latency_(false) {} 47 48 const char* SchedulerStateMachine::OutputSurfaceStateToString( 49 OutputSurfaceState state) { 50 switch (state) { 51 case OUTPUT_SURFACE_ACTIVE: 52 return "OUTPUT_SURFACE_ACTIVE"; 53 case OUTPUT_SURFACE_LOST: 54 return "OUTPUT_SURFACE_LOST"; 55 case OUTPUT_SURFACE_CREATING: 56 return "OUTPUT_SURFACE_CREATING"; 57 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: 58 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT"; 59 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: 60 return "OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION"; 61 } 62 NOTREACHED(); 63 return "???"; 64 } 65 66 const char* SchedulerStateMachine::BeginImplFrameStateToString( 67 BeginImplFrameState state) { 68 switch (state) { 69 case BEGIN_IMPL_FRAME_STATE_IDLE: 70 return "BEGIN_IMPL_FRAME_STATE_IDLE"; 71 case BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING: 72 return "BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING"; 73 case BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME: 74 return "BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME"; 75 case BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE: 76 return "BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE"; 77 } 78 NOTREACHED(); 79 return "???"; 80 } 81 82 const char* SchedulerStateMachine::CommitStateToString(CommitState state) { 83 switch (state) { 84 case COMMIT_STATE_IDLE: 85 return "COMMIT_STATE_IDLE"; 86 case COMMIT_STATE_FRAME_IN_PROGRESS: 87 return "COMMIT_STATE_FRAME_IN_PROGRESS"; 88 case COMMIT_STATE_READY_TO_COMMIT: 89 return "COMMIT_STATE_READY_TO_COMMIT"; 90 case COMMIT_STATE_WAITING_FOR_FIRST_DRAW: 91 return "COMMIT_STATE_WAITING_FOR_FIRST_DRAW"; 92 } 93 NOTREACHED(); 94 return "???"; 95 } 96 97 const char* SchedulerStateMachine::TextureStateToString(TextureState state) { 98 switch (state) { 99 case LAYER_TEXTURE_STATE_UNLOCKED: 100 return "LAYER_TEXTURE_STATE_UNLOCKED"; 101 case LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD: 102 return "LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD"; 103 case LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD: 104 return "LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD"; 105 } 106 NOTREACHED(); 107 return "???"; 108 } 109 110 const char* SchedulerStateMachine::SynchronousReadbackStateToString( 111 SynchronousReadbackState state) { 112 switch (state) { 113 case READBACK_STATE_IDLE: 114 return "READBACK_STATE_IDLE"; 115 case READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME: 116 return "READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME"; 117 case READBACK_STATE_WAITING_FOR_COMMIT: 118 return "READBACK_STATE_WAITING_FOR_COMMIT"; 119 case READBACK_STATE_WAITING_FOR_ACTIVATION: 120 return "READBACK_STATE_WAITING_FOR_ACTIVATION"; 121 case READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK: 122 return "READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK"; 123 case READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT: 124 return "READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT"; 125 case READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION: 126 return "READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION"; 127 } 128 NOTREACHED(); 129 return "???"; 130 } 131 132 const char* SchedulerStateMachine::ForcedRedrawOnTimeoutStateToString( 133 ForcedRedrawOnTimeoutState state) { 134 switch (state) { 135 case FORCED_REDRAW_STATE_IDLE: 136 return "FORCED_REDRAW_STATE_IDLE"; 137 case FORCED_REDRAW_STATE_WAITING_FOR_COMMIT: 138 return "FORCED_REDRAW_STATE_WAITING_FOR_COMMIT"; 139 case FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION: 140 return "FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION"; 141 case FORCED_REDRAW_STATE_WAITING_FOR_DRAW: 142 return "FORCED_REDRAW_STATE_WAITING_FOR_DRAW"; 143 } 144 NOTREACHED(); 145 return "???"; 146 } 147 148 const char* SchedulerStateMachine::ActionToString(Action action) { 149 switch (action) { 150 case ACTION_NONE: 151 return "ACTION_NONE"; 152 case ACTION_SEND_BEGIN_MAIN_FRAME: 153 return "ACTION_SEND_BEGIN_MAIN_FRAME"; 154 case ACTION_COMMIT: 155 return "ACTION_COMMIT"; 156 case ACTION_UPDATE_VISIBLE_TILES: 157 return "ACTION_UPDATE_VISIBLE_TILES"; 158 case ACTION_ACTIVATE_PENDING_TREE: 159 return "ACTION_ACTIVATE_PENDING_TREE"; 160 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: 161 return "ACTION_DRAW_AND_SWAP_IF_POSSIBLE"; 162 case ACTION_DRAW_AND_SWAP_FORCED: 163 return "ACTION_DRAW_AND_SWAP_FORCED"; 164 case ACTION_DRAW_AND_SWAP_ABORT: 165 return "ACTION_DRAW_AND_SWAP_ABORT"; 166 case ACTION_DRAW_AND_READBACK: 167 return "ACTION_DRAW_AND_READBACK"; 168 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION: 169 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION"; 170 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: 171 return "ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD"; 172 case ACTION_MANAGE_TILES: 173 return "ACTION_MANAGE_TILES"; 174 } 175 NOTREACHED(); 176 return "???"; 177 } 178 179 scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const { 180 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); 181 182 scoped_ptr<base::DictionaryValue> major_state(new base::DictionaryValue); 183 major_state->SetString("next_action", ActionToString(NextAction())); 184 major_state->SetString("begin_impl_frame_state", 185 BeginImplFrameStateToString(begin_impl_frame_state_)); 186 major_state->SetString("commit_state", CommitStateToString(commit_state_)); 187 major_state->SetString("texture_state_", 188 TextureStateToString(texture_state_)); 189 major_state->SetString("output_surface_state_", 190 OutputSurfaceStateToString(output_surface_state_)); 191 major_state->SetString( 192 "forced_redraw_state", 193 ForcedRedrawOnTimeoutStateToString(forced_redraw_state_)); 194 major_state->SetString("readback_state", 195 SynchronousReadbackStateToString(readback_state_)); 196 state->Set("major_state", major_state.release()); 197 198 scoped_ptr<base::DictionaryValue> timestamps_state(new base::DictionaryValue); 199 base::TimeTicks now = gfx::FrameTime::Now(); 200 timestamps_state->SetDouble( 201 "0_interval", 202 last_begin_impl_frame_args_.interval.InMicroseconds() / 1000.0L); 203 timestamps_state->SetDouble( 204 "1_now_to_deadline", 205 (last_begin_impl_frame_args_.deadline - now).InMicroseconds() / 1000.0L); 206 timestamps_state->SetDouble( 207 "2_frame_time_to_now", 208 (now - last_begin_impl_frame_args_.frame_time).InMicroseconds() / 209 1000.0L); 210 timestamps_state->SetDouble( 211 "3_frame_time_to_deadline", 212 (last_begin_impl_frame_args_.deadline - 213 last_begin_impl_frame_args_.frame_time).InMicroseconds() / 214 1000.0L); 215 timestamps_state->SetDouble( 216 "4_now", (now - base::TimeTicks()).InMicroseconds() / 1000.0L); 217 timestamps_state->SetDouble( 218 "5_frame_time", 219 (last_begin_impl_frame_args_.frame_time - base::TimeTicks()) 220 .InMicroseconds() / 221 1000.0L); 222 timestamps_state->SetDouble( 223 "6_deadline", 224 (last_begin_impl_frame_args_.deadline - base::TimeTicks()) 225 .InMicroseconds() / 226 1000.0L); 227 state->Set("major_timestamps_in_ms", timestamps_state.release()); 228 229 scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue); 230 minor_state->SetInteger("commit_count", commit_count_); 231 minor_state->SetInteger("current_frame_number", current_frame_number_); 232 233 minor_state->SetInteger("last_frame_number_swap_performed", 234 last_frame_number_swap_performed_); 235 minor_state->SetInteger( 236 "last_frame_number_begin_main_frame_sent", 237 last_frame_number_begin_main_frame_sent_); 238 minor_state->SetInteger( 239 "last_frame_number_update_visible_tiles_was_called", 240 last_frame_number_update_visible_tiles_was_called_); 241 242 minor_state->SetInteger("consecutive_failed_draws", 243 consecutive_failed_draws_); 244 minor_state->SetBoolean("needs_redraw", needs_redraw_); 245 minor_state->SetBoolean("needs_manage_tiles", needs_manage_tiles_); 246 minor_state->SetBoolean("swap_used_incomplete_tile", 247 swap_used_incomplete_tile_); 248 minor_state->SetBoolean("needs_commit", needs_commit_); 249 minor_state->SetBoolean("main_thread_needs_layer_textures", 250 main_thread_needs_layer_textures_); 251 minor_state->SetBoolean("visible", visible_); 252 minor_state->SetBoolean("can_start", can_start_); 253 minor_state->SetBoolean("can_draw", can_draw_); 254 minor_state->SetBoolean("has_pending_tree", has_pending_tree_); 255 minor_state->SetBoolean("pending_tree_is_ready_for_activation", 256 pending_tree_is_ready_for_activation_); 257 minor_state->SetBoolean("active_tree_needs_first_draw", 258 active_tree_needs_first_draw_); 259 minor_state->SetBoolean("draw_if_possible_failed", draw_if_possible_failed_); 260 minor_state->SetBoolean("did_create_and_initialize_first_output_surface", 261 did_create_and_initialize_first_output_surface_); 262 minor_state->SetBoolean("smoothness_takes_priority", 263 smoothness_takes_priority_); 264 minor_state->SetBoolean("main_thread_is_in_high_latency_mode", 265 MainThreadIsInHighLatencyMode()); 266 minor_state->SetBoolean("skip_begin_main_frame_to_reduce_latency", 267 skip_begin_main_frame_to_reduce_latency_); 268 state->Set("minor_state", minor_state.release()); 269 270 return state.PassAs<base::Value>(); 271 } 272 273 bool SchedulerStateMachine::HasSentBeginMainFrameThisFrame() const { 274 return current_frame_number_ == 275 last_frame_number_begin_main_frame_sent_; 276 } 277 278 bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const { 279 return current_frame_number_ == 280 last_frame_number_update_visible_tiles_was_called_; 281 } 282 283 bool SchedulerStateMachine::HasSwappedThisFrame() const { 284 return current_frame_number_ == last_frame_number_swap_performed_; 285 } 286 287 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const { 288 // These are all the cases where we normally cannot or do not want to draw 289 // but, if needs_redraw_ is true and we do not draw to make forward progress, 290 // we might deadlock with the main thread. 291 // This should be a superset of PendingActivationsShouldBeForced() since 292 // activation of the pending tree is blocked by drawing of the active tree and 293 // the main thread might be blocked on activation of the most recent commit. 294 if (PendingActivationsShouldBeForced()) 295 return true; 296 297 // Additional states where we should abort draws. 298 // Note: We don't force activation in these cases because doing so would 299 // result in checkerboarding on resize, becoming visible, etc. 300 if (!can_draw_) 301 return true; 302 if (!visible_) 303 return true; 304 return false; 305 } 306 307 bool SchedulerStateMachine::PendingActivationsShouldBeForced() const { 308 // These are all the cases where, if we do not force activations to make 309 // forward progress, we might deadlock with the main thread. 310 311 // The impl thread cannot lock layer textures unless the pending 312 // tree can be activated to unblock the commit. 313 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD) 314 return true; 315 316 // There is no output surface to trigger our activations. 317 if (output_surface_state_ == OUTPUT_SURFACE_LOST) 318 return true; 319 320 return false; 321 } 322 323 bool SchedulerStateMachine::ShouldBeginOutputSurfaceCreation() const { 324 // Don't try to initialize too early. 325 if (!can_start_) 326 return false; 327 328 // We only want to start output surface initialization after the 329 // previous commit is complete. 330 if (commit_state_ != COMMIT_STATE_IDLE) 331 return false; 332 333 // We want to clear the pipline of any pending draws and activations 334 // before starting output surface initialization. This allows us to avoid 335 // weird corner cases where we abort draws or force activation while we 336 // are initializing the output surface and can potentially have a pending 337 // readback. 338 if (active_tree_needs_first_draw_ || has_pending_tree_) 339 return false; 340 341 // We need to create the output surface if we don't have one and we haven't 342 // started creating one yet. 343 return output_surface_state_ == OUTPUT_SURFACE_LOST; 344 } 345 346 bool SchedulerStateMachine::ShouldDraw() const { 347 // After a readback, make sure not to draw again until we've replaced the 348 // readback commit with a real one. 349 if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT || 350 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) 351 return false; 352 353 // Draw immediately for readbacks to unblock the main thread quickly. 354 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) { 355 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW); 356 return true; 357 } 358 359 // If we need to abort draws, we should do so ASAP since the draw could 360 // be blocking other important actions (like output surface initialization), 361 // from occuring. If we are waiting for the first draw, then perfom the 362 // aborted draw to keep things moving. If we are not waiting for the first 363 // draw however, we don't want to abort for no reason. 364 if (PendingDrawsShouldBeAborted()) 365 return active_tree_needs_first_draw_; 366 367 // After this line, we only want to swap once per frame. 368 if (HasSwappedThisFrame()) 369 return false; 370 371 // Except for the cases above, do not draw outside of the BeginImplFrame 372 // deadline. 373 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) 374 return false; 375 376 // Only handle forced redraws due to timeouts on the regular deadline. 377 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) { 378 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW); 379 return true; 380 } 381 382 return needs_redraw_; 383 } 384 385 bool SchedulerStateMachine::ShouldAcquireLayerTexturesForMainThread() const { 386 if (!main_thread_needs_layer_textures_) 387 return false; 388 if (texture_state_ == LAYER_TEXTURE_STATE_UNLOCKED) 389 return true; 390 DCHECK_EQ(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD); 391 return false; 392 } 393 394 bool SchedulerStateMachine::ShouldActivatePendingTree() const { 395 // There is nothing to activate. 396 if (!has_pending_tree_) 397 return false; 398 399 // We should not activate a second tree before drawing the first one. 400 // Even if we need to force activation of the pending tree, we should abort 401 // drawing the active tree first. 402 if (active_tree_needs_first_draw_) 403 return false; 404 405 // If we want to force activation, do so ASAP. 406 if (PendingActivationsShouldBeForced()) 407 return true; 408 409 // At this point, only activate if we are ready to activate. 410 return pending_tree_is_ready_for_activation_; 411 } 412 413 bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const { 414 if (!settings_.impl_side_painting) 415 return false; 416 if (HasUpdatedVisibleTilesThisFrame()) 417 return false; 418 419 // There's no reason to check for tiles if we don't have an output surface. 420 if (!HasInitializedOutputSurface()) 421 return false; 422 423 // We should not check for visible tiles until we've entered the deadline so 424 // we check as late as possible and give the tiles more time to initialize. 425 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) 426 return false; 427 428 // If the last swap drew with checkerboard or missing tiles, we should 429 // poll for any new visible tiles so we can be notified to draw again 430 // when there are. 431 if (swap_used_incomplete_tile_) 432 return true; 433 434 return false; 435 } 436 437 bool SchedulerStateMachine::ShouldSendBeginMainFrame() const { 438 if (!needs_commit_) 439 return false; 440 441 // Only send BeginMainFrame when there isn't another commit pending already. 442 if (commit_state_ != COMMIT_STATE_IDLE) 443 return false; 444 445 // We can't accept a commit if we have a pending tree. 446 if (has_pending_tree_) 447 return false; 448 449 // We want to handle readback commits immediately to unblock the main thread. 450 // Note: This BeginMainFrame will correspond to the replacement commit that 451 // comes after the readback commit itself, so we only send the BeginMainFrame 452 // if a commit isn't already pending behind the readback. 453 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME) 454 return !CommitPending(); 455 456 // We do not need commits if we are not visible, unless there's a 457 // request for a readback. 458 if (!visible_) 459 return false; 460 461 // We want to start the first commit after we get a new output surface ASAP. 462 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) 463 return true; 464 465 // With deadline scheduling enabled, we should not send BeginMainFrame while 466 // we are in BEGIN_IMPL_FRAME_STATE_IDLE, since we might have new user input 467 // coming in soon. 468 // However, if we are not expecting a BeginImplFrame to take us out of idle, 469 // we should not early out here to avoid blocking commits forever. 470 // This only works well when deadline scheduling is enabled because there is 471 // an interval over which to accept the commit and draw. Without deadline 472 // scheduling, delaying the commit could prevent us from having something 473 // to draw on the next BeginImplFrame. 474 // TODO(brianderson): Allow sending BeginMainFrame while idle when the main 475 // thread isn't consuming user input. 476 if (settings_.deadline_scheduling_enabled && 477 begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE && 478 BeginImplFrameNeeded()) 479 return false; 480 481 // We need a new commit for the forced redraw. This honors the 482 // single commit per interval because the result will be swapped to screen. 483 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) 484 return true; 485 486 // After this point, we only start a commit once per frame. 487 if (HasSentBeginMainFrameThisFrame()) 488 return false; 489 490 // We shouldn't normally accept commits if there isn't an OutputSurface. 491 if (!HasInitializedOutputSurface()) 492 return false; 493 494 if (skip_begin_main_frame_to_reduce_latency_) 495 return false; 496 497 return true; 498 } 499 500 bool SchedulerStateMachine::ShouldCommit() const { 501 return commit_state_ == COMMIT_STATE_READY_TO_COMMIT; 502 } 503 504 bool SchedulerStateMachine::IsCommitStateWaiting() const { 505 return commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS; 506 } 507 508 bool SchedulerStateMachine::ShouldManageTiles() const { 509 // ManageTiles only really needs to be called immediately after commit 510 // and then periodically after that. Limiting to once per frame prevents 511 // post-commit and post-draw ManageTiles on the same frame. 512 if (last_frame_number_manage_tiles_called_ == current_frame_number_) 513 return false; 514 515 // Limiting to once per-frame is not enough, since we only want to 516 // manage tiles _after_ draws. Polling for draw triggers and 517 // begin-frame are mutually exclusive, so we limit to these two cases. 518 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE && 519 !inside_poll_for_anticipated_draw_triggers_) 520 return false; 521 return needs_manage_tiles_; 522 } 523 524 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { 525 if (ShouldAcquireLayerTexturesForMainThread()) 526 return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD; 527 if (ShouldUpdateVisibleTiles()) 528 return ACTION_UPDATE_VISIBLE_TILES; 529 if (ShouldActivatePendingTree()) 530 return ACTION_ACTIVATE_PENDING_TREE; 531 if (ShouldCommit()) 532 return ACTION_COMMIT; 533 if (ShouldDraw()) { 534 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) 535 return ACTION_DRAW_AND_READBACK; 536 else if (PendingDrawsShouldBeAborted()) 537 return ACTION_DRAW_AND_SWAP_ABORT; 538 else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) 539 return ACTION_DRAW_AND_SWAP_FORCED; 540 else 541 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE; 542 } 543 if (ShouldManageTiles()) 544 return ACTION_MANAGE_TILES; 545 if (ShouldSendBeginMainFrame()) 546 return ACTION_SEND_BEGIN_MAIN_FRAME; 547 if (ShouldBeginOutputSurfaceCreation()) 548 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION; 549 return ACTION_NONE; 550 } 551 552 void SchedulerStateMachine::CheckInvariants() { 553 // We should never try to perform a draw for readback and forced draw due to 554 // timeout simultaneously. 555 DCHECK(!(forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW && 556 readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK)); 557 } 558 559 void SchedulerStateMachine::UpdateState(Action action) { 560 switch (action) { 561 case ACTION_NONE: 562 return; 563 564 case ACTION_UPDATE_VISIBLE_TILES: 565 last_frame_number_update_visible_tiles_was_called_ = 566 current_frame_number_; 567 return; 568 569 case ACTION_ACTIVATE_PENDING_TREE: 570 UpdateStateOnActivation(); 571 return; 572 573 case ACTION_SEND_BEGIN_MAIN_FRAME: 574 DCHECK(!has_pending_tree_); 575 DCHECK(visible_ || 576 readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME); 577 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS; 578 needs_commit_ = false; 579 if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME) 580 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT; 581 last_frame_number_begin_main_frame_sent_ = 582 current_frame_number_; 583 return; 584 585 case ACTION_COMMIT: { 586 bool commit_was_aborted = false; 587 UpdateStateOnCommit(commit_was_aborted); 588 return; 589 } 590 591 case ACTION_DRAW_AND_SWAP_FORCED: 592 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: { 593 bool did_swap = true; 594 UpdateStateOnDraw(did_swap); 595 return; 596 } 597 598 case ACTION_DRAW_AND_SWAP_ABORT: 599 case ACTION_DRAW_AND_READBACK: { 600 bool did_swap = false; 601 UpdateStateOnDraw(did_swap); 602 return; 603 } 604 605 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION: 606 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST); 607 output_surface_state_ = OUTPUT_SURFACE_CREATING; 608 609 // The following DCHECKs make sure we are in the proper quiescent state. 610 // The pipeline should be flushed entirely before we start output 611 // surface creation to avoid complicated corner cases. 612 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE); 613 DCHECK(!has_pending_tree_); 614 DCHECK(!active_tree_needs_first_draw_); 615 return; 616 617 case ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD: 618 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD; 619 main_thread_needs_layer_textures_ = false; 620 return; 621 622 case ACTION_MANAGE_TILES: 623 UpdateStateOnManageTiles(); 624 return; 625 } 626 } 627 628 void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) { 629 commit_count_++; 630 631 // If we are impl-side-painting but the commit was aborted, then we behave 632 // mostly as if we are not impl-side-painting since there is no pending tree. 633 has_pending_tree_ = settings_.impl_side_painting && !commit_was_aborted; 634 635 // Update state related to readbacks. 636 if (readback_state_ == READBACK_STATE_WAITING_FOR_COMMIT) { 637 // Update the state if this is the readback commit. 638 readback_state_ = has_pending_tree_ 639 ? READBACK_STATE_WAITING_FOR_ACTIVATION 640 : READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK; 641 } else if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT) { 642 // Update the state if this is the commit replacing the readback commit. 643 readback_state_ = has_pending_tree_ 644 ? READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION 645 : READBACK_STATE_IDLE; 646 } else { 647 DCHECK(readback_state_ == READBACK_STATE_IDLE); 648 } 649 650 // Readbacks can interrupt output surface initialization and forced draws, 651 // so we do not want to advance those states if we are in the middle of a 652 // readback. Note: It is possible for the readback's replacement commit to 653 // be the output surface's first commit and/or the forced redraw's commit. 654 if (readback_state_ == READBACK_STATE_IDLE || 655 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) { 656 // Update state related to forced draws. 657 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) { 658 forced_redraw_state_ = has_pending_tree_ 659 ? FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION 660 : FORCED_REDRAW_STATE_WAITING_FOR_DRAW; 661 } 662 663 // Update the output surface state. 664 DCHECK_NE(output_surface_state_, 665 OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION); 666 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) { 667 if (has_pending_tree_) { 668 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION; 669 } else { 670 output_surface_state_ = OUTPUT_SURFACE_ACTIVE; 671 needs_redraw_ = true; 672 } 673 } 674 } 675 676 // Update the commit state. We expect and wait for a draw if the commit 677 // was not aborted or if we are in a readback or forced draw. 678 if (!commit_was_aborted) { 679 DCHECK(commit_state_ == COMMIT_STATE_READY_TO_COMMIT); 680 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW; 681 } else if (readback_state_ != READBACK_STATE_IDLE || 682 forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE) { 683 commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW; 684 } else { 685 commit_state_ = COMMIT_STATE_IDLE; 686 } 687 688 // Update state if we have a new active tree to draw, or if the active tree 689 // was unchanged but we need to do a readback or forced draw. 690 if (!has_pending_tree_ && 691 (!commit_was_aborted || 692 readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK || 693 forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)) { 694 needs_redraw_ = true; 695 active_tree_needs_first_draw_ = true; 696 } 697 698 // This post-commit work is common to both completed and aborted commits. 699 pending_tree_is_ready_for_activation_ = false; 700 701 if (draw_if_possible_failed_) 702 last_frame_number_swap_performed_ = -1; 703 704 // If we are planing to draw with the new commit, lock the layer textures for 705 // use on the impl thread. Otherwise, leave them unlocked. 706 if (has_pending_tree_ || needs_redraw_) 707 texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD; 708 else 709 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED; 710 } 711 712 void SchedulerStateMachine::UpdateStateOnActivation() { 713 // Update output surface state. 714 if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION) 715 output_surface_state_ = OUTPUT_SURFACE_ACTIVE; 716 717 // Update readback state 718 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION) 719 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_DRAW; 720 721 // Update forced redraw state 722 if (readback_state_ == READBACK_STATE_WAITING_FOR_ACTIVATION) 723 readback_state_ = READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK; 724 else if (readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) 725 readback_state_ = READBACK_STATE_IDLE; 726 727 has_pending_tree_ = false; 728 pending_tree_is_ready_for_activation_ = false; 729 active_tree_needs_first_draw_ = true; 730 needs_redraw_ = true; 731 } 732 733 void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) { 734 DCHECK(readback_state_ != READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT && 735 readback_state_ != READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION) 736 << *AsValue(); 737 738 if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) { 739 // The draw correspons to a readback commit. 740 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW); 741 // We are blocking commits from the main thread until after this draw, so 742 // we should not have a pending tree. 743 DCHECK(!has_pending_tree_); 744 // We transition to COMMIT_STATE_FRAME_IN_PROGRESS because there is a 745 // pending BeginMainFrame behind the readback request. 746 commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS; 747 readback_state_ = READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT; 748 } else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) { 749 DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW); 750 commit_state_ = COMMIT_STATE_IDLE; 751 forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE; 752 } else if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW && 753 !has_pending_tree_) { 754 commit_state_ = COMMIT_STATE_IDLE; 755 } 756 757 if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD) 758 texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED; 759 760 needs_redraw_ = false; 761 draw_if_possible_failed_ = false; 762 active_tree_needs_first_draw_ = false; 763 764 if (did_swap) 765 last_frame_number_swap_performed_ = current_frame_number_; 766 } 767 768 void SchedulerStateMachine::UpdateStateOnManageTiles() { 769 needs_manage_tiles_ = false; 770 } 771 772 void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() { 773 DCHECK(!main_thread_needs_layer_textures_); 774 DCHECK_NE(texture_state_, LAYER_TEXTURE_STATE_ACQUIRED_BY_MAIN_THREAD); 775 main_thread_needs_layer_textures_ = true; 776 } 777 778 void SchedulerStateMachine::SetSkipBeginMainFrameToReduceLatency(bool skip) { 779 skip_begin_main_frame_to_reduce_latency_ = skip; 780 } 781 782 bool SchedulerStateMachine::BeginImplFrameNeeded() const { 783 // Proactive BeginImplFrames are bad for the synchronous compositor because we 784 // have to draw when we get the BeginImplFrame and could end up drawing many 785 // duplicate frames if our new frame isn't ready in time. 786 // To poll for state with the synchronous compositor without having to draw, 787 // we rely on ShouldPollForAnticipatedDrawTriggers instead. 788 if (!SupportsProactiveBeginImplFrame()) 789 return BeginImplFrameNeededToDraw(); 790 791 return BeginImplFrameNeededToDraw() || 792 ProactiveBeginImplFrameWanted(); 793 } 794 795 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const { 796 // ShouldPollForAnticipatedDrawTriggers is what we use in place of 797 // ProactiveBeginImplFrameWanted when we are using the synchronous 798 // compositor. 799 if (!SupportsProactiveBeginImplFrame()) { 800 return !BeginImplFrameNeededToDraw() && 801 ProactiveBeginImplFrameWanted(); 802 } 803 804 // Non synchronous compositors should rely on 805 // ProactiveBeginImplFrameWanted to poll for state instead. 806 return false; 807 } 808 809 bool SchedulerStateMachine::SupportsProactiveBeginImplFrame() const { 810 // Both the synchronous compositor and disabled vsync settings 811 // make it undesirable to proactively request BeginImplFrames. 812 // If this is true, the scheduler should poll. 813 return !settings_.using_synchronous_renderer_compositor && 814 settings_.throttle_frame_production; 815 } 816 817 // These are the cases where we definitely (or almost definitely) have a 818 // new frame to draw and can draw. 819 bool SchedulerStateMachine::BeginImplFrameNeededToDraw() const { 820 // The output surface is the provider of BeginImplFrames, so we are not going 821 // to get them even if we ask for them. 822 if (!HasInitializedOutputSurface()) 823 return false; 824 825 // If we can't draw, don't tick until we are notified that we can draw again. 826 if (!can_draw_) 827 return false; 828 829 // The forced draw respects our normal draw scheduling, so we need to 830 // request a BeginImplFrame for it. 831 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) 832 return true; 833 834 // There's no need to produce frames if we are not visible. 835 if (!visible_) 836 return false; 837 838 // We need to draw a more complete frame than we did the last BeginImplFrame, 839 // so request another BeginImplFrame in anticipation that we will have 840 // additional visible tiles. 841 if (swap_used_incomplete_tile_) 842 return true; 843 844 return needs_redraw_; 845 } 846 847 // These are cases where we are very likely to draw soon, but might not 848 // actually have a new frame to draw when we receive the next BeginImplFrame. 849 // Proactively requesting the BeginImplFrame helps hide the round trip latency 850 // of the SetNeedsBeginImplFrame request that has to go to the Browser. 851 bool SchedulerStateMachine::ProactiveBeginImplFrameWanted() const { 852 // The output surface is the provider of BeginImplFrames, 853 // so we are not going to get them even if we ask for them. 854 if (!HasInitializedOutputSurface()) 855 return false; 856 857 // Do not be proactive when invisible. 858 if (!visible_) 859 return false; 860 861 // We should proactively request a BeginImplFrame if a commit is pending 862 // because we will want to draw if the commit completes quickly. 863 if (needs_commit_ || commit_state_ != COMMIT_STATE_IDLE) 864 return true; 865 866 // If the pending tree activates quickly, we'll want a BeginImplFrame soon 867 // to draw the new active tree. 868 if (has_pending_tree_) 869 return true; 870 871 // Changing priorities may allow us to activate (given the new priorities), 872 // which may result in a new frame. 873 if (needs_manage_tiles_) 874 return true; 875 876 // If we just swapped, it's likely that we are going to produce another 877 // frame soon. This helps avoid negative glitches in our 878 // SetNeedsBeginImplFrame requests, which may propagate to the BeginImplFrame 879 // provider and get sampled at an inopportune time, delaying the next 880 // BeginImplFrame. 881 if (last_frame_number_swap_performed_ == current_frame_number_) 882 return true; 883 884 return false; 885 } 886 887 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) { 888 current_frame_number_++; 889 last_begin_impl_frame_args_ = args; 890 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) << *AsValue(); 891 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING; 892 } 893 894 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() { 895 DCHECK_EQ(begin_impl_frame_state_, 896 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) 897 << *AsValue(); 898 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; 899 } 900 901 void SchedulerStateMachine::OnBeginImplFrameDeadline() { 902 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) 903 << *AsValue(); 904 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; 905 } 906 907 void SchedulerStateMachine::OnBeginImplFrameIdle() { 908 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) 909 << *AsValue(); 910 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE; 911 } 912 913 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineEarly() const { 914 // TODO(brianderson): This should take into account multiple commit sources. 915 916 // If we are in the middle of the readback, we won't swap, so there is 917 // no reason to trigger the deadline early. 918 if (readback_state_ != READBACK_STATE_IDLE) 919 return false; 920 921 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) 922 return false; 923 924 if (active_tree_needs_first_draw_) 925 return true; 926 927 if (!needs_redraw_) 928 return false; 929 930 // This is used to prioritize impl-thread draws when the main thread isn't 931 // producing anything, e.g., after an aborted commit. We also check that we 932 // don't have a pending tree -- otherwise we should give it a chance to 933 // activate. 934 // TODO(skyostil): Revisit this when we have more accurate deadline estimates. 935 if (commit_state_ == COMMIT_STATE_IDLE && !has_pending_tree_) 936 return true; 937 938 // Prioritize impl-thread draws in smoothness mode. 939 if (smoothness_takes_priority_) 940 return true; 941 942 return false; 943 } 944 945 bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const { 946 // If we just sent a BeginMainFrame and haven't hit the deadline yet, the main 947 // thread is in a low latency mode. 948 if (last_frame_number_begin_main_frame_sent_ == current_frame_number_ && 949 (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING || 950 begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)) 951 return false; 952 953 // If there's a commit in progress it must either be from the previous frame 954 // or it started after the impl thread's deadline. In either case the main 955 // thread is in high latency mode. 956 if (commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS || 957 commit_state_ == COMMIT_STATE_READY_TO_COMMIT) 958 return true; 959 960 // Similarly, if there's a pending tree the main thread is in high latency 961 // mode, because either 962 // it's from the previous frame 963 // or 964 // we're currently drawing the active tree and the pending tree will thus 965 // only be drawn in the next frame. 966 if (has_pending_tree_) 967 return true; 968 969 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) { 970 // Even if there's a new active tree to draw at the deadline or we've just 971 // drawn it, it may have been triggered by a previous BeginImplFrame, in 972 // which case the main thread is in a high latency mode. 973 return (active_tree_needs_first_draw_ || 974 last_frame_number_swap_performed_ == current_frame_number_) && 975 last_frame_number_begin_main_frame_sent_ != current_frame_number_; 976 } 977 978 // If the active tree needs its first draw in any other state, we know the 979 // main thread is in a high latency mode. 980 return active_tree_needs_first_draw_; 981 } 982 983 void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() { 984 current_frame_number_++; 985 inside_poll_for_anticipated_draw_triggers_ = true; 986 } 987 988 void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() { 989 inside_poll_for_anticipated_draw_triggers_ = false; 990 } 991 992 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; } 993 994 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; } 995 996 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; } 997 998 void SchedulerStateMachine::SetNeedsManageTiles() { 999 if (!needs_manage_tiles_) { 1000 TRACE_EVENT0("cc", 1001 "SchedulerStateMachine::SetNeedsManageTiles"); 1002 needs_manage_tiles_ = true; 1003 } 1004 } 1005 1006 void SchedulerStateMachine::SetSwapUsedIncompleteTile( 1007 bool used_incomplete_tile) { 1008 swap_used_incomplete_tile_ = used_incomplete_tile; 1009 } 1010 1011 void SchedulerStateMachine::SetSmoothnessTakesPriority( 1012 bool smoothness_takes_priority) { 1013 smoothness_takes_priority_ = smoothness_takes_priority; 1014 } 1015 1016 void SchedulerStateMachine::DidDrawIfPossibleCompleted(bool success) { 1017 draw_if_possible_failed_ = !success; 1018 if (draw_if_possible_failed_) { 1019 needs_redraw_ = true; 1020 1021 // If we're already in the middle of a redraw, we don't need to 1022 // restart it. 1023 if (forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE) 1024 return; 1025 1026 needs_commit_ = true; 1027 consecutive_failed_draws_++; 1028 if (settings_.timeout_and_draw_when_animation_checkerboards && 1029 consecutive_failed_draws_ >= 1030 settings_.maximum_number_of_failed_draws_before_draw_is_forced_) { 1031 consecutive_failed_draws_ = 0; 1032 // We need to force a draw, but it doesn't make sense to do this until 1033 // we've committed and have new textures. 1034 forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT; 1035 } 1036 } else { 1037 consecutive_failed_draws_ = 0; 1038 forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE; 1039 } 1040 } 1041 1042 void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; } 1043 1044 void SchedulerStateMachine::SetNeedsForcedCommitForReadback() { 1045 // If this is called in READBACK_STATE_IDLE, this is a "first" readback 1046 // request. 1047 // If this is called in READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT, this 1048 // is a back-to-back readback request that started before the replacement 1049 // commit had a chance to land. 1050 DCHECK(readback_state_ == READBACK_STATE_IDLE || 1051 readback_state_ == READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT); 1052 1053 // If there is already a commit in progress when we get the readback request 1054 // (we are in COMMIT_STATE_FRAME_IN_PROGRESS), then we don't need to send a 1055 // BeginMainFrame for the replacement commit, since there's already a 1056 // BeginMainFrame behind the readback request. In that case, we can skip 1057 // READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME and go directly to 1058 // READBACK_STATE_WAITING_FOR_COMMIT 1059 if (commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS) 1060 readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT; 1061 else 1062 readback_state_ = READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME; 1063 } 1064 1065 void SchedulerStateMachine::FinishCommit() { 1066 DCHECK(commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS) << *AsValue(); 1067 commit_state_ = COMMIT_STATE_READY_TO_COMMIT; 1068 } 1069 1070 void SchedulerStateMachine::BeginMainFrameAborted(bool did_handle) { 1071 DCHECK_EQ(commit_state_, COMMIT_STATE_FRAME_IN_PROGRESS); 1072 if (did_handle) { 1073 bool commit_was_aborted = true; 1074 UpdateStateOnCommit(commit_was_aborted); 1075 } else { 1076 DCHECK_NE(readback_state_, READBACK_STATE_WAITING_FOR_COMMIT); 1077 commit_state_ = COMMIT_STATE_IDLE; 1078 SetNeedsCommit(); 1079 } 1080 } 1081 1082 void SchedulerStateMachine::DidManageTiles() { 1083 needs_manage_tiles_ = false; 1084 last_frame_number_manage_tiles_called_ = current_frame_number_; 1085 } 1086 1087 void SchedulerStateMachine::DidLoseOutputSurface() { 1088 if (output_surface_state_ == OUTPUT_SURFACE_LOST || 1089 output_surface_state_ == OUTPUT_SURFACE_CREATING) 1090 return; 1091 output_surface_state_ = OUTPUT_SURFACE_LOST; 1092 needs_redraw_ = false; 1093 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE; 1094 } 1095 1096 void SchedulerStateMachine::NotifyReadyToActivate() { 1097 if (has_pending_tree_) 1098 pending_tree_is_ready_for_activation_ = true; 1099 } 1100 1101 void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() { 1102 DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING); 1103 output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT; 1104 1105 if (did_create_and_initialize_first_output_surface_) { 1106 // TODO(boliu): See if we can remove this when impl-side painting is always 1107 // on. Does anything on the main thread need to update after recreate? 1108 needs_commit_ = true; 1109 } 1110 did_create_and_initialize_first_output_surface_ = true; 1111 } 1112 1113 bool SchedulerStateMachine::HasInitializedOutputSurface() const { 1114 switch (output_surface_state_) { 1115 case OUTPUT_SURFACE_LOST: 1116 case OUTPUT_SURFACE_CREATING: 1117 return false; 1118 1119 case OUTPUT_SURFACE_ACTIVE: 1120 case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: 1121 case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: 1122 return true; 1123 } 1124 NOTREACHED(); 1125 return false; 1126 } 1127 1128 } // namespace cc 1129