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

Unified Diff: cc/scheduler/scheduler_state_machine.cc

Issue 2659123004: cc: Add scheduler support for invalidating content on impl thread. (Closed)
Patch Set: no DCHECK 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
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..4ca6d431a82fa6a47d6408b707360c7aae0fb01b 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,10 @@ 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),
+ previous_pending_tree_was_impl_side_(false),
+ current_pending_tree_is_impl_side_(false) {}
const char* SchedulerStateMachine::CompositorFrameSinkStateToString(
CompositorFrameSinkState state) {
@@ -177,6 +181,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 +226,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 +263,8 @@ 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->EndDictionary();
}
@@ -554,6 +564,8 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
else
return ACTION_DRAW_IF_POSSIBLE;
}
+ if (ShouldPerformImplSideInvalidation())
+ return ACTION_PERFORM_IMPL_SIDE_INVALIDATION;
if (ShouldPrepareTiles())
return ACTION_PREPARE_TILES;
if (ShouldSendBeginMainFrame())
@@ -565,6 +577,82 @@ 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())) {
+ return false;
+ }
+
+ // If we are inside the deadline and an impl-side invalidation request is
+ // still pending, do it now. We restrict performing impl-side invalidations
+ // until the deadline to give the main thread a chance to respond to a sent
+ // BeginMainFrame. If the main thread responds with a commit, we know the
+ // invalidations will have been merged with the main frame.
+ // If the commit was aborted, or the main thread fails to respond within the
+ // deadline, then we create a pending tree for impl-side invalidations now.
+ // This also checks to make sure that the |prepare_tiles_funnel_| is not full,
+ // since impl-side invalidations will cause a PrepareTiles.
+ if (begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE &&
+ prepare_tiles_funnel_ == 0) {
+ return true;
+ }
+
+ // Wait till the deadline to perform impl-side invalidations.
+ return false;
+}
+
+void SchedulerStateMachine::WillPerformImplSideInvalidation() {
+ current_pending_tree_is_impl_side_ = true;
+ WillPerformImplSideInvalidationInternal();
+}
+
+void SchedulerStateMachine::WillPerformImplSideInvalidationInternal() {
+ DCHECK(needs_impl_side_invalidation_);
+ DCHECK(!has_pending_tree_);
+
+ needs_impl_side_invalidation_ = false;
+ has_pending_tree_ = true;
+ impl_side_invalidation_funnel_ = true;
+}
+
+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_);
@@ -585,6 +673,15 @@ void SchedulerStateMachine::WillCommit(bool commit_has_no_updates) {
begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_IDLE;
if (!commit_has_no_updates) {
+ // If there was a commit, the impl-side invalidations will be merged with
+ // it. We always fill the impl-side invalidation funnel here, even if no
+ // request was currently pending, to defer creating another pending tree and
+ // performing PrepareTiles until the next frame, in case the invalidation
+ // request is received after the commit.
+ if (needs_impl_side_invalidation_)
+ WillPerformImplSideInvalidationInternal();
+ impl_side_invalidation_funnel_ = true;
+
// Pending tree only exists if commit had updates.
has_pending_tree_ = true;
pending_tree_is_ready_for_activation_ = false;
@@ -619,6 +716,9 @@ void SchedulerStateMachine::WillActivate() {
pending_tree_is_ready_for_activation_ = false;
active_tree_needs_first_draw_ = true;
needs_redraw_ = true;
+
+ previous_pending_tree_was_impl_side_ = current_pending_tree_is_impl_side_;
+ current_pending_tree_is_impl_side_ = false;
}
void SchedulerStateMachine::WillDrawInternal() {
@@ -689,6 +789,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 +871,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 +932,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)
« 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