| OLD | NEW |
| 1 // Copyright 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/scheduler/scheduler_state_machine.h" | 5 #include "cc/scheduler/scheduler_state_machine.h" |
| 6 | 6 |
| 7 #include "base/format_macros.h" | 7 #include "base/format_macros.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
| 10 #include "base/trace_event/trace_event.h" | 10 #include "base/trace_event/trace_event.h" |
| 11 #include "base/trace_event/trace_event_argument.h" | 11 #include "base/trace_event/trace_event_argument.h" |
| 12 #include "base/values.h" | 12 #include "base/values.h" |
| 13 #include "ui/gfx/frame_time.h" | 13 #include "ui/gfx/frame_time.h" |
| 14 | 14 |
| 15 namespace cc { | 15 namespace cc { |
| 16 | 16 |
| 17 SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) | 17 SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) |
| 18 : settings_(settings), | 18 : settings_(settings), |
| 19 output_surface_state_(OUTPUT_SURFACE_LOST), | 19 output_surface_state_(OUTPUT_SURFACE_LOST), |
| 20 begin_impl_frame_state_(BEGIN_IMPL_FRAME_STATE_IDLE), | 20 begin_impl_frame_state_(BEGIN_IMPL_FRAME_STATE_IDLE), |
| 21 commit_state_(COMMIT_STATE_IDLE), | 21 commit_state_(COMMIT_STATE_IDLE), |
| 22 forced_redraw_state_(FORCED_REDRAW_STATE_IDLE), | 22 forced_redraw_state_(FORCED_REDRAW_STATE_IDLE), |
| 23 commit_count_(0), | 23 commit_count_(0), |
| 24 current_frame_number_(0), | 24 current_frame_number_(0), |
| 25 last_frame_number_animate_performed_(-1), | 25 last_frame_number_animate_performed_(-1), |
| 26 last_frame_number_swap_performed_(-1), | 26 last_frame_number_swap_performed_(-1), |
| 27 last_frame_number_swap_requested_(-1), | 27 last_frame_number_swap_requested_(-1), |
| 28 last_frame_number_begin_main_frame_sent_(-1), | 28 last_frame_number_begin_main_frame_sent_(-1), |
| 29 last_frame_number_invalidate_output_surface_performed_(-1), |
| 29 prepare_tiles_funnel_(0), | 30 prepare_tiles_funnel_(0), |
| 30 consecutive_checkerboard_animations_(0), | 31 consecutive_checkerboard_animations_(0), |
| 31 max_pending_swaps_(1), | 32 max_pending_swaps_(1), |
| 32 pending_swaps_(0), | 33 pending_swaps_(0), |
| 33 needs_redraw_(false), | 34 needs_redraw_(false), |
| 34 needs_animate_(false), | 35 needs_animate_(false), |
| 35 needs_prepare_tiles_(false), | 36 needs_prepare_tiles_(false), |
| 36 needs_commit_(false), | 37 needs_commit_(false), |
| 37 inside_poll_for_anticipated_draw_triggers_(false), | |
| 38 visible_(false), | 38 visible_(false), |
| 39 can_start_(false), | 39 can_start_(false), |
| 40 can_draw_(false), | 40 can_draw_(false), |
| 41 has_pending_tree_(false), | 41 has_pending_tree_(false), |
| 42 pending_tree_is_ready_for_activation_(false), | 42 pending_tree_is_ready_for_activation_(false), |
| 43 active_tree_needs_first_draw_(false), | 43 active_tree_needs_first_draw_(false), |
| 44 did_commit_after_animating_(false), | 44 did_commit_after_animating_(false), |
| 45 did_create_and_initialize_first_output_surface_(false), | 45 did_create_and_initialize_first_output_surface_(false), |
| 46 impl_latency_takes_priority_(false), | 46 impl_latency_takes_priority_(false), |
| 47 skip_next_begin_main_frame_to_reduce_latency_(false), | 47 skip_next_begin_main_frame_to_reduce_latency_(false), |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 return "BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING"; | 79 return "BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING"; |
| 80 case BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME: | 80 case BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME: |
| 81 return "BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME"; | 81 return "BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME"; |
| 82 case BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE: | 82 case BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE: |
| 83 return "BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE"; | 83 return "BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE"; |
| 84 } | 84 } |
| 85 NOTREACHED(); | 85 NOTREACHED(); |
| 86 return "???"; | 86 return "???"; |
| 87 } | 87 } |
| 88 | 88 |
| 89 const char* SchedulerStateMachine::BeginImplFrameDeadlineModeToString( |
| 90 BeginImplFrameDeadlineMode mode) { |
| 91 switch (mode) { |
| 92 case BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_SYNCHRONOUS: |
| 93 return "BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_SYNCHRONOUS"; |
| 94 case BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_ASYNCHRONOUS: |
| 95 return "BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_ASYNCHRONOUS"; |
| 96 case BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR: |
| 97 return "BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR"; |
| 98 case BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE: |
| 99 return "BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE"; |
| 100 } |
| 101 NOTREACHED(); |
| 102 return "???"; |
| 103 } |
| 104 |
| 89 const char* SchedulerStateMachine::CommitStateToString(CommitState state) { | 105 const char* SchedulerStateMachine::CommitStateToString(CommitState state) { |
| 90 switch (state) { | 106 switch (state) { |
| 91 case COMMIT_STATE_IDLE: | 107 case COMMIT_STATE_IDLE: |
| 92 return "COMMIT_STATE_IDLE"; | 108 return "COMMIT_STATE_IDLE"; |
| 93 case COMMIT_STATE_BEGIN_MAIN_FRAME_SENT: | 109 case COMMIT_STATE_BEGIN_MAIN_FRAME_SENT: |
| 94 return "COMMIT_STATE_BEGIN_MAIN_FRAME_SENT"; | 110 return "COMMIT_STATE_BEGIN_MAIN_FRAME_SENT"; |
| 95 case COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED: | 111 case COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED: |
| 96 return "COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED"; | 112 return "COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED"; |
| 97 case COMMIT_STATE_READY_TO_COMMIT: | 113 case COMMIT_STATE_READY_TO_COMMIT: |
| 98 return "COMMIT_STATE_READY_TO_COMMIT"; | 114 return "COMMIT_STATE_READY_TO_COMMIT"; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: | 152 case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: |
| 137 return "ACTION_DRAW_AND_SWAP_IF_POSSIBLE"; | 153 return "ACTION_DRAW_AND_SWAP_IF_POSSIBLE"; |
| 138 case ACTION_DRAW_AND_SWAP_FORCED: | 154 case ACTION_DRAW_AND_SWAP_FORCED: |
| 139 return "ACTION_DRAW_AND_SWAP_FORCED"; | 155 return "ACTION_DRAW_AND_SWAP_FORCED"; |
| 140 case ACTION_DRAW_AND_SWAP_ABORT: | 156 case ACTION_DRAW_AND_SWAP_ABORT: |
| 141 return "ACTION_DRAW_AND_SWAP_ABORT"; | 157 return "ACTION_DRAW_AND_SWAP_ABORT"; |
| 142 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION: | 158 case ACTION_BEGIN_OUTPUT_SURFACE_CREATION: |
| 143 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION"; | 159 return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION"; |
| 144 case ACTION_PREPARE_TILES: | 160 case ACTION_PREPARE_TILES: |
| 145 return "ACTION_PREPARE_TILES"; | 161 return "ACTION_PREPARE_TILES"; |
| 162 case ACTION_INVALIDATE_OUTPUT_SURFACE: |
| 163 return "ACTION_INVALIDATE_OUTPUT_SURFACE"; |
| 146 } | 164 } |
| 147 NOTREACHED(); | 165 NOTREACHED(); |
| 148 return "???"; | 166 return "???"; |
| 149 } | 167 } |
| 150 | 168 |
| 151 scoped_refptr<base::trace_event::ConvertableToTraceFormat> | 169 scoped_refptr<base::trace_event::ConvertableToTraceFormat> |
| 152 SchedulerStateMachine::AsValue() const { | 170 SchedulerStateMachine::AsValue() const { |
| 153 scoped_refptr<base::trace_event::TracedValue> state = | 171 scoped_refptr<base::trace_event::TracedValue> state = |
| 154 new base::trace_event::TracedValue(); | 172 new base::trace_event::TracedValue(); |
| 155 AsValueInto(state.get(), gfx::FrameTime::Now()); | 173 AsValueInto(state.get(), gfx::FrameTime::Now()); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency", | 254 state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency", |
| 237 skip_next_begin_main_frame_to_reduce_latency_); | 255 skip_next_begin_main_frame_to_reduce_latency_); |
| 238 state->SetBoolean("continuous_painting", continuous_painting_); | 256 state->SetBoolean("continuous_painting", continuous_painting_); |
| 239 state->SetBoolean("impl_latency_takes_priority_on_battery", | 257 state->SetBoolean("impl_latency_takes_priority_on_battery", |
| 240 impl_latency_takes_priority_on_battery_); | 258 impl_latency_takes_priority_on_battery_); |
| 241 state->SetBoolean("children_need_begin_frames", children_need_begin_frames_); | 259 state->SetBoolean("children_need_begin_frames", children_need_begin_frames_); |
| 242 state->SetBoolean("defer_commits", defer_commits_); | 260 state->SetBoolean("defer_commits", defer_commits_); |
| 243 state->EndDictionary(); | 261 state->EndDictionary(); |
| 244 } | 262 } |
| 245 | 263 |
| 246 void SchedulerStateMachine::AdvanceCurrentFrameNumber() { | 264 void SchedulerStateMachine::AdvanceFrame() { |
| 247 current_frame_number_++; | 265 current_frame_number_++; |
| 248 | 266 |
| 249 // "Drain" the PrepareTiles funnel. | 267 // "Drain" the PrepareTiles funnel. |
| 250 if (prepare_tiles_funnel_ > 0) | 268 if (prepare_tiles_funnel_ > 0) |
| 251 prepare_tiles_funnel_--; | 269 prepare_tiles_funnel_--; |
| 252 | 270 |
| 253 skip_begin_main_frame_to_reduce_latency_ = | 271 skip_begin_main_frame_to_reduce_latency_ = |
| 254 skip_next_begin_main_frame_to_reduce_latency_; | 272 skip_next_begin_main_frame_to_reduce_latency_; |
| 255 skip_next_begin_main_frame_to_reduce_latency_ = false; | 273 skip_next_begin_main_frame_to_reduce_latency_ = false; |
| 256 } | 274 } |
| 257 | 275 |
| 258 bool SchedulerStateMachine::HasAnimatedThisFrame() const { | 276 bool SchedulerStateMachine::HasAnimatedThisFrame() const { |
| 259 return last_frame_number_animate_performed_ == current_frame_number_; | 277 return last_frame_number_animate_performed_ == current_frame_number_; |
| 260 } | 278 } |
| 261 | 279 |
| 262 bool SchedulerStateMachine::HasSentBeginMainFrameThisFrame() const { | 280 bool SchedulerStateMachine::HasSentBeginMainFrameThisFrame() const { |
| 263 return current_frame_number_ == | 281 return current_frame_number_ == |
| 264 last_frame_number_begin_main_frame_sent_; | 282 last_frame_number_begin_main_frame_sent_; |
| 265 } | 283 } |
| 266 | 284 |
| 267 bool SchedulerStateMachine::HasSwappedThisFrame() const { | 285 bool SchedulerStateMachine::HasSwappedThisFrame() const { |
| 268 return current_frame_number_ == last_frame_number_swap_performed_; | 286 return current_frame_number_ == last_frame_number_swap_performed_; |
| 269 } | 287 } |
| 270 | 288 |
| 271 bool SchedulerStateMachine::HasRequestedSwapThisFrame() const { | 289 bool SchedulerStateMachine::HasRequestedSwapThisFrame() const { |
| 272 return current_frame_number_ == last_frame_number_swap_requested_; | 290 return current_frame_number_ == last_frame_number_swap_requested_; |
| 273 } | 291 } |
| 274 | 292 |
| 293 bool SchedulerStateMachine::HasInvalidatedOutputSurfaceThisFrame() const { |
| 294 return current_frame_number_ == |
| 295 last_frame_number_invalidate_output_surface_performed_; |
| 296 } |
| 297 |
| 275 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const { | 298 bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const { |
| 276 // These are all the cases where we normally cannot or do not want to draw | 299 // These are all the cases where we normally cannot or do not want to draw |
| 277 // but, if needs_redraw_ is true and we do not draw to make forward progress, | 300 // but, if needs_redraw_ is true and we do not draw to make forward progress, |
| 278 // we might deadlock with the main thread. | 301 // we might deadlock with the main thread. |
| 279 // This should be a superset of PendingActivationsShouldBeForced() since | 302 // This should be a superset of PendingActivationsShouldBeForced() since |
| 280 // activation of the pending tree is blocked by drawing of the active tree and | 303 // activation of the pending tree is blocked by drawing of the active tree and |
| 281 // the main thread might be blocked on activation of the most recent commit. | 304 // the main thread might be blocked on activation of the most recent commit. |
| 282 if (PendingActivationsShouldBeForced()) | 305 if (PendingActivationsShouldBeForced()) |
| 283 return true; | 306 return true; |
| 284 | 307 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 // are initializing the output surface. | 352 // are initializing the output surface. |
| 330 if (active_tree_needs_first_draw_ || has_pending_tree_) | 353 if (active_tree_needs_first_draw_ || has_pending_tree_) |
| 331 return false; | 354 return false; |
| 332 | 355 |
| 333 // We need to create the output surface if we don't have one and we haven't | 356 // We need to create the output surface if we don't have one and we haven't |
| 334 // started creating one yet. | 357 // started creating one yet. |
| 335 return output_surface_state_ == OUTPUT_SURFACE_LOST; | 358 return output_surface_state_ == OUTPUT_SURFACE_LOST; |
| 336 } | 359 } |
| 337 | 360 |
| 338 bool SchedulerStateMachine::ShouldDraw() const { | 361 bool SchedulerStateMachine::ShouldDraw() const { |
| 362 // In the synchronous compositor mode, draw only when asked to. |
| 363 if (settings_.using_synchronous_renderer_compositor && |
| 364 begin_impl_frame_args_.type != BeginFrameArgs::SYNCHRONOUS_DRAW) |
| 365 return false; |
| 366 |
| 339 // If we need to abort draws, we should do so ASAP since the draw could | 367 // If we need to abort draws, we should do so ASAP since the draw could |
| 340 // be blocking other important actions (like output surface initialization), | 368 // be blocking other important actions (like output surface initialization), |
| 341 // from occuring. If we are waiting for the first draw, then perfom the | 369 // from occuring. If we are waiting for the first draw, then perfom the |
| 342 // aborted draw to keep things moving. If we are not waiting for the first | 370 // aborted draw to keep things moving. If we are not waiting for the first |
| 343 // draw however, we don't want to abort for no reason. | 371 // draw however, we don't want to abort for no reason. |
| 344 if (PendingDrawsShouldBeAborted()) | 372 if (PendingDrawsShouldBeAborted()) |
| 345 return active_tree_needs_first_draw_; | 373 return active_tree_needs_first_draw_; |
| 346 | 374 |
| 347 // Don't draw if we are waiting on the first commit after a surface. | 375 // Don't draw if we are waiting on the first commit after a surface. |
| 348 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE) | 376 if (output_surface_state_ != OUTPUT_SURFACE_ACTIVE) |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 } | 520 } |
| 493 | 521 |
| 494 bool SchedulerStateMachine::ShouldPrepareTiles() const { | 522 bool SchedulerStateMachine::ShouldPrepareTiles() const { |
| 495 // PrepareTiles only really needs to be called immediately after commit | 523 // PrepareTiles only really needs to be called immediately after commit |
| 496 // and then periodically after that. Use a funnel to make sure we average | 524 // and then periodically after that. Use a funnel to make sure we average |
| 497 // one PrepareTiles per BeginImplFrame in the long run. | 525 // one PrepareTiles per BeginImplFrame in the long run. |
| 498 if (prepare_tiles_funnel_ > 0) | 526 if (prepare_tiles_funnel_ > 0) |
| 499 return false; | 527 return false; |
| 500 | 528 |
| 501 // Limiting to once per-frame is not enough, since we only want to | 529 // Limiting to once per-frame is not enough, since we only want to |
| 502 // prepare tiles _after_ draws. Polling for draw triggers and | 530 // prepare tiles _after_ draws. |
| 503 // begin-frame are mutually exclusive, so we limit to these two cases. | 531 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) |
| 504 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE && | |
| 505 !inside_poll_for_anticipated_draw_triggers_) | |
| 506 return false; | 532 return false; |
| 533 |
| 507 return needs_prepare_tiles_; | 534 return needs_prepare_tiles_; |
| 508 } | 535 } |
| 509 | 536 |
| 537 bool SchedulerStateMachine::ShouldInvalidateOutputSurface() const { |
| 538 // Only the synchronous compositor requires invalidations. |
| 539 if (!settings_.using_synchronous_renderer_compositor) |
| 540 return false; |
| 541 |
| 542 // Invalidations are only performed inside a BeginFrame deadline. |
| 543 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) |
| 544 return false; |
| 545 |
| 546 // Invalidate the output surface only once per frame. |
| 547 if (HasInvalidatedOutputSurfaceThisFrame()) |
| 548 return false; |
| 549 |
| 550 return needs_redraw_; |
| 551 } |
| 552 |
| 510 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { | 553 SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { |
| 511 if (ShouldActivatePendingTree()) | 554 if (ShouldActivatePendingTree()) |
| 512 return ACTION_ACTIVATE_SYNC_TREE; | 555 return ACTION_ACTIVATE_SYNC_TREE; |
| 513 if (ShouldCommit()) | 556 if (ShouldCommit()) |
| 514 return ACTION_COMMIT; | 557 return ACTION_COMMIT; |
| 515 if (ShouldAnimate()) | 558 if (ShouldAnimate()) |
| 516 return ACTION_ANIMATE; | 559 return ACTION_ANIMATE; |
| 517 if (ShouldDraw()) { | 560 if (ShouldDraw()) { |
| 518 if (PendingDrawsShouldBeAborted()) | 561 if (PendingDrawsShouldBeAborted()) |
| 519 return ACTION_DRAW_AND_SWAP_ABORT; | 562 return ACTION_DRAW_AND_SWAP_ABORT; |
| 520 else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) | 563 else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) |
| 521 return ACTION_DRAW_AND_SWAP_FORCED; | 564 return ACTION_DRAW_AND_SWAP_FORCED; |
| 522 else | 565 else |
| 523 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE; | 566 return ACTION_DRAW_AND_SWAP_IF_POSSIBLE; |
| 524 } | 567 } |
| 525 if (ShouldPrepareTiles()) | 568 if (ShouldPrepareTiles()) |
| 526 return ACTION_PREPARE_TILES; | 569 return ACTION_PREPARE_TILES; |
| 527 if (ShouldSendBeginMainFrame()) | 570 if (ShouldSendBeginMainFrame()) |
| 528 return ACTION_SEND_BEGIN_MAIN_FRAME; | 571 return ACTION_SEND_BEGIN_MAIN_FRAME; |
| 572 if (ShouldInvalidateOutputSurface()) |
| 573 return ACTION_INVALIDATE_OUTPUT_SURFACE; |
| 529 if (ShouldBeginOutputSurfaceCreation()) | 574 if (ShouldBeginOutputSurfaceCreation()) |
| 530 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION; | 575 return ACTION_BEGIN_OUTPUT_SURFACE_CREATION; |
| 531 return ACTION_NONE; | 576 return ACTION_NONE; |
| 532 } | 577 } |
| 533 | 578 |
| 534 void SchedulerStateMachine::UpdateState(Action action) { | 579 void SchedulerStateMachine::UpdateState(Action action) { |
| 535 switch (action) { | 580 switch (action) { |
| 536 case ACTION_NONE: | 581 case ACTION_NONE: |
| 537 return; | 582 return; |
| 538 | 583 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 // The pipeline should be flushed entirely before we start output | 631 // The pipeline should be flushed entirely before we start output |
| 587 // surface creation to avoid complicated corner cases. | 632 // surface creation to avoid complicated corner cases. |
| 588 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE); | 633 DCHECK_EQ(commit_state_, COMMIT_STATE_IDLE); |
| 589 DCHECK(!has_pending_tree_); | 634 DCHECK(!has_pending_tree_); |
| 590 DCHECK(!active_tree_needs_first_draw_); | 635 DCHECK(!active_tree_needs_first_draw_); |
| 591 return; | 636 return; |
| 592 | 637 |
| 593 case ACTION_PREPARE_TILES: | 638 case ACTION_PREPARE_TILES: |
| 594 UpdateStateOnPrepareTiles(); | 639 UpdateStateOnPrepareTiles(); |
| 595 return; | 640 return; |
| 641 |
| 642 case ACTION_INVALIDATE_OUTPUT_SURFACE: |
| 643 last_frame_number_invalidate_output_surface_performed_ = |
| 644 current_frame_number_; |
| 645 return; |
| 596 } | 646 } |
| 597 } | 647 } |
| 598 | 648 |
| 599 void SchedulerStateMachine::UpdateStateOnCommit(bool commit_has_no_updates) { | 649 void SchedulerStateMachine::UpdateStateOnCommit(bool commit_has_no_updates) { |
| 600 commit_count_++; | 650 commit_count_++; |
| 601 | 651 |
| 602 if (!commit_has_no_updates && HasAnimatedThisFrame()) | 652 if (!commit_has_no_updates && HasAnimatedThisFrame()) |
| 603 did_commit_after_animating_ = true; | 653 did_commit_after_animating_ = true; |
| 604 | 654 |
| 605 if (commit_has_no_updates || settings_.main_frame_before_activation_enabled) { | 655 if (commit_has_no_updates || settings_.main_frame_before_activation_enabled) { |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 699 return children_need_begin_frames_; | 749 return children_need_begin_frames_; |
| 700 | 750 |
| 701 return false; | 751 return false; |
| 702 } | 752 } |
| 703 | 753 |
| 704 bool SchedulerStateMachine::BeginFrameNeeded() const { | 754 bool SchedulerStateMachine::BeginFrameNeeded() const { |
| 705 // We can't handle BeginFrames when output surface isn't initialized. | 755 // We can't handle BeginFrames when output surface isn't initialized. |
| 706 // TODO(brianderson): Support output surface creation inside a BeginFrame. | 756 // TODO(brianderson): Support output surface creation inside a BeginFrame. |
| 707 if (!HasInitializedOutputSurface()) | 757 if (!HasInitializedOutputSurface()) |
| 708 return false; | 758 return false; |
| 709 | 759 return (BeginFrameNeededToAnimateOrDraw() || BeginFrameNeededForChildren() || |
| 710 if (SupportsProactiveBeginFrame()) { | 760 ProactiveBeginFrameWanted()); |
| 711 return (BeginFrameNeededToAnimateOrDraw() || | |
| 712 BeginFrameNeededForChildren() || | |
| 713 ProactiveBeginFrameWanted()); | |
| 714 } | |
| 715 | |
| 716 // Proactive BeginFrames are bad for the synchronous compositor because we | |
| 717 // have to draw when we get the BeginFrame and could end up drawing many | |
| 718 // duplicate frames if our new frame isn't ready in time. | |
| 719 // To poll for state with the synchronous compositor without having to draw, | |
| 720 // we rely on ShouldPollForAnticipatedDrawTriggers instead. | |
| 721 // Synchronous compositor doesn't have a browser. | |
| 722 DCHECK(!children_need_begin_frames_); | |
| 723 return BeginFrameNeededToAnimateOrDraw(); | |
| 724 } | 761 } |
| 725 | 762 |
| 726 bool SchedulerStateMachine::ShouldSetNeedsBeginFrames( | 763 bool SchedulerStateMachine::ShouldSetNeedsBeginFrames( |
| 727 bool frame_source_needs_begin_frames) const { | 764 bool frame_source_needs_begin_frames) const { |
| 728 bool needs_begin_frame = BeginFrameNeeded(); | 765 bool needs_begin_frame = BeginFrameNeeded(); |
| 729 | 766 |
| 730 // Never call SetNeedsBeginFrames if the frame source has the right value. | 767 // Never call SetNeedsBeginFrames if the frame source has the right value. |
| 731 if (needs_begin_frame == frame_source_needs_begin_frames) | 768 if (needs_begin_frame == frame_source_needs_begin_frames) |
| 732 return false; | 769 return false; |
| 733 | 770 |
| 734 // Always request the BeginFrame immediately if it's needed. | 771 // Always request the BeginFrame immediately if it's needed. |
| 735 if (needs_begin_frame) | 772 if (needs_begin_frame) |
| 736 return true; | 773 return true; |
| 737 | 774 |
| 738 // Stop requesting BeginFrames after a deadline. | 775 // Stop requesting BeginFrames after a deadline. |
| 739 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) | 776 if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) |
| 740 return true; | 777 return true; |
| 741 | 778 |
| 742 // Stop requesting BeginFrames immediately when output surface is lost. | 779 // Stop requesting BeginFrames immediately when output surface is lost. |
| 743 if (!HasInitializedOutputSurface()) | 780 if (!HasInitializedOutputSurface()) |
| 744 return true; | 781 return true; |
| 745 | 782 |
| 746 return false; | 783 return false; |
| 747 } | 784 } |
| 748 | 785 |
| 749 bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const { | |
| 750 // ShouldPollForAnticipatedDrawTriggers is what we use in place of | |
| 751 // ProactiveBeginFrameWanted when we are using the synchronous | |
| 752 // compositor. | |
| 753 if (!SupportsProactiveBeginFrame()) { | |
| 754 return !BeginFrameNeededToAnimateOrDraw() && ProactiveBeginFrameWanted(); | |
| 755 } | |
| 756 | |
| 757 // Non synchronous compositors should rely on | |
| 758 // ProactiveBeginFrameWanted to poll for state instead. | |
| 759 return false; | |
| 760 } | |
| 761 | |
| 762 // Note: If SupportsProactiveBeginFrame is false, the scheduler should poll | |
| 763 // for changes in it's draw state so it can request a BeginFrame when it's | |
| 764 // actually ready. | |
| 765 bool SchedulerStateMachine::SupportsProactiveBeginFrame() const { | |
| 766 // It is undesirable to proactively request BeginFrames if we are | |
| 767 // using a synchronous compositor because we *must* draw for every | |
| 768 // BeginFrame, which could cause duplicate draws. | |
| 769 return !settings_.using_synchronous_renderer_compositor; | |
| 770 } | |
| 771 | |
| 772 void SchedulerStateMachine::SetChildrenNeedBeginFrames( | 786 void SchedulerStateMachine::SetChildrenNeedBeginFrames( |
| 773 bool children_need_begin_frames) { | 787 bool children_need_begin_frames) { |
| 774 DCHECK(settings_.forward_begin_frames_to_children); | 788 DCHECK(settings_.forward_begin_frames_to_children); |
| 775 children_need_begin_frames_ = children_need_begin_frames; | 789 children_need_begin_frames_ = children_need_begin_frames; |
| 776 } | 790 } |
| 777 | 791 |
| 778 void SchedulerStateMachine::SetDeferCommits(bool defer_commits) { | 792 void SchedulerStateMachine::SetDeferCommits(bool defer_commits) { |
| 779 defer_commits_ = defer_commits; | 793 defer_commits_ = defer_commits; |
| 780 } | 794 } |
| 781 | 795 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 819 // SetNeedsBeginFrame requests, which may propagate to the BeginImplFrame | 833 // SetNeedsBeginFrame requests, which may propagate to the BeginImplFrame |
| 820 // provider and get sampled at an inopportune time, delaying the next | 834 // provider and get sampled at an inopportune time, delaying the next |
| 821 // BeginImplFrame. | 835 // BeginImplFrame. |
| 822 if (HasRequestedSwapThisFrame()) | 836 if (HasRequestedSwapThisFrame()) |
| 823 return true; | 837 return true; |
| 824 | 838 |
| 825 return false; | 839 return false; |
| 826 } | 840 } |
| 827 | 841 |
| 828 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) { | 842 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) { |
| 829 AdvanceCurrentFrameNumber(); | |
| 830 begin_impl_frame_args_ = args; | 843 begin_impl_frame_args_ = args; |
| 844 |
| 845 // Advance frame for synchronous compositor on SYNCHRONOUS_ANIMATE only. |
| 846 if (!settings_.using_synchronous_renderer_compositor || |
| 847 begin_impl_frame_args_.type == BeginFrameArgs::SYNCHRONOUS_ANIMATE) |
| 848 AdvanceFrame(); |
| 849 |
| 831 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) | 850 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) |
| 832 << AsValue()->ToString(); | 851 << AsValue()->ToString(); |
| 833 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING; | 852 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING; |
| 834 } | 853 } |
| 835 | 854 |
| 836 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() { | 855 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() { |
| 837 DCHECK_EQ(begin_impl_frame_state_, | 856 DCHECK_EQ(begin_impl_frame_state_, |
| 838 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) | 857 BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) |
| 839 << AsValue()->ToString(); | 858 << AsValue()->ToString(); |
| 840 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; | 859 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; |
| 841 } | 860 } |
| 842 | 861 |
| 843 void SchedulerStateMachine::OnBeginImplFrameDeadline() { | 862 void SchedulerStateMachine::OnBeginImplFrameDeadline() { |
| 844 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) | 863 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) |
| 845 << AsValue()->ToString(); | 864 << AsValue()->ToString(); |
| 846 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; | 865 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; |
| 847 } | 866 } |
| 848 | 867 |
| 849 void SchedulerStateMachine::OnBeginImplFrameIdle() { | 868 void SchedulerStateMachine::OnBeginImplFrameIdle() { |
| 850 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) | 869 DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) |
| 851 << AsValue()->ToString(); | 870 << AsValue()->ToString(); |
| 852 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE; | 871 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE; |
| 853 } | 872 } |
| 854 | 873 |
| 855 SchedulerStateMachine::BeginImplFrameDeadlineMode | 874 SchedulerStateMachine::BeginImplFrameDeadlineMode |
| 856 SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const { | 875 SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const { |
| 857 if (ShouldTriggerBeginImplFrameDeadlineImmediately()) { | 876 if (settings_.using_synchronous_renderer_compositor) { |
| 858 return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE; | 877 // If the synchronous compositor wants to draw now. |
| 878 return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_SYNCHRONOUS; |
| 879 } else if (ShouldTriggerBeginImplFrameDeadlineImmediately()) { |
| 880 return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_ASYNCHRONOUS; |
| 859 } else if (needs_redraw_ && pending_swaps_ < max_pending_swaps_) { | 881 } else if (needs_redraw_ && pending_swaps_ < max_pending_swaps_) { |
| 860 // We have an animation or fast input path on the impl thread that wants | 882 // We have an animation or fast input path on the impl thread that wants |
| 861 // to draw, so don't wait too long for a new active tree. | 883 // to draw, so don't wait too long for a new active tree. |
| 862 // If we are swap throttled we should wait until we are unblocked. | 884 // If we are swap throttled we should wait until we are unblocked. |
| 863 return BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR; | 885 return BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR; |
| 864 } else { | 886 } else { |
| 865 // The impl thread doesn't have anything it wants to draw and we are just | 887 // The impl thread doesn't have anything it wants to draw and we are just |
| 866 // waiting for a new active tree or we are swap throttled. In short we are | 888 // waiting for a new active tree or we are swap throttled. In short we are |
| 867 // blocked. | 889 // blocked. |
| 868 return BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE; | 890 return BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE; |
| 869 } | 891 } |
| 870 } | 892 } |
| 871 | 893 |
| 872 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately() | 894 bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately() |
| 873 const { | 895 const { |
| 874 // TODO(brianderson): This should take into account multiple commit sources. | 896 // TODO(brianderson): This should take into account multiple commit sources. |
| 875 | |
| 876 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) | 897 if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) |
| 877 return false; | 898 return false; |
| 878 | 899 |
| 879 // If we've lost the output surface, end the current BeginImplFrame ASAP | 900 // If we've lost the output surface, end the current BeginImplFrame ASAP |
| 880 // so we can start creating the next output surface. | 901 // so we can start creating the next output surface. |
| 881 if (output_surface_state_ == OUTPUT_SURFACE_LOST) | 902 if (output_surface_state_ == OUTPUT_SURFACE_LOST) |
| 882 return true; | 903 return true; |
| 883 | 904 |
| 884 // SwapAck throttle the deadline since we wont draw and swap anyway. | 905 // SwapAck throttle the deadline since we wont draw and swap anyway. |
| 885 if (pending_swaps_ >= max_pending_swaps_) | 906 if (pending_swaps_ >= max_pending_swaps_) |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 945 // which case the main thread is in a high latency mode. | 966 // which case the main thread is in a high latency mode. |
| 946 return (active_tree_needs_first_draw_ || HasSwappedThisFrame()) && | 967 return (active_tree_needs_first_draw_ || HasSwappedThisFrame()) && |
| 947 !HasSentBeginMainFrameThisFrame(); | 968 !HasSentBeginMainFrameThisFrame(); |
| 948 } | 969 } |
| 949 | 970 |
| 950 // If the active tree needs its first draw in any other state, we know the | 971 // If the active tree needs its first draw in any other state, we know the |
| 951 // main thread is in a high latency mode. | 972 // main thread is in a high latency mode. |
| 952 return active_tree_needs_first_draw_; | 973 return active_tree_needs_first_draw_; |
| 953 } | 974 } |
| 954 | 975 |
| 955 void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() { | |
| 956 AdvanceCurrentFrameNumber(); | |
| 957 inside_poll_for_anticipated_draw_triggers_ = true; | |
| 958 } | |
| 959 | |
| 960 void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() { | |
| 961 inside_poll_for_anticipated_draw_triggers_ = false; | |
| 962 } | |
| 963 | |
| 964 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; } | 976 void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; } |
| 965 | 977 |
| 966 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; } | 978 void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; } |
| 967 | 979 |
| 968 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; } | 980 void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; } |
| 969 | 981 |
| 970 void SchedulerStateMachine::SetNeedsAnimate() { | 982 void SchedulerStateMachine::SetNeedsAnimate() { |
| 971 needs_animate_ = true; | 983 needs_animate_ = true; |
| 972 } | 984 } |
| 973 | 985 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1132 static_cast<int>(begin_impl_frame_state_), | 1144 static_cast<int>(begin_impl_frame_state_), |
| 1133 static_cast<int>(commit_state_), | 1145 static_cast<int>(commit_state_), |
| 1134 has_pending_tree_ ? 'T' : 'F', | 1146 has_pending_tree_ ? 'T' : 'F', |
| 1135 pending_tree_is_ready_for_activation_ ? 'T' : 'F', | 1147 pending_tree_is_ready_for_activation_ ? 'T' : 'F', |
| 1136 active_tree_needs_first_draw_ ? 'T' : 'F', | 1148 active_tree_needs_first_draw_ ? 'T' : 'F', |
| 1137 max_pending_swaps_, | 1149 max_pending_swaps_, |
| 1138 pending_swaps_); | 1150 pending_swaps_); |
| 1139 } | 1151 } |
| 1140 | 1152 |
| 1141 } // namespace cc | 1153 } // namespace cc |
| OLD | NEW |