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

Unified Diff: cc/scheduler/scheduler_state_machine.cc

Issue 817603002: cc: Make scheduling be driven by vsync for android webview. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years 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 dc3fa3643aaa9096b92abf0955e45889149d4d71..81c54ab27ca4a58bca0c847544a3aca29f88f6de 100644
--- a/cc/scheduler/scheduler_state_machine.cc
+++ b/cc/scheduler/scheduler_state_machine.cc
@@ -26,6 +26,7 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
last_frame_number_swap_performed_(-1),
last_frame_number_swap_requested_(-1),
last_frame_number_begin_main_frame_sent_(-1),
+ last_frame_number_invalidate_output_surface_performed_(-1),
prepare_tiles_funnel_(0),
consecutive_checkerboard_animations_(0),
max_pending_swaps_(1),
@@ -34,7 +35,6 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
needs_animate_(false),
needs_prepare_tiles_(false),
needs_commit_(false),
- inside_poll_for_anticipated_draw_triggers_(false),
visible_(false),
can_start_(false),
can_draw_(false),
@@ -48,7 +48,8 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
skip_begin_main_frame_to_reduce_latency_(false),
continuous_painting_(false),
impl_latency_takes_priority_on_battery_(false),
- children_need_begin_frames_(false) {
+ children_need_begin_frames_(false),
+ output_surface_did_request_draw_(false) {
}
const char* SchedulerStateMachine::OutputSurfaceStateToString(
@@ -85,6 +86,22 @@ const char* SchedulerStateMachine::BeginImplFrameStateToString(
return "???";
}
+const char* SchedulerStateMachine::BeginImplFrameDeadlineModeToString(
+ BeginImplFrameDeadlineMode mode) {
+ switch (mode) {
+ case BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_SYNCHRONOUS:
+ return "BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_SYNCHRONOUS";
+ case BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_ASYNCHRONOUS:
+ return "BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_ASYNCHRONOUS";
+ case BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR:
+ return "BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR";
+ case BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE:
+ return "BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE";
+ }
+ NOTREACHED();
+ return "???";
+}
+
const char* SchedulerStateMachine::CommitStateToString(CommitState state) {
switch (state) {
case COMMIT_STATE_IDLE:
@@ -142,6 +159,8 @@ const char* SchedulerStateMachine::ActionToString(Action action) {
return "ACTION_BEGIN_OUTPUT_SURFACE_CREATION";
case ACTION_PREPARE_TILES:
return "ACTION_PREPARE_TILES";
+ case ACTION_INVALIDATE_OUTPUT_SURFACE:
+ return "ACTION_INVALIDATE_OUTPUT_SURFACE";
}
NOTREACHED();
return "???";
@@ -270,6 +289,10 @@ bool SchedulerStateMachine::HasRequestedSwapThisFrame() const {
return current_frame_number_ == last_frame_number_swap_requested_;
}
+bool SchedulerStateMachine::HasInvalidatedOutputSurfaceThisFrame() const {
+ return current_frame_number_ == last_frame_number_invalidate_output_surface_performed_;
+}
+
bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const {
// These are all the cases where we normally cannot or do not want to draw
// but, if needs_redraw_ is true and we do not draw to make forward progress,
@@ -334,6 +357,12 @@ bool SchedulerStateMachine::ShouldBeginOutputSurfaceCreation() const {
}
bool SchedulerStateMachine::ShouldDraw() const {
+ // In the synchronous compositor mode, draws are initiated by the output
+ // surface only.
+ if (settings_.using_synchronous_renderer_compositor &&
+ !output_surface_did_request_draw_)
+ return false;
+
// If we need to abort draws, we should do so ASAP since the draw could
// be blocking other important actions (like output surface initialization),
// from occuring. If we are waiting for the first draw, then perfom the
@@ -489,14 +518,30 @@ bool SchedulerStateMachine::ShouldPrepareTiles() const {
return false;
// Limiting to once per-frame is not enough, since we only want to
- // prepare tiles _after_ draws. Polling for draw triggers and
- // begin-frame are mutually exclusive, so we limit to these two cases.
- if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE &&
- !inside_poll_for_anticipated_draw_triggers_)
+ // prepare tiles _after_ draws.
+ if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
return false;
+
return needs_prepare_tiles_;
}
+bool SchedulerStateMachine::ShouldInvalidateOutputSurface() const {
+ // Only the synchronous compositor requires invalidations.
+ if (!settings_.using_synchronous_renderer_compositor)
+ return false;
+
+ // Invalidations are only performed inside a BeginFrame excluding deadline.
+ if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING &&
+ begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
+ return false;
+
+ // Invalidate the output surface only once per frame.
+ if (HasInvalidatedOutputSurfaceThisFrame())
+ return false;
+
+ return needs_redraw_;
+}
+
SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
if (ShouldActivatePendingTree())
return ACTION_ACTIVATE_SYNC_TREE;
@@ -516,6 +561,8 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
return ACTION_PREPARE_TILES;
if (ShouldSendBeginMainFrame())
return ACTION_SEND_BEGIN_MAIN_FRAME;
+ if (ShouldInvalidateOutputSurface())
+ return ACTION_INVALIDATE_OUTPUT_SURFACE;
if (ShouldBeginOutputSurfaceCreation())
return ACTION_BEGIN_OUTPUT_SURFACE_CREATION;
return ACTION_NONE;
@@ -557,6 +604,9 @@ void SchedulerStateMachine::UpdateState(Action action) {
case ACTION_DRAW_AND_SWAP_FORCED:
case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: {
+ // Synchronous compositor only draws when requested.
+ DCHECK_IMPLIES(settings_.using_synchronous_renderer_compositor,
+ output_surface_did_request_draw_);
bool did_request_swap = true;
UpdateStateOnDraw(did_request_swap);
return;
@@ -583,6 +633,10 @@ void SchedulerStateMachine::UpdateState(Action action) {
case ACTION_PREPARE_TILES:
UpdateStateOnPrepareTiles();
return;
+
+ case ACTION_INVALIDATE_OUTPUT_SURFACE:
+ last_frame_number_invalidate_output_surface_performed_ = current_frame_number_;
+ return;
}
}
@@ -668,6 +722,7 @@ void SchedulerStateMachine::UpdateStateOnDraw(bool did_request_swap) {
needs_redraw_ = false;
active_tree_needs_first_draw_ = false;
+ output_surface_did_request_draw_ = false;
if (did_request_swap)
last_frame_number_swap_requested_ = current_frame_number_;
@@ -692,43 +747,9 @@ bool SchedulerStateMachine::BeginFrameNeededForChildren() const {
}
bool SchedulerStateMachine::BeginFrameNeeded() const {
- if (SupportsProactiveBeginFrame()) {
- return (BeginFrameNeededToAnimateOrDraw() ||
- BeginFrameNeededForChildren() ||
- ProactiveBeginFrameWanted());
- }
-
- // Proactive BeginFrames are bad for the synchronous compositor because we
- // have to draw when we get the BeginFrame and could end up drawing many
- // duplicate frames if our new frame isn't ready in time.
- // To poll for state with the synchronous compositor without having to draw,
- // we rely on ShouldPollForAnticipatedDrawTriggers instead.
- // Synchronous compositor doesn't have a browser.
- DCHECK(!children_need_begin_frames_);
- return BeginFrameNeededToAnimateOrDraw();
-}
-
-bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const {
- // ShouldPollForAnticipatedDrawTriggers is what we use in place of
- // ProactiveBeginFrameWanted when we are using the synchronous
- // compositor.
- if (!SupportsProactiveBeginFrame()) {
- return !BeginFrameNeededToAnimateOrDraw() && ProactiveBeginFrameWanted();
- }
-
- // Non synchronous compositors should rely on
- // ProactiveBeginFrameWanted to poll for state instead.
- return false;
-}
-
-// Note: If SupportsProactiveBeginFrame is false, the scheduler should poll
-// for changes in it's draw state so it can request a BeginFrame when it's
-// actually ready.
-bool SchedulerStateMachine::SupportsProactiveBeginFrame() const {
- // It is undesirable to proactively request BeginFrames if we are
- // using a synchronous compositor because we *must* draw for every
- // BeginFrame, which could cause duplicate draws.
- return !settings_.using_synchronous_renderer_compositor;
+ return (BeginFrameNeededToAnimateOrDraw() ||
+ BeginFrameNeededForChildren() ||
+ ProactiveBeginFrameWanted());
}
void SchedulerStateMachine::SetChildrenNeedBeginFrames(
@@ -822,8 +843,13 @@ void SchedulerStateMachine::OnBeginImplFrameIdle() {
SchedulerStateMachine::BeginImplFrameDeadlineMode
SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const {
- if (ShouldTriggerBeginImplFrameDeadlineImmediately()) {
- return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE;
+ if (settings_.using_synchronous_renderer_compositor &&
+ output_surface_did_request_draw_) {
+ // If the synchronous compositor wants to draw now or if we know that the
+ // synchronous compositor won't draw trigger an immediate deadline.
+ return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_SYNCHRONOUS;
+ } else if (ShouldTriggerBeginImplFrameDeadlineImmediately()) {
+ return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE_ASYNCHRONOUS;
} else if (needs_redraw_ && pending_swaps_ < max_pending_swaps_) {
// We have an animation or fast input path on the impl thread that wants
// to draw, so don't wait too long for a new active tree.
@@ -840,6 +866,14 @@ SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const {
bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately()
const {
// TODO(brianderson): This should take into account multiple commit sources.
+
+ // Set an immediate asynchronous deadline for the synchronous compositor.
+ // If the output surface was invalidated, then the synchronous compositor will
+ // cause the deadline to be rescheduled on OutputSurfaceDidRequestDraw.
+ // If the output surface was not invalidated (i.e. needs_redraw_ is false)
+ // then the deadline will pass but drawing will not happen.
+ if (settings_.using_synchronous_renderer_compositor)
+ return true;
if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
return false;
@@ -920,21 +954,16 @@ bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const {
return active_tree_needs_first_draw_;
}
-void SchedulerStateMachine::DidEnterPollForAnticipatedDrawTriggers() {
- AdvanceCurrentFrameNumber();
- inside_poll_for_anticipated_draw_triggers_ = true;
-}
-
-void SchedulerStateMachine::DidLeavePollForAnticipatedDrawTriggers() {
- inside_poll_for_anticipated_draw_triggers_ = false;
-}
-
void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }
void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }
void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }
+void SchedulerStateMachine::OutputSurfaceDidRequestDraw() {
+ output_surface_did_request_draw_ = true;
+}
+
void SchedulerStateMachine::SetNeedsAnimate() {
needs_animate_ = true;
}

Powered by Google App Engine
This is Rietveld 408576698