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..f115815b1e3b38c849739662cfa8cca411df9991 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), |
+ run_impl_side_invalidation_after_main_frame_aborted_(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_RUN_IMPL_SIDE_INVALIDATION: |
+ return "ACTION_RUN_IMPL_SIDE_INVALIDATION"; |
} |
NOTREACHED(); |
return "???"; |
@@ -558,6 +563,8 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { |
return ACTION_PREPARE_TILES; |
if (ShouldSendBeginMainFrame()) |
return ACTION_SEND_BEGIN_MAIN_FRAME; |
+ if (ShouldRunImplSideInvalidation()) |
+ return ACTION_RUN_IMPL_SIDE_INVALIDATION; |
if (ShouldInvalidateCompositorFrameSink()) |
return ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK; |
if (ShouldBeginCompositorFrameSinkCreation()) |
@@ -565,6 +572,72 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { |
return ACTION_NONE; |
} |
+bool SchedulerStateMachine::ShouldRunImplSideInvalidation() 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_) |
Khushal
2017/01/31 02:04:41
May be this should get set after each commit, irre
|
+ return false; |
+ |
+ // Don't keep waiting on the main thread if the commits are being aborted. |
+ if (run_impl_side_invalidation_after_main_frame_aborted_) |
+ 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? |
+ 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_); |
+ |
+ needs_impl_side_invalidation_ = false; |
+ has_pending_tree_ = true; |
+ run_impl_side_invalidation_after_main_frame_aborted_ = false; |
+ 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; |
+ |
+ return true; |
+} |
+ |
void SchedulerStateMachine::WillSendBeginMainFrame() { |
DCHECK(!has_pending_tree_ || settings_.main_frame_before_activation_enabled); |
DCHECK(visible_); |
@@ -589,6 +662,13 @@ 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. |
+ if (needs_impl_side_invalidation_) |
+ WillRunImplSideInvalidation(); |
+ } else if (needs_impl_side_invalidation_) { |
+ run_impl_side_invalidation_after_main_frame_aborted_ = true; |
} |
// Update state related to forced draws. |
@@ -689,6 +769,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 +851,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 +912,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) |