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

Unified Diff: cc/scheduler/scheduler_state_machine.cc

Issue 23796002: cc: Implement deadine scheduling disabled by default (Closed) Base URL: http://git.chromium.org/chromium/src.git@schedReadback4
Patch Set: Fix context lost race conditions Created 7 years, 3 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 a608fb902c74864a3203db522e5f72f367a091eb..c76566ac622c9642d374fa3590af91c13f3e5454 100644
--- a/cc/scheduler/scheduler_state_machine.cc
+++ b/cc/scheduler/scheduler_state_machine.cc
@@ -14,21 +14,21 @@ namespace cc {
SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
: settings_(settings),
output_surface_state_(OUTPUT_SURFACE_LOST),
+ begin_frame_state_(BEGIN_FRAME_STATE_IDLE),
commit_state_(COMMIT_STATE_IDLE),
texture_state_(LAYER_TEXTURE_STATE_UNLOCKED),
forced_redraw_state_(FORCED_REDRAW_STATE_IDLE),
readback_state_(READBACK_STATE_IDLE),
commit_count_(0),
- current_frame_number_(0),
- last_frame_number_where_begin_frame_sent_to_main_thread_(-1),
- last_frame_number_swap_performed_(-1),
- last_frame_number_where_update_visible_tiles_was_called_(-1),
+ begin_frame_count_(0),
+ last_begin_frame_count_swap_performed_(-1),
+ last_begin_frame_count_begin_frame_sent_to_main_thread_(-1),
+ last_begin_frame_count_update_visible_tiles_was_called_(-1),
consecutive_failed_draws_(0),
needs_redraw_(false),
swap_used_incomplete_tile_(false),
needs_commit_(false),
main_thread_needs_layer_textures_(false),
- inside_begin_frame_(false),
visible_(false),
can_start_(false),
can_draw_(false),
@@ -56,6 +56,22 @@ const char* SchedulerStateMachine::OutputSurfaceStateToString(
return "???";
}
+const char* SchedulerStateMachine::BeginFrameStateToString(
+ BeginFrameState state) {
+ switch (state) {
+ case BEGIN_FRAME_STATE_IDLE:
+ return "BEGIN_FRAME_STATE_IDLE";
+ case BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME:
+ return "BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME";
+ case BEGIN_FRAME_STATE_DEADLINE_PENDING:
+ return "BEGIN_FRAME_STATE_DEADLINE_PENDING";
+ case BEGIN_FRAME_STATE_INSIDE_DEADLINE:
+ return "BEGIN_FRAME_STATE_INSIDE_DEADLINE";
+ }
+ NOTREACHED();
+ return "???";
+}
+
const char* SchedulerStateMachine::CommitStateToString(CommitState state) {
switch (state) {
case COMMIT_STATE_IDLE:
@@ -156,6 +172,8 @@ scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const {
scoped_ptr<base::DictionaryValue> major_state(new base::DictionaryValue);
major_state->SetString("next_action", ActionToString(NextAction()));
+ major_state->SetString("begin_frame_state",
+ BeginFrameStateToString(begin_frame_state_));
major_state->SetString("commit_state", CommitStateToString(commit_state_));
major_state->SetString("texture_state_",
TextureStateToString(texture_state_));
@@ -197,16 +215,18 @@ scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const {
scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue);
minor_state->SetInteger("commit_count", commit_count_);
- minor_state->SetInteger("current_frame_number", current_frame_number_);
+ minor_state->SetInteger("begin_frame_count_", begin_frame_count_);
+
+ minor_state->SetInteger("last_begin_frame_count_swap_performed_",
+ last_begin_frame_count_swap_performed_);
minor_state->SetInteger(
- "last_frame_number_where_begin_frame_sent_to_main_thread",
- last_frame_number_where_begin_frame_sent_to_main_thread_);
- minor_state->SetInteger("last_frame_number_swap_performed_",
- last_frame_number_swap_performed_);
+ "last_begin_frame_count_begin_frame_sent_to_main_thread_",
+ last_begin_frame_count_begin_frame_sent_to_main_thread_);
minor_state->SetInteger(
- "last_frame_number_where_update_visible_tiles_was_called",
- last_frame_number_where_update_visible_tiles_was_called_);
- minor_state->SetInteger("consecutive_failed_draws",
+ "last_begin_frame_count_update_visible_tiles_was_called_",
+ last_begin_frame_count_update_visible_tiles_was_called_);
+
+ minor_state->SetInteger("consecutive_failed_draws_",
consecutive_failed_draws_);
minor_state->SetBoolean("needs_redraw", needs_redraw_);
minor_state->SetBoolean("swap_used_incomplete_tile",
@@ -214,7 +234,6 @@ scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const {
minor_state->SetBoolean("needs_commit", needs_commit_);
minor_state->SetBoolean("main_thread_needs_layer_textures",
main_thread_needs_layer_textures_);
- minor_state->SetBoolean("inside_begin_frame", inside_begin_frame_);
minor_state->SetBoolean("visible", visible_);
minor_state->SetBoolean("can_start", can_start_);
minor_state->SetBoolean("can_draw", can_draw_);
@@ -231,18 +250,18 @@ scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const {
return state.PassAs<base::Value>();
}
-bool SchedulerStateMachine::HasDrawnAndSwappedThisFrame() const {
- return current_frame_number_ == last_frame_number_swap_performed_;
+bool SchedulerStateMachine::HasSentBeginFrameToMainThreadThisFrame() const {
+ return begin_frame_count_ ==
+ last_begin_frame_count_begin_frame_sent_to_main_thread_;
}
bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const {
- return current_frame_number_ ==
- last_frame_number_where_update_visible_tiles_was_called_;
+ return begin_frame_count_ ==
+ last_begin_frame_count_update_visible_tiles_was_called_;
}
-bool SchedulerStateMachine::HasSentBeginFrameToMainThreadThisFrame() const {
- return current_frame_number_ ==
- last_frame_number_where_begin_frame_sent_to_main_thread_;
+bool SchedulerStateMachine::HasSwappedThisFrame() const {
+ return begin_frame_count_ == last_begin_frame_count_swap_performed_;
}
bool SchedulerStateMachine::PendingDrawsShouldBeAborted() const {
@@ -325,12 +344,12 @@ bool SchedulerStateMachine::ShouldDraw() const {
if (PendingDrawsShouldBeAborted())
return active_tree_needs_first_draw_;
- // After this line, we only want to draw once per frame.
- if (HasDrawnAndSwappedThisFrame())
+ // After this line, we only want to swap once per frame.
+ if (HasSwappedThisFrame())
return false;
- // We currently only draw within the BeginFrame.
- if (!inside_begin_frame_)
+ // Except for the cases above, do not draw outside of the BeginFrame deadline.
+ if (begin_frame_state_ != BEGIN_FRAME_STATE_INSIDE_DEADLINE)
return false;
// Only handle forced redraws due to timeouts on the regular deadline.
@@ -380,10 +399,10 @@ bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const {
if (!HasInitializedOutputSurface())
return false;
- // We always want to update the most recent visible tiles before drawing
- // so we draw with fewer missing tiles.
- if (ShouldDraw())
- return true;
+ // We should not check for visible tiles until we've entered the deadline so
+ // we check as late possible and give the tiles more time to initialize.
+ if (begin_frame_state_ != BEGIN_FRAME_STATE_INSIDE_DEADLINE)
+ return false;
// If the last swap drew with checkerboard or missing tiles, we should
// poll for any new visible tiles so we can be notified to draw again
@@ -414,14 +433,25 @@ bool SchedulerStateMachine::ShouldSendBeginFrameToMainThread() const {
return !CommitPending();
// We do not need commits if we are not visible, unless there's a
- // request for a forced commit.
+ // request for a readback.
if (!visible_)
return false;
+ // We shouldn't normally accept commits if there isn't an OutputSurface.
+ if (!HasInitializedOutputSurface())
+ return false;
+
// We want to start the first commit after we get a new output surface ASAP.
if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT)
return true;
+ // We should not send the BeginFrame to the main thread while we are in
+ // BEGIN_FRAME_STATE_IDLE since we might have new user input coming in soon.
+ // TODO(brianderson): Also allow sending BeginFrame to main thread while idle
+ // when the main thread isn't consuming user input.
+ if (begin_frame_state_ == BEGIN_FRAME_STATE_IDLE)
+ return false;
+
// We need a new commit for the forced redraw. This honors the
// single commit per interval because the result will be swapped to screen.
if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT)
@@ -431,10 +461,6 @@ bool SchedulerStateMachine::ShouldSendBeginFrameToMainThread() const {
if (HasSentBeginFrameToMainThreadThisFrame())
return false;
- // We shouldn't normally accept commits if there isn't an OutputSurface.
- if (!HasInitializedOutputSurface())
- return false;
-
return true;
}
@@ -481,8 +507,8 @@ void SchedulerStateMachine::UpdateState(Action action) {
return;
case ACTION_UPDATE_VISIBLE_TILES:
- last_frame_number_where_update_visible_tiles_was_called_ =
- current_frame_number_;
+ last_begin_frame_count_update_visible_tiles_was_called_ =
+ begin_frame_count_;
return;
case ACTION_ACTIVATE_PENDING_TREE:
@@ -496,8 +522,8 @@ void SchedulerStateMachine::UpdateState(Action action) {
needs_commit_ = false;
if (readback_state_ == READBACK_STATE_NEEDS_BEGIN_FRAME)
readback_state_ = READBACK_STATE_WAITING_FOR_COMMIT;
- last_frame_number_where_begin_frame_sent_to_main_thread_ =
- current_frame_number_;
+ last_begin_frame_count_begin_frame_sent_to_main_thread_ =
+ begin_frame_count_;
return;
case ACTION_COMMIT: {
@@ -610,8 +636,9 @@ void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) {
// This post-commit work is common to both completed and aborted commits.
pending_tree_is_ready_for_activation_ = false;
- if (draw_if_possible_failed_)
- last_frame_number_swap_performed_ = -1;
+ if (draw_if_possible_failed_) {
+ last_begin_frame_count_swap_performed_ = -1;
+ }
// If we are planing to draw with the new commit, lock the layer textures for
// use on the impl thread. Otherwise, leave them unlocked.
@@ -674,7 +701,7 @@ void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) {
active_tree_needs_first_draw_ = false;
if (did_swap)
- last_frame_number_swap_performed_ = current_frame_number_;
+ last_begin_frame_count_swap_performed_ = begin_frame_count_;
}
void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() {
@@ -683,6 +710,11 @@ void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() {
main_thread_needs_layer_textures_ = true;
}
+bool SchedulerStateMachine::BeginFrameNeededByImplThread() const {
+ return BeginFrameNeededToDrawByImplThread() ||
+ ProactiveBeginFrameWantedByImplThread();
+}
+
// These are the cases where we definitely (or almost definitely) have a
// new frame to draw and can draw.
bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const {
@@ -717,15 +749,22 @@ bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const {
// actually have a new frame to draw when we receive the next BeginFrame.
// Proactively requesting the BeginFrame helps hide the round trip latency of
// the SetNeedsBeginFrame request that has to go to the Browser.
-// However, this is bad for the synchronous compositor because we have to
-// draw when we get the BeginFrame and could end up drawing many duplicate
-// frames.
bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const {
// The output surface is the provider of BeginFrames for the impl thread,
// so we are not going to get them even if we ask for them.
if (!HasInitializedOutputSurface())
return false;
+ // 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.
+ if (settings_.using_synchronous_renderer_compositor)
+ return false;
+
+ // Do not be proactive if vsync is off.
+ if (!settings_.throttle_frame_production)
+ return false;
+
// Do not be proactive when invisible.
if (!visible_)
return false;
@@ -743,18 +782,49 @@ bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const {
return false;
}
-void SchedulerStateMachine::DidEnterBeginFrame(const BeginFrameArgs& args) {
- current_frame_number_++;
- inside_begin_frame_ = true;
+void SchedulerStateMachine::OnBeginFrame(const BeginFrameArgs& args) {
+ begin_frame_count_++;
last_begin_frame_args_ = args;
+ DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_IDLE)
+ << *AsValue();
+ begin_frame_state_ = BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME;
}
-void SchedulerStateMachine::DidLeaveBeginFrame() {
- inside_begin_frame_ = false;
+void SchedulerStateMachine::OnBeginFrameDeadlinePending() {
enne (OOO) 2013/09/11 22:30:47 These functions make things a lot more clear!
+ DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME)
+ << *AsValue();
+ begin_frame_state_ = BEGIN_FRAME_STATE_DEADLINE_PENDING;
+}
+
+void SchedulerStateMachine::OnBeginFrameDeadline() {
+ DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_DEADLINE_PENDING)
+ << *AsValue();
+ begin_frame_state_ = BEGIN_FRAME_STATE_INSIDE_DEADLINE;
+}
+
+void SchedulerStateMachine::OnBeginFrameIdle() {
+ if (HasInitializedOutputSurface()) {
+ DCHECK_EQ(begin_frame_state_, BEGIN_FRAME_STATE_INSIDE_DEADLINE)
+ << *AsValue();
+ }
+ begin_frame_state_ = BEGIN_FRAME_STATE_IDLE;
+}
+
+bool SchedulerStateMachine::ShouldTriggerBeginFrameDeadlineEarly() const {
+ // TODO(brianderson): This should take into account multiple commit sources.
+ return begin_frame_state_ == BEGIN_FRAME_STATE_DEADLINE_PENDING &&
+ active_tree_needs_first_draw_;
+}
+
+bool SchedulerStateMachine::InsideBeginFrame() const {
enne (OOO) 2013/09/11 22:30:47 What does "inside begin frame" mean here if this f
brianderson 2013/09/12 00:12:34 I'll need to fix the naming. "Inside BeginFrame" i
+ return begin_frame_state_ == BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME ||
+ begin_frame_state_ == BEGIN_FRAME_STATE_DEADLINE_PENDING;
}
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::SetSwapUsedIncompleteTile(
@@ -827,6 +897,7 @@ void SchedulerStateMachine::DidLoseOutputSurface() {
return;
output_surface_state_ = OUTPUT_SURFACE_LOST;
needs_redraw_ = false;
+ begin_frame_state_ = BEGIN_FRAME_STATE_IDLE;
}
void SchedulerStateMachine::NotifyReadyToActivate() {
@@ -834,8 +905,6 @@ void SchedulerStateMachine::NotifyReadyToActivate() {
pending_tree_is_ready_for_activation_ = true;
}
-void SchedulerStateMachine::SetCanDraw(bool can) { can_draw_ = can; }
-
void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING);
output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT;

Powered by Google App Engine
This is Rietveld 408576698