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

Unified Diff: cc/scheduler/scheduler_state_machine.cc

Issue 2659123004: cc: Add scheduler support for invalidating content on impl thread. (Closed)
Patch Set: tests 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 side-by-side diff with in-line comments
Download patch
Index: cc/scheduler/scheduler_state_machine.cc
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc
index 91ae485850381b5ce41b3eb509a11d06deb5ba09..124cd0a8f4afdd453ff30f530cea99cd8972e44f 100644
--- a/cc/scheduler/scheduler_state_machine.cc
+++ b/cc/scheduler/scheduler_state_machine.cc
@@ -33,6 +33,7 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
draw_funnel_(false),
send_begin_main_frame_funnel_(true),
invalidate_compositor_frame_sink_funnel_(false),
+ impl_side_invalidation_funnel_(false),
prepare_tiles_funnel_(0),
consecutive_checkerboard_animations_(0),
pending_submit_frames_(0),
@@ -60,7 +61,9 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
last_commit_had_no_updates_(false),
wait_for_ready_to_draw_(false),
did_draw_in_last_frame_(false),
- did_submit_in_last_frame_(false) {}
+ did_submit_in_last_frame_(false),
+ needs_impl_side_invalidation_(false),
+ impl_side_invalidations_take_priority_(false) {}
const char* SchedulerStateMachine::CompositorFrameSinkStateToString(
CompositorFrameSinkState state) {
@@ -177,6 +180,8 @@ const char* SchedulerStateMachine::ActionToString(Action action) {
return "ACTION_PREPARE_TILES";
case ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK:
return "ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK";
+ case ACTION_PERFORM_IMPL_SIDE_INVALIDATION:
+ return "ACTION_PERFORM_IMPL_SIDE_INVALIDATION";
}
NOTREACHED();
return "???";
@@ -220,6 +225,8 @@ void SchedulerStateMachine::AsValueInto(
state->SetInteger("funnel: prepare_tiles_funnel", prepare_tiles_funnel_);
state->SetBoolean("funnel: invalidate_compositor_frame_sink_funnel",
invalidate_compositor_frame_sink_funnel_);
+ state->SetBoolean("funnel: impl_side_invalidation_funnel",
+ impl_side_invalidation_funnel_);
state->SetInteger("consecutive_checkerboard_animations",
consecutive_checkerboard_animations_);
state->SetInteger("pending_submit_frames_", pending_submit_frames_);
@@ -255,6 +262,10 @@ void SchedulerStateMachine::AsValueInto(
state->SetBoolean("last_commit_had_no_updates", last_commit_had_no_updates_);
state->SetBoolean("did_draw_in_last_frame", did_draw_in_last_frame_);
state->SetBoolean("did_submit_in_last_frame", did_submit_in_last_frame_);
+ state->SetBoolean("needs_impl_side_invalidation",
+ needs_impl_side_invalidation_);
+ state->SetBoolean("impl_side_invalidations_take_priority",
+ impl_side_invalidations_take_priority_);
state->EndDictionary();
}
@@ -558,6 +569,8 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
return ACTION_PREPARE_TILES;
if (ShouldSendBeginMainFrame())
return ACTION_SEND_BEGIN_MAIN_FRAME;
+ if (ShouldPerformImplSideInvalidation())
+ return ACTION_PERFORM_IMPL_SIDE_INVALIDATION;
if (ShouldInvalidateCompositorFrameSink())
return ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK;
if (ShouldBeginCompositorFrameSinkCreation())
@@ -565,6 +578,94 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
return ACTION_NONE;
}
+bool SchedulerStateMachine::ShouldPerformImplSideInvalidation() const {
+ if (!needs_impl_side_invalidation_)
+ return false;
+
+ if (!CouldCreatePendingTree())
+ return false;
+
+ // If the main thread is ready to commit, the impl-side invalidations will be
+ // merged with the incoming main frame.
+ if (begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_READY_TO_COMMIT)
+ return false;
+
+ // Don't invalidate too many times in the same frame.
+ if (impl_side_invalidation_funnel_)
+ return false;
+
+ // If invalidations go to the active tree and we are waiting for the previous
+ // frame to be drawn, submitted and acked.
+ if (settings_.commit_to_active_tree &&
+ (active_tree_needs_first_draw_ || IsDrawThrottled())) {
sunnyps 2017/02/14 21:40:18 What does impl-side invalidation mean if commit_to
Khushal 2017/02/15 00:56:33 It would mean we invalidate the tiles on the activ
enne (OOO) 2017/02/15 01:09:28 Yeah, that was my thought as well. It seems like
sunnyps 2017/02/20 23:19:22 I'm still confused about how active tree tiles wil
Khushal 2017/02/21 09:43:44 The impl-side invalidation works exactly like a co
+ return false;
+ }
+
+ // Don't wait on the response to BeginMainFrame if we are prioritizing impl
+ // side invalidations.
+ if (impl_side_invalidations_take_priority_)
+ return true;
+
+ // If BeginMainFrame has been sent, let's wait for the main thread before
+ // pipelining impl-side invalidations.
+ // TODO(khushalsagar): If the main thread is high latency, may be run
+ // impl-side invalidations instead of waiting on the main thread?
+ // See crbug.com/691735.
+ if (begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_SENT ||
+ begin_main_frame_state_ == BEGIN_MAIN_FRAME_STATE_STARTED)
+ return false;
+
+ // If a main frame request is pending, always prioritize sending a
+ // BeginMainFrame and receiving an update from the main thread before creating
+ // a pending tree for impl-side invalidations.
+ if (CouldSendBeginMainFrame() &&
+ begin_main_frame_state_ ==
+ BeginMainFrameState::BEGIN_MAIN_FRAME_STATE_IDLE)
+ return false;
+
+ // At this point, create a pending tree to run impl-side invalidations.
+ return true;
+}
+
+void SchedulerStateMachine::WillRunImplSideInvalidation() {
+ DCHECK(needs_impl_side_invalidation_);
+ WillRunImplSideInvalidationInternal();
+}
+
+void SchedulerStateMachine::WillRunImplSideInvalidationInternal() {
+ needs_impl_side_invalidation_ = false;
+ has_pending_tree_ = true;
+ impl_side_invalidations_take_priority_ = false;
+ impl_side_invalidation_funnel_ = true;
+
+ // We fill the BeginMainFrame funnel when running impl-side invalidations
+ // since we know that another pending tree in this BeginFrame will end up
+ // getting blocked on drawing of the impl-side pending tree further down the
+ // pipeline.
+ send_begin_main_frame_funnel_ = true;
sunnyps 2017/02/14 21:40:18 I'm kinda worried about this. It means there will
Khushal 2017/02/15 00:56:33 If there is rAF alongside a pending invalidation,
Khushal 2017/02/15 03:23:52 Okay. After offline discussion, removed this. We w
+}
+
+bool SchedulerStateMachine::CouldCreatePendingTree() const {
+ // Can't create a new pending tree till the current one is activated.
+ if (has_pending_tree_)
+ return false;
+
+ // Can't make frames while we're invisible.
+ if (!visible_)
+ return false;
+
+ // If the BeginFrameSource is paused, we will not be able to make any impl
+ // frames.
+ if (begin_frame_source_paused_)
+ return false;
+
+ // Don't create a pending tree till a frame sink is initialized.
+ if (!HasInitializedCompositorFrameSink())
+ return false;
+
+ return true;
+}
+
void SchedulerStateMachine::WillSendBeginMainFrame() {
DCHECK(!has_pending_tree_ || settings_.main_frame_before_activation_enabled);
DCHECK(visible_);
@@ -589,6 +690,15 @@ void SchedulerStateMachine::WillCommit(bool commit_has_no_updates) {
has_pending_tree_ = true;
pending_tree_is_ready_for_activation_ = false;
wait_for_ready_to_draw_ = settings_.commit_to_active_tree;
+
+ // If there was a commit, the impl-side invalidations will be merged with
+ // it.
+ WillRunImplSideInvalidationInternal();
+ } else if (needs_impl_side_invalidation_) {
+ // If the main frame is getting aborted, the impl-side updates will end up
+ // continuously waiting on a commit. In this case, prioritize these over
+ // the main frame.
+ impl_side_invalidations_take_priority_ = true;
sunnyps 2017/02/14 21:40:18 nit: you can use last_commit_had_no_updates_ inste
Khushal 2017/02/15 00:56:33 That flag gets reset on every BeginImplFrame, but
}
// Update state related to forced draws.
@@ -689,6 +799,10 @@ void SchedulerStateMachine::DidDraw(DrawResult draw_result) {
DidDrawInternal(draw_result);
}
+void SchedulerStateMachine::SetNeedsImplSideInvalidation() {
+ needs_impl_side_invalidation_ = true;
+}
+
void SchedulerStateMachine::AbortDraw() {
// Pretend like the draw was successful.
// Note: We may abort at any time and cannot DCHECK that
@@ -767,7 +881,8 @@ bool SchedulerStateMachine::BeginFrameRequiredForAction() const {
return true;
return needs_redraw_ || needs_one_begin_impl_frame_ ||
- (needs_begin_main_frame_ && !defer_commits_);
+ (needs_begin_main_frame_ && !defer_commits_) ||
+ needs_impl_side_invalidation_;
}
// These are cases where we are very likely want a BeginFrame message in the
@@ -827,6 +942,7 @@ void SchedulerStateMachine::OnBeginImplFrame() {
// Clear funnels for any actions we perform during the frame.
send_begin_main_frame_funnel_ = false;
invalidate_compositor_frame_sink_funnel_ = false;
+ impl_side_invalidation_funnel_ = false;
// "Drain" the PrepareTiles funnel.
if (prepare_tiles_funnel_ > 0)

Powered by Google App Engine
This is Rietveld 408576698