Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(372)

Side by Side Diff: cc/scheduler/scheduler_state_machine.cc

Issue 2659123004: cc: Add scheduler support for invalidating content on impl thread. (Closed)
Patch Set: addressed comments. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 15 matching lines...) Expand all
26 forced_redraw_state_(FORCED_REDRAW_STATE_IDLE), 26 forced_redraw_state_(FORCED_REDRAW_STATE_IDLE),
27 commit_count_(0), 27 commit_count_(0),
28 current_frame_number_(0), 28 current_frame_number_(0),
29 last_frame_number_submit_performed_(-1), 29 last_frame_number_submit_performed_(-1),
30 last_frame_number_draw_performed_(-1), 30 last_frame_number_draw_performed_(-1),
31 last_frame_number_begin_main_frame_sent_(-1), 31 last_frame_number_begin_main_frame_sent_(-1),
32 last_frame_number_invalidate_compositor_frame_sink_performed_(-1), 32 last_frame_number_invalidate_compositor_frame_sink_performed_(-1),
33 draw_funnel_(false), 33 draw_funnel_(false),
34 send_begin_main_frame_funnel_(true), 34 send_begin_main_frame_funnel_(true),
35 invalidate_compositor_frame_sink_funnel_(false), 35 invalidate_compositor_frame_sink_funnel_(false),
36 impl_side_invalidation_funnel_(false),
36 prepare_tiles_funnel_(0), 37 prepare_tiles_funnel_(0),
37 consecutive_checkerboard_animations_(0), 38 consecutive_checkerboard_animations_(0),
38 pending_submit_frames_(0), 39 pending_submit_frames_(0),
39 submit_frames_with_current_compositor_frame_sink_(0), 40 submit_frames_with_current_compositor_frame_sink_(0),
40 needs_redraw_(false), 41 needs_redraw_(false),
41 needs_prepare_tiles_(false), 42 needs_prepare_tiles_(false),
42 needs_begin_main_frame_(false), 43 needs_begin_main_frame_(false),
43 needs_one_begin_impl_frame_(false), 44 needs_one_begin_impl_frame_(false),
44 visible_(false), 45 visible_(false),
45 begin_frame_source_paused_(false), 46 begin_frame_source_paused_(false),
46 resourceless_draw_(false), 47 resourceless_draw_(false),
47 can_draw_(false), 48 can_draw_(false),
48 has_pending_tree_(false), 49 has_pending_tree_(false),
49 pending_tree_is_ready_for_activation_(false), 50 pending_tree_is_ready_for_activation_(false),
50 active_tree_needs_first_draw_(false), 51 active_tree_needs_first_draw_(false),
51 did_create_and_initialize_first_compositor_frame_sink_(false), 52 did_create_and_initialize_first_compositor_frame_sink_(false),
52 tree_priority_(NEW_CONTENT_TAKES_PRIORITY), 53 tree_priority_(NEW_CONTENT_TAKES_PRIORITY),
53 scroll_handler_state_( 54 scroll_handler_state_(
54 ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER), 55 ScrollHandlerState::SCROLL_DOES_NOT_AFFECT_SCROLL_HANDLER),
55 critical_begin_main_frame_to_activate_is_fast_(true), 56 critical_begin_main_frame_to_activate_is_fast_(true),
56 main_thread_missed_last_deadline_(false), 57 main_thread_missed_last_deadline_(false),
57 skip_next_begin_main_frame_to_reduce_latency_(false), 58 skip_next_begin_main_frame_to_reduce_latency_(false),
58 defer_commits_(false), 59 defer_commits_(false),
59 video_needs_begin_frames_(false), 60 video_needs_begin_frames_(false),
60 last_commit_had_no_updates_(false), 61 last_commit_had_no_updates_(false),
61 wait_for_ready_to_draw_(false), 62 wait_for_ready_to_draw_(false),
62 did_draw_in_last_frame_(false), 63 did_draw_in_last_frame_(false),
63 did_submit_in_last_frame_(false) {} 64 did_submit_in_last_frame_(false),
65 needs_impl_side_invalidation_(false),
66 run_impl_side_invalidation_after_main_frame_aborted_(false) {}
64 67
65 const char* SchedulerStateMachine::CompositorFrameSinkStateToString( 68 const char* SchedulerStateMachine::CompositorFrameSinkStateToString(
66 CompositorFrameSinkState state) { 69 CompositorFrameSinkState state) {
67 switch (state) { 70 switch (state) {
68 case COMPOSITOR_FRAME_SINK_NONE: 71 case COMPOSITOR_FRAME_SINK_NONE:
69 return "COMPOSITOR_FRAME_SINK_NONE"; 72 return "COMPOSITOR_FRAME_SINK_NONE";
70 case COMPOSITOR_FRAME_SINK_ACTIVE: 73 case COMPOSITOR_FRAME_SINK_ACTIVE:
71 return "COMPOSITOR_FRAME_SINK_ACTIVE"; 74 return "COMPOSITOR_FRAME_SINK_ACTIVE";
72 case COMPOSITOR_FRAME_SINK_CREATING: 75 case COMPOSITOR_FRAME_SINK_CREATING:
73 return "COMPOSITOR_FRAME_SINK_CREATING"; 76 return "COMPOSITOR_FRAME_SINK_CREATING";
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 case ACTION_DRAW_FORCED: 173 case ACTION_DRAW_FORCED:
171 return "ACTION_DRAW_FORCED"; 174 return "ACTION_DRAW_FORCED";
172 case ACTION_DRAW_ABORT: 175 case ACTION_DRAW_ABORT:
173 return "ACTION_DRAW_ABORT"; 176 return "ACTION_DRAW_ABORT";
174 case ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION: 177 case ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION:
175 return "ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION"; 178 return "ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION";
176 case ACTION_PREPARE_TILES: 179 case ACTION_PREPARE_TILES:
177 return "ACTION_PREPARE_TILES"; 180 return "ACTION_PREPARE_TILES";
178 case ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK: 181 case ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK:
179 return "ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK"; 182 return "ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK";
183 case ACTION_RUN_IMPL_SIDE_INVALIDATION:
184 return "ACTION_RUN_IMPL_SIDE_INVALIDATION";
180 } 185 }
181 NOTREACHED(); 186 NOTREACHED();
182 return "???"; 187 return "???";
183 } 188 }
184 189
185 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> 190 std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
186 SchedulerStateMachine::AsValue() const { 191 SchedulerStateMachine::AsValue() const {
187 std::unique_ptr<base::trace_event::TracedValue> state( 192 std::unique_ptr<base::trace_event::TracedValue> state(
188 new base::trace_event::TracedValue()); 193 new base::trace_event::TracedValue());
189 AsValueInto(state.get()); 194 AsValueInto(state.get());
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 return ACTION_DRAW_ABORT; 556 return ACTION_DRAW_ABORT;
552 else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) 557 else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
553 return ACTION_DRAW_FORCED; 558 return ACTION_DRAW_FORCED;
554 else 559 else
555 return ACTION_DRAW_IF_POSSIBLE; 560 return ACTION_DRAW_IF_POSSIBLE;
556 } 561 }
557 if (ShouldPrepareTiles()) 562 if (ShouldPrepareTiles())
558 return ACTION_PREPARE_TILES; 563 return ACTION_PREPARE_TILES;
559 if (ShouldSendBeginMainFrame()) 564 if (ShouldSendBeginMainFrame())
560 return ACTION_SEND_BEGIN_MAIN_FRAME; 565 return ACTION_SEND_BEGIN_MAIN_FRAME;
566 if (ShouldRunImplSideInvalidation())
567 return ACTION_RUN_IMPL_SIDE_INVALIDATION;
561 if (ShouldInvalidateCompositorFrameSink()) 568 if (ShouldInvalidateCompositorFrameSink())
562 return ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK; 569 return ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK;
563 if (ShouldBeginCompositorFrameSinkCreation()) 570 if (ShouldBeginCompositorFrameSinkCreation())
564 return ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION; 571 return ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION;
565 return ACTION_NONE; 572 return ACTION_NONE;
566 } 573 }
567 574
575 bool SchedulerStateMachine::ShouldRunImplSideInvalidation() const {
576 if (!needs_impl_side_invalidation_)
577 return false;
578
579 if (!CouldCreatePendingTree())
580 return false;
581
582 // If the main thread is ready to commit, the impl-side invalidations will be
583 // merged with the incoming main frame.
584 if (begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT)
585 return false;
586
587 // Don't invalidate too many times in the same frame.
588 if (impl_side_invalidation_funnel_)
Khushal 2017/02/03 01:45:11 One thought while thinking about the corner cases
589 return false;
590
591 // If invalidations go to the active tree and we are waiting for the previous
592 // frame to be drawn, submitted and acked.
593 if (settings_.commit_to_active_tree &&
594 (active_tree_needs_first_draw_ || IsDrawThrottled())) {
595 return false;
596 }
597
598 // Don't keep waiting on the main thread if the commits are being aborted.
599 if (run_impl_side_invalidation_after_main_frame_aborted_)
600 return true;
601
602 // If BeginMainFrame has been sent, let's wait for the main thread before
603 // pipelining impl-side invalidations.
604 // TODO(khushalsagar): If the main thread is high latency, may be run
605 // impl-side invalidations instead of waiting on the main thread?
606 if (begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_SENT ||
607 begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_STARTED)
608 return false;
609
610 // If a main frame request is pending, always prioritize sending a
611 // BeginMainFrame and receiving an update from the main thread before creating
612 // a pending tree for impl-side invalidations.
613 if (CouldSendBeginMainFrame() &&
614 begin_main_frame_state_ ==
615 BeginMainFrameState::BEGIN_MAIN_FRAME_STATE_IDLE)
616 return false;
617
618 // At this point, create a pending tree to run impl-side invalidations.
619 return true;
620 }
621
622 void SchedulerStateMachine::WillRunImplSideInvalidation() {
623 DCHECK(needs_impl_side_invalidation_);
624 WillRunImplSideInvalidationInternal();
625 }
626
627 void SchedulerStateMachine::WillRunImplSideInvalidationInternal() {
628 needs_impl_side_invalidation_ = false;
629 has_pending_tree_ = true;
630 run_impl_side_invalidation_after_main_frame_aborted_ = false;
631 impl_side_invalidation_funnel_ = true;
632 }
633
634 bool SchedulerStateMachine::CouldCreatePendingTree() const {
635 // Can't create a new pending tree till the current one is activated.
636 if (has_pending_tree_)
637 return false;
638
639 // Can't make frames while we're invisible.
640 if (!visible_)
641 return false;
642
643 // If the BeginFrameSource is paused, we will not be able to make any impl
644 // frames.
645 if (begin_frame_source_paused_)
646 return false;
647
648 return true;
649 }
650
568 void SchedulerStateMachine::WillSendBeginMainFrame() { 651 void SchedulerStateMachine::WillSendBeginMainFrame() {
569 DCHECK(!has_pending_tree_ || settings_.main_frame_before_activation_enabled); 652 DCHECK(!has_pending_tree_ || settings_.main_frame_before_activation_enabled);
570 DCHECK(visible_); 653 DCHECK(visible_);
571 DCHECK(!begin_frame_source_paused_); 654 DCHECK(!begin_frame_source_paused_);
572 DCHECK(!send_begin_main_frame_funnel_); 655 DCHECK(!send_begin_main_frame_funnel_);
573 begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_SENT; 656 begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_SENT;
574 needs_begin_main_frame_ = false; 657 needs_begin_main_frame_ = false;
575 send_begin_main_frame_funnel_ = true; 658 send_begin_main_frame_funnel_ = true;
576 last_frame_number_begin_main_frame_sent_ = current_frame_number_; 659 last_frame_number_begin_main_frame_sent_ = current_frame_number_;
577 } 660 }
578 661
579 void SchedulerStateMachine::WillCommit(bool commit_has_no_updates) { 662 void SchedulerStateMachine::WillCommit(bool commit_has_no_updates) {
580 DCHECK(!has_pending_tree_ || 663 DCHECK(!has_pending_tree_ ||
581 (settings_.main_frame_before_activation_enabled && 664 (settings_.main_frame_before_activation_enabled &&
582 commit_has_no_updates)); 665 commit_has_no_updates));
583 commit_count_++; 666 commit_count_++;
584 last_commit_had_no_updates_ = commit_has_no_updates; 667 last_commit_had_no_updates_ = commit_has_no_updates;
585 begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_IDLE; 668 begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_IDLE;
586 669
587 if (!commit_has_no_updates) { 670 if (!commit_has_no_updates) {
588 // Pending tree only exists if commit had updates. 671 // Pending tree only exists if commit had updates.
589 has_pending_tree_ = true; 672 has_pending_tree_ = true;
590 pending_tree_is_ready_for_activation_ = false; 673 pending_tree_is_ready_for_activation_ = false;
591 wait_for_ready_to_draw_ = settings_.commit_to_active_tree; 674 wait_for_ready_to_draw_ = settings_.commit_to_active_tree;
675
676 // If there was a commit, the impl-side invalidations will be merged with
677 // it.
678 WillRunImplSideInvalidationInternal();
679 } else if (needs_impl_side_invalidation_) {
680 run_impl_side_invalidation_after_main_frame_aborted_ = true;
592 } 681 }
593 682
594 // Update state related to forced draws. 683 // Update state related to forced draws.
595 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) { 684 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) {
596 forced_redraw_state_ = has_pending_tree_ 685 forced_redraw_state_ = has_pending_tree_
597 ? FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION 686 ? FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION
598 : FORCED_REDRAW_STATE_WAITING_FOR_DRAW; 687 : FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
599 } 688 }
600 689
601 // Update the output surface state. 690 // Update the output surface state.
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 771
683 void SchedulerStateMachine::WillDraw() { 772 void SchedulerStateMachine::WillDraw() {
684 DCHECK(!draw_funnel_); 773 DCHECK(!draw_funnel_);
685 WillDrawInternal(); 774 WillDrawInternal();
686 } 775 }
687 776
688 void SchedulerStateMachine::DidDraw(DrawResult draw_result) { 777 void SchedulerStateMachine::DidDraw(DrawResult draw_result) {
689 DidDrawInternal(draw_result); 778 DidDrawInternal(draw_result);
690 } 779 }
691 780
781 void SchedulerStateMachine::SetNeedsImplSideInvalidation() {
782 needs_impl_side_invalidation_ = true;
783 }
784
692 void SchedulerStateMachine::AbortDraw() { 785 void SchedulerStateMachine::AbortDraw() {
693 // Pretend like the draw was successful. 786 // Pretend like the draw was successful.
694 // Note: We may abort at any time and cannot DCHECK that 787 // Note: We may abort at any time and cannot DCHECK that
695 // we haven't drawn in or swapped in the last frame here. 788 // we haven't drawn in or swapped in the last frame here.
696 WillDrawInternal(); 789 WillDrawInternal();
697 DidDrawInternal(DRAW_ABORTED_DRAINING_PIPELINE); 790 DidDrawInternal(DRAW_ABORTED_DRAINING_PIPELINE);
698 } 791 }
699 792
700 void SchedulerStateMachine::WillPrepareTiles() { 793 void SchedulerStateMachine::WillPrepareTiles() {
701 needs_prepare_tiles_ = false; 794 needs_prepare_tiles_ = false;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 853
761 // These are the cases where we require a BeginFrame message to make progress 854 // These are the cases where we require a BeginFrame message to make progress
762 // on requested actions. 855 // on requested actions.
763 bool SchedulerStateMachine::BeginFrameRequiredForAction() const { 856 bool SchedulerStateMachine::BeginFrameRequiredForAction() const {
764 // The forced draw respects our normal draw scheduling, so we need to 857 // The forced draw respects our normal draw scheduling, so we need to
765 // request a BeginImplFrame for it. 858 // request a BeginImplFrame for it.
766 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) 859 if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
767 return true; 860 return true;
768 861
769 return needs_redraw_ || needs_one_begin_impl_frame_ || 862 return needs_redraw_ || needs_one_begin_impl_frame_ ||
770 (needs_begin_main_frame_ && !defer_commits_); 863 (needs_begin_main_frame_ && !defer_commits_) ||
864 needs_impl_side_invalidation_;
771 } 865 }
772 866
773 // These are cases where we are very likely want a BeginFrame message in the 867 // These are cases where we are very likely want a BeginFrame message in the
774 // near future. Proactively requesting the BeginImplFrame helps hide the round 868 // near future. Proactively requesting the BeginImplFrame helps hide the round
775 // trip latency of the SetNeedsBeginFrame request that has to go to the 869 // trip latency of the SetNeedsBeginFrame request that has to go to the
776 // Browser. 870 // Browser.
777 // This includes things like drawing soon, but might not actually have a new 871 // This includes things like drawing soon, but might not actually have a new
778 // frame to draw when we receive the next BeginImplFrame. 872 // frame to draw when we receive the next BeginImplFrame.
779 bool SchedulerStateMachine::ProactiveBeginFrameWanted() const { 873 bool SchedulerStateMachine::ProactiveBeginFrameWanted() const {
780 // Do not be proactive when invisible. 874 // Do not be proactive when invisible.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 current_frame_number_++; 914 current_frame_number_++;
821 915
822 last_commit_had_no_updates_ = false; 916 last_commit_had_no_updates_ = false;
823 did_draw_in_last_frame_ = false; 917 did_draw_in_last_frame_ = false;
824 did_submit_in_last_frame_ = false; 918 did_submit_in_last_frame_ = false;
825 needs_one_begin_impl_frame_ = false; 919 needs_one_begin_impl_frame_ = false;
826 920
827 // Clear funnels for any actions we perform during the frame. 921 // Clear funnels for any actions we perform during the frame.
828 send_begin_main_frame_funnel_ = false; 922 send_begin_main_frame_funnel_ = false;
829 invalidate_compositor_frame_sink_funnel_ = false; 923 invalidate_compositor_frame_sink_funnel_ = false;
924 impl_side_invalidation_funnel_ = false;
830 925
831 // "Drain" the PrepareTiles funnel. 926 // "Drain" the PrepareTiles funnel.
832 if (prepare_tiles_funnel_ > 0) 927 if (prepare_tiles_funnel_ > 0)
833 prepare_tiles_funnel_--; 928 prepare_tiles_funnel_--;
834 } 929 }
835 930
836 void SchedulerStateMachine::OnBeginImplFrameDeadline() { 931 void SchedulerStateMachine::OnBeginImplFrameDeadline() {
837 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; 932 begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
838 933
839 // Clear funnels for any actions we perform during the deadline. 934 // Clear funnels for any actions we perform during the deadline.
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1103 case COMPOSITOR_FRAME_SINK_ACTIVE: 1198 case COMPOSITOR_FRAME_SINK_ACTIVE:
1104 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_COMMIT: 1199 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_COMMIT:
1105 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_ACTIVATION: 1200 case COMPOSITOR_FRAME_SINK_WAITING_FOR_FIRST_ACTIVATION:
1106 return true; 1201 return true;
1107 } 1202 }
1108 NOTREACHED(); 1203 NOTREACHED();
1109 return false; 1204 return false;
1110 } 1205 }
1111 1206
1112 } // namespace cc 1207 } // namespace cc
OLDNEW
« no previous file with comments | « cc/scheduler/scheduler_state_machine.h ('k') | cc/scheduler/scheduler_state_machine_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698