Chromium Code Reviews| 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" |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 38 commit_count_(0), | 38 commit_count_(0), |
| 39 current_frame_number_(0), | 39 current_frame_number_(0), |
| 40 last_frame_number_submit_performed_(-1), | 40 last_frame_number_submit_performed_(-1), |
| 41 last_frame_number_draw_performed_(-1), | 41 last_frame_number_draw_performed_(-1), |
| 42 last_frame_number_begin_main_frame_sent_(-1), | 42 last_frame_number_begin_main_frame_sent_(-1), |
| 43 last_frame_number_invalidate_compositor_frame_sink_performed_(-1), | 43 last_frame_number_invalidate_compositor_frame_sink_performed_(-1), |
| 44 draw_funnel_(false), | 44 draw_funnel_(false), |
| 45 send_begin_main_frame_funnel_(true), | 45 send_begin_main_frame_funnel_(true), |
| 46 invalidate_compositor_frame_sink_funnel_(false), | 46 invalidate_compositor_frame_sink_funnel_(false), |
| 47 impl_side_invalidation_funnel_(false), | 47 impl_side_invalidation_funnel_(false), |
| 48 do_idle_work_funnel_(false), | |
| 48 prepare_tiles_funnel_(0), | 49 prepare_tiles_funnel_(0), |
| 49 consecutive_checkerboard_animations_(0), | 50 consecutive_checkerboard_animations_(0), |
| 50 pending_submit_frames_(0), | 51 pending_submit_frames_(0), |
| 51 submit_frames_with_current_compositor_frame_sink_(0), | 52 submit_frames_with_current_compositor_frame_sink_(0), |
| 52 needs_redraw_(false), | 53 needs_redraw_(false), |
| 53 needs_prepare_tiles_(false), | 54 needs_prepare_tiles_(false), |
| 54 needs_begin_main_frame_(false), | 55 needs_begin_main_frame_(false), |
| 55 needs_one_begin_impl_frame_(false), | 56 needs_one_begin_impl_frame_(false), |
| 56 visible_(false), | 57 visible_(false), |
| 57 begin_frame_source_paused_(false), | 58 begin_frame_source_paused_(false), |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 case ACTION_DRAW_ABORT: | 188 case ACTION_DRAW_ABORT: |
| 188 return "ACTION_DRAW_ABORT"; | 189 return "ACTION_DRAW_ABORT"; |
| 189 case ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION: | 190 case ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION: |
| 190 return "ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION"; | 191 return "ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION"; |
| 191 case ACTION_PREPARE_TILES: | 192 case ACTION_PREPARE_TILES: |
| 192 return "ACTION_PREPARE_TILES"; | 193 return "ACTION_PREPARE_TILES"; |
| 193 case ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK: | 194 case ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK: |
| 194 return "ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK"; | 195 return "ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK"; |
| 195 case ACTION_PERFORM_IMPL_SIDE_INVALIDATION: | 196 case ACTION_PERFORM_IMPL_SIDE_INVALIDATION: |
| 196 return "ACTION_PERFORM_IMPL_SIDE_INVALIDATION"; | 197 return "ACTION_PERFORM_IMPL_SIDE_INVALIDATION"; |
| 198 case ACTION_DO_IDLE_WORK: | |
| 199 return "ACTION_DO_IDLE_WORK"; | |
| 197 } | 200 } |
| 198 NOTREACHED(); | 201 NOTREACHED(); |
| 199 return "???"; | 202 return "???"; |
| 200 } | 203 } |
| 201 | 204 |
| 202 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> | 205 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> |
| 203 SchedulerStateMachine::AsValue() const { | 206 SchedulerStateMachine::AsValue() const { |
| 204 std::unique_ptr<base::trace_event::TracedValue> state( | 207 std::unique_ptr<base::trace_event::TracedValue> state( |
| 205 new base::trace_event::TracedValue()); | 208 new base::trace_event::TracedValue()); |
| 206 AsValueInto(state.get()); | 209 AsValueInto(state.get()); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 state->SetInteger("last_begin_frame_sequence_number_pending_tree_was_fresh", | 242 state->SetInteger("last_begin_frame_sequence_number_pending_tree_was_fresh", |
| 240 last_begin_frame_sequence_number_pending_tree_was_fresh_); | 243 last_begin_frame_sequence_number_pending_tree_was_fresh_); |
| 241 state->SetInteger("last_begin_frame_sequence_number_active_tree_was_fresh", | 244 state->SetInteger("last_begin_frame_sequence_number_active_tree_was_fresh", |
| 242 last_begin_frame_sequence_number_active_tree_was_fresh_); | 245 last_begin_frame_sequence_number_active_tree_was_fresh_); |
| 243 state->SetInteger( | 246 state->SetInteger( |
| 244 "last_begin_frame_sequence_number_compositor_frame_was_fresh", | 247 "last_begin_frame_sequence_number_compositor_frame_was_fresh", |
| 245 last_begin_frame_sequence_number_compositor_frame_was_fresh_); | 248 last_begin_frame_sequence_number_compositor_frame_was_fresh_); |
| 246 state->SetBoolean("funnel: draw_funnel", draw_funnel_); | 249 state->SetBoolean("funnel: draw_funnel", draw_funnel_); |
| 247 state->SetBoolean("funnel: send_begin_main_frame_funnel", | 250 state->SetBoolean("funnel: send_begin_main_frame_funnel", |
| 248 send_begin_main_frame_funnel_); | 251 send_begin_main_frame_funnel_); |
| 252 state->SetBoolean("funnel: do_idle_work_funnel", do_idle_work_funnel_); | |
| 249 state->SetInteger("funnel: prepare_tiles_funnel", prepare_tiles_funnel_); | 253 state->SetInteger("funnel: prepare_tiles_funnel", prepare_tiles_funnel_); |
| 250 state->SetBoolean("funnel: invalidate_compositor_frame_sink_funnel", | 254 state->SetBoolean("funnel: invalidate_compositor_frame_sink_funnel", |
| 251 invalidate_compositor_frame_sink_funnel_); | 255 invalidate_compositor_frame_sink_funnel_); |
| 252 state->SetBoolean("funnel: impl_side_invalidation_funnel", | 256 state->SetBoolean("funnel: impl_side_invalidation_funnel", |
| 253 impl_side_invalidation_funnel_); | 257 impl_side_invalidation_funnel_); |
| 254 state->SetInteger("consecutive_checkerboard_animations", | 258 state->SetInteger("consecutive_checkerboard_animations", |
| 255 consecutive_checkerboard_animations_); | 259 consecutive_checkerboard_animations_); |
| 256 state->SetInteger("pending_submit_frames_", pending_submit_frames_); | 260 state->SetInteger("pending_submit_frames_", pending_submit_frames_); |
| 257 state->SetInteger("submit_frames_with_current_compositor_frame_sink", | 261 state->SetInteger("submit_frames_with_current_compositor_frame_sink", |
| 258 submit_frames_with_current_compositor_frame_sink_); | 262 submit_frames_with_current_compositor_frame_sink_); |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 421 return false; | 425 return false; |
| 422 | 426 |
| 423 // If we want to force activation, do so ASAP. | 427 // If we want to force activation, do so ASAP. |
| 424 if (PendingActivationsShouldBeForced()) | 428 if (PendingActivationsShouldBeForced()) |
| 425 return true; | 429 return true; |
| 426 | 430 |
| 427 // At this point, only activate if we are ready to activate. | 431 // At this point, only activate if we are ready to activate. |
| 428 return pending_tree_is_ready_for_activation_; | 432 return pending_tree_is_ready_for_activation_; |
| 429 } | 433 } |
| 430 | 434 |
| 435 bool SchedulerStateMachine::CouldDoIdleWork() const { | |
| 436 if (needs_begin_main_frame_ || send_begin_main_frame_funnel_) | |
|
Dan Elphick
2017/03/21 11:23:51
I made this change here because needs_begin_main_f
Sami
2017/03/21 11:35:21
I wonder if we should look at begin_main_frame_sta
Sami
2017/03/21 11:36:39
Just to clarify: the problem with looking at the f
Dan Elphick
2017/03/21 15:56:25
I've renamed the funnel as discussed in comments e
| |
| 437 return false; | |
| 438 | |
| 439 // We can not perform commits if we are not visible. | |
| 440 if (!visible_) | |
| 441 return false; | |
| 442 | |
| 443 // There are no BeginImplFrames while BeginFrameSource is paused, | |
| 444 // so should also stop BeginMainFrames. | |
| 445 if (begin_frame_source_paused_) | |
| 446 return false; | |
| 447 | |
| 448 // Do not make a new commits when it is deferred. | |
| 449 if (defer_commits_) | |
| 450 return false; | |
| 451 | |
| 452 return true; | |
| 453 } | |
| 454 | |
| 455 bool SchedulerStateMachine::ShouldDoIdleWork() const { | |
| 456 if (!CouldDoIdleWork()) | |
| 457 return false; | |
| 458 | |
| 459 // Do not do idle work too many times in a single frame or before | |
| 460 // the first BeginFrame. | |
| 461 if (do_idle_work_funnel_) | |
| 462 return false; | |
| 463 | |
| 464 // Only send BeginMainFrame when there isn't another commit pending already. | |
| 465 // Other parts of the state machine indirectly defer the BeginMainFrame | |
| 466 // by transitioning to WAITING commit states rather than going | |
| 467 // immediately to IDLE. | |
| 468 if (begin_main_frame_state_ != BEGIN_MAIN_FRAME_STATE_IDLE) | |
| 469 return false; | |
| 470 | |
| 471 // MFBA is disabled and we are waiting for previous activation. | |
| 472 if (!settings_.main_frame_before_activation_enabled && has_pending_tree_) | |
| 473 return false; | |
| 474 | |
| 475 // We are waiting for previous frame to be drawn, submitted and acked. | |
| 476 if (settings_.commit_to_active_tree && | |
| 477 (active_tree_needs_first_draw_ || IsDrawThrottled())) { | |
| 478 return false; | |
| 479 } | |
| 480 | |
| 481 // Don't send BeginMainFrame early if we are prioritizing the active tree | |
| 482 // because of ImplLatencyTakesPriority. | |
| 483 if (ImplLatencyTakesPriority() && | |
| 484 (has_pending_tree_ || active_tree_needs_first_draw_)) { | |
| 485 return false; | |
| 486 } | |
| 487 | |
| 488 // We should not send BeginMainFrame while we are in the idle state since we | |
| 489 // might have new user input arriving soon. It's okay to send BeginMainFrame | |
| 490 // for the synchronous compositor because the main thread is always high | |
| 491 // latency in that case. | |
| 492 // TODO(brianderson): Allow sending BeginMainFrame while idle when the main | |
| 493 // thread isn't consuming user input for non-synchronous compositor. | |
| 494 if (!settings_.using_synchronous_renderer_compositor && | |
| 495 begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_IDLE) { | |
| 496 return false; | |
| 497 } | |
| 498 | |
| 499 // We need a new commit for the forced redraw. This honors the | |
| 500 // single commit per interval because the result will be swapped to screen. | |
| 501 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) | |
| 502 return true; | |
| 503 | |
| 504 // We shouldn't normally accept commits if there isn't an CompositorFrameSink. | |
| 505 if (!HasInitializedCompositorFrameSink()) | |
| 506 return false; | |
| 507 | |
| 508 if (!settings_.main_frame_while_submit_frame_throttled_enabled) { | |
| 509 // Throttle the BeginMainFrames on CompositorFrameAck unless we just | |
| 510 // submitted a frame to potentially improve impl-thread latency over | |
| 511 // main-thread throughput. | |
| 512 // TODO(brianderson): Remove this restriction to improve throughput or | |
| 513 // make it conditional on ImplLatencyTakesPriority. | |
| 514 bool just_submitted_in_deadline = | |
| 515 begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE && | |
| 516 did_submit_in_last_frame_; | |
| 517 if (IsDrawThrottled() && !just_submitted_in_deadline) | |
| 518 return false; | |
| 519 } | |
| 520 | |
| 521 if (skip_next_begin_main_frame_to_reduce_latency_) | |
| 522 return false; | |
| 523 | |
| 524 return true; | |
| 525 } | |
| 526 | |
| 431 bool SchedulerStateMachine::CouldSendBeginMainFrame() const { | 527 bool SchedulerStateMachine::CouldSendBeginMainFrame() const { |
| 432 if (!needs_begin_main_frame_) | 528 if (!needs_begin_main_frame_) |
| 433 return false; | 529 return false; |
| 434 | 530 |
| 435 // We can not perform commits if we are not visible. | 531 // We can not perform commits if we are not visible. |
| 436 if (!visible_) | 532 if (!visible_) |
| 437 return false; | 533 return false; |
| 438 | 534 |
| 439 // There are no BeginImplFrames while BeginFrameSource is paused, | 535 // There are no BeginImplFrames while BeginFrameSource is paused, |
| 440 // so should also stop BeginMainFrames. | 536 // so should also stop BeginMainFrames. |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 587 return ACTION_DRAW_FORCED; | 683 return ACTION_DRAW_FORCED; |
| 588 else | 684 else |
| 589 return ACTION_DRAW_IF_POSSIBLE; | 685 return ACTION_DRAW_IF_POSSIBLE; |
| 590 } | 686 } |
| 591 if (ShouldPerformImplSideInvalidation()) | 687 if (ShouldPerformImplSideInvalidation()) |
| 592 return ACTION_PERFORM_IMPL_SIDE_INVALIDATION; | 688 return ACTION_PERFORM_IMPL_SIDE_INVALIDATION; |
| 593 if (ShouldPrepareTiles()) | 689 if (ShouldPrepareTiles()) |
| 594 return ACTION_PREPARE_TILES; | 690 return ACTION_PREPARE_TILES; |
| 595 if (ShouldSendBeginMainFrame()) | 691 if (ShouldSendBeginMainFrame()) |
| 596 return ACTION_SEND_BEGIN_MAIN_FRAME; | 692 return ACTION_SEND_BEGIN_MAIN_FRAME; |
| 693 if (ShouldDoIdleWork()) | |
| 694 return ACTION_DO_IDLE_WORK; | |
| 597 if (ShouldInvalidateCompositorFrameSink()) | 695 if (ShouldInvalidateCompositorFrameSink()) |
| 598 return ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK; | 696 return ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK; |
| 599 if (ShouldBeginCompositorFrameSinkCreation()) | 697 if (ShouldBeginCompositorFrameSinkCreation()) |
| 600 return ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION; | 698 return ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION; |
| 601 return ACTION_NONE; | 699 return ACTION_NONE; |
| 602 } | 700 } |
| 603 | 701 |
| 604 bool SchedulerStateMachine::ShouldPerformImplSideInvalidation() const { | 702 bool SchedulerStateMachine::ShouldPerformImplSideInvalidation() const { |
| 605 if (!needs_impl_side_invalidation_) | 703 if (!needs_impl_side_invalidation_) |
| 606 return false; | 704 return false; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 685 DCHECK(!begin_frame_source_paused_); | 783 DCHECK(!begin_frame_source_paused_); |
| 686 DCHECK(!send_begin_main_frame_funnel_); | 784 DCHECK(!send_begin_main_frame_funnel_); |
| 687 begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_SENT; | 785 begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_SENT; |
| 688 needs_begin_main_frame_ = false; | 786 needs_begin_main_frame_ = false; |
| 689 send_begin_main_frame_funnel_ = true; | 787 send_begin_main_frame_funnel_ = true; |
| 690 last_frame_number_begin_main_frame_sent_ = current_frame_number_; | 788 last_frame_number_begin_main_frame_sent_ = current_frame_number_; |
| 691 last_begin_frame_sequence_number_begin_main_frame_sent_ = | 789 last_begin_frame_sequence_number_begin_main_frame_sent_ = |
| 692 begin_frame_sequence_number_; | 790 begin_frame_sequence_number_; |
| 693 } | 791 } |
| 694 | 792 |
| 793 void SchedulerStateMachine::WillDoIdleWork() { | |
| 794 DCHECK(!has_pending_tree_ || settings_.main_frame_before_activation_enabled); | |
| 795 DCHECK(visible_); | |
| 796 DCHECK(!begin_frame_source_paused_); | |
| 797 DCHECK(!do_idle_work_funnel_); | |
| 798 do_idle_work_funnel_ = true; | |
| 799 } | |
| 800 | |
| 695 void SchedulerStateMachine::WillCommit(bool commit_has_no_updates) { | 801 void SchedulerStateMachine::WillCommit(bool commit_has_no_updates) { |
| 696 bool can_have_pending_tree = | 802 bool can_have_pending_tree = |
| 697 commit_has_no_updates && | 803 commit_has_no_updates && |
| 698 (settings_.main_frame_before_activation_enabled || | 804 (settings_.main_frame_before_activation_enabled || |
| 699 current_pending_tree_is_impl_side_); | 805 current_pending_tree_is_impl_side_); |
| 700 DCHECK(!has_pending_tree_ || can_have_pending_tree); | 806 DCHECK(!has_pending_tree_ || can_have_pending_tree); |
| 701 commit_count_++; | 807 commit_count_++; |
| 702 last_commit_had_no_updates_ = commit_has_no_updates; | 808 last_commit_had_no_updates_ = commit_has_no_updates; |
| 703 begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_IDLE; | 809 begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_IDLE; |
| 704 | 810 |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1040 | 1146 |
| 1041 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; | 1147 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME; |
| 1042 current_frame_number_++; | 1148 current_frame_number_++; |
| 1043 | 1149 |
| 1044 last_commit_had_no_updates_ = false; | 1150 last_commit_had_no_updates_ = false; |
| 1045 did_draw_in_last_frame_ = false; | 1151 did_draw_in_last_frame_ = false; |
| 1046 did_submit_in_last_frame_ = false; | 1152 did_submit_in_last_frame_ = false; |
| 1047 needs_one_begin_impl_frame_ = false; | 1153 needs_one_begin_impl_frame_ = false; |
| 1048 | 1154 |
| 1049 // Clear funnels for any actions we perform during the frame. | 1155 // Clear funnels for any actions we perform during the frame. |
| 1156 do_idle_work_funnel_ = false; | |
| 1050 send_begin_main_frame_funnel_ = false; | 1157 send_begin_main_frame_funnel_ = false; |
| 1051 invalidate_compositor_frame_sink_funnel_ = false; | 1158 invalidate_compositor_frame_sink_funnel_ = false; |
| 1052 impl_side_invalidation_funnel_ = false; | 1159 impl_side_invalidation_funnel_ = false; |
| 1053 | 1160 |
| 1054 // "Drain" the PrepareTiles funnel. | 1161 // "Drain" the PrepareTiles funnel. |
| 1055 if (prepare_tiles_funnel_ > 0) | 1162 if (prepare_tiles_funnel_ > 0) |
| 1056 prepare_tiles_funnel_--; | 1163 prepare_tiles_funnel_--; |
| 1057 } | 1164 } |
| 1058 | 1165 |
| 1059 void SchedulerStateMachine::OnBeginImplFrameDeadline() { | 1166 void SchedulerStateMachine::OnBeginImplFrameDeadline() { |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1335 case COMPOSITOR_FRAME_SINK_ACTIVE: | 1442 case COMPOSITOR_FRAME_SINK_ACTIVE: |
| 1336 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_COMMIT: | 1443 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_COMMIT: |
| 1337 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_ACTIVATION: | 1444 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_ACTIVATION: |
| 1338 return true; | 1445 return true; |
| 1339 } | 1446 } |
| 1340 NOTREACHED(); | 1447 NOTREACHED(); |
| 1341 return false; | 1448 return false; |
| 1342 } | 1449 } |
| 1343 | 1450 |
| 1344 } // namespace cc | 1451 } // namespace cc |
| OLD | NEW |