Chromium Code Reviews| Index: cc/scheduler/scheduler_state_machine.cc |
| diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc |
| index e73508ce1ab1fb198c9b69ff0e65609a3e637e8e..7dd14efabf8f04c31f96b583a0a4f62577e8cece 100644 |
| --- a/cc/scheduler/scheduler_state_machine.cc |
| +++ b/cc/scheduler/scheduler_state_machine.cc |
| @@ -42,9 +42,11 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) |
| last_frame_number_begin_main_frame_sent_(-1), |
| last_frame_number_invalidate_compositor_frame_sink_performed_(-1), |
| draw_funnel_(false), |
| - send_begin_main_frame_funnel_(true), |
| + did_send_begin_main_frame_for_current_frame_(true), |
| invalidate_compositor_frame_sink_funnel_(false), |
| impl_side_invalidation_funnel_(false), |
| + did_notify_begin_main_frame_not_sent_(false), |
| + did_commit_during_frame_(false), |
| prepare_tiles_funnel_(0), |
| consecutive_checkerboard_animations_(0), |
| pending_submit_frames_(0), |
| @@ -194,6 +196,8 @@ const char* SchedulerStateMachine::ActionToString(Action action) { |
| return "ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK"; |
| case ACTION_PERFORM_IMPL_SIDE_INVALIDATION: |
| return "ACTION_PERFORM_IMPL_SIDE_INVALIDATION"; |
| + case ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_SENT: |
| + return "ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_SENT"; |
| } |
| NOTREACHED(); |
| return "???"; |
| @@ -244,8 +248,12 @@ void SchedulerStateMachine::AsValueInto( |
| "last_begin_frame_sequence_number_compositor_frame_was_fresh", |
| last_begin_frame_sequence_number_compositor_frame_was_fresh_); |
| state->SetBoolean("funnel: draw_funnel", draw_funnel_); |
| - state->SetBoolean("funnel: send_begin_main_frame_funnel", |
| - send_begin_main_frame_funnel_); |
| + state->SetBoolean("funnel: did_send_begin_main_frame", |
| + did_send_begin_main_frame_for_current_frame_); |
| + state->SetBoolean("funnel: did_notify_begin_main_frame_not_sent", |
| + did_notify_begin_main_frame_not_sent_); |
| + state->SetBoolean("funnel: did_commit_during_frame", |
| + did_commit_during_frame_); |
| state->SetInteger("funnel: prepare_tiles_funnel", prepare_tiles_funnel_); |
| state->SetBoolean("funnel: invalidate_compositor_frame_sink_funnel", |
| invalidate_compositor_frame_sink_funnel_); |
| @@ -428,6 +436,39 @@ bool SchedulerStateMachine::ShouldActivatePendingTree() const { |
| return pending_tree_is_ready_for_activation_; |
| } |
| +bool SchedulerStateMachine::ShouldNotifyBeginMainFrameNotSent() const { |
| + // BeginMainFrame already triggers idle work, so we don't need to schedule |
|
Sami
2017/04/06 17:39:09
I'm wondering if we should rephrase all these comm
Dan Elphick
2017/04/07 09:05:02
I think you're right. I've phrased most of the com
|
| + // extra idle work here. |
| + if (needs_begin_main_frame_ || did_send_begin_main_frame_for_current_frame_) |
| + return false; |
| + |
| + // Only schedule extra idle work when we're visible. |
| + if (!visible_) |
| + return false; |
| + |
| + // There are no BeginImplFrames while BeginFrameSource is paused, |
| + // so should also stop scheduling extra idle work. |
| + if (begin_frame_source_paused_) |
| + return false; |
| + |
| + // Do not notify that no BeginMainFrame was sent too many times in a single |
| + // frame. |
| + if (did_notify_begin_main_frame_not_sent_) |
| + return false; |
| + |
| + // Do not notify if a commit happened during this frame as idle work will be |
| + // scheduled after that anyway. (This occurs if the main frame was scheduled |
| + // but didn't complete before the vsync deadline). |
| + if (did_commit_during_frame_) |
| + return false; |
| + |
| + // If a BeginMainFrame is in progress, don't do any extra idle work. |
| + if (begin_main_frame_state_ != BEGIN_MAIN_FRAME_STATE_IDLE) |
| + return false; |
| + |
| + return true; |
| +} |
| + |
| bool SchedulerStateMachine::CouldSendBeginMainFrame() const { |
| if (!needs_begin_main_frame_) |
| return false; |
| @@ -454,7 +495,7 @@ bool SchedulerStateMachine::ShouldSendBeginMainFrame() const { |
| // Do not send begin main frame too many times in a single frame or before |
| // the first BeginFrame. |
| - if (send_begin_main_frame_funnel_) |
| + if (did_send_begin_main_frame_for_current_frame_) |
| return false; |
| // Only send BeginMainFrame when there isn't another commit pending already. |
| @@ -598,6 +639,8 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { |
| return ACTION_INVALIDATE_COMPOSITOR_FRAME_SINK; |
| if (ShouldBeginCompositorFrameSinkCreation()) |
| return ACTION_BEGIN_COMPOSITOR_FRAME_SINK_CREATION; |
| + if (ShouldNotifyBeginMainFrameNotSent()) |
| + return ACTION_NOTIFY_BEGIN_MAIN_FRAME_NOT_SENT; |
| return ACTION_NONE; |
| } |
| @@ -683,15 +726,22 @@ void SchedulerStateMachine::WillSendBeginMainFrame() { |
| DCHECK(!has_pending_tree_ || settings_.main_frame_before_activation_enabled); |
| DCHECK(visible_); |
| DCHECK(!begin_frame_source_paused_); |
| - DCHECK(!send_begin_main_frame_funnel_); |
| + DCHECK(!did_send_begin_main_frame_for_current_frame_); |
| begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_SENT; |
| needs_begin_main_frame_ = false; |
| - send_begin_main_frame_funnel_ = true; |
| + did_send_begin_main_frame_for_current_frame_ = true; |
| last_frame_number_begin_main_frame_sent_ = current_frame_number_; |
| last_begin_frame_sequence_number_begin_main_frame_sent_ = |
| begin_frame_sequence_number_; |
| } |
| +void SchedulerStateMachine::WillNotifyBeginMainFrameNotSent() { |
| + DCHECK(visible_); |
| + DCHECK(!begin_frame_source_paused_); |
| + DCHECK(!did_notify_begin_main_frame_not_sent_); |
| + did_notify_begin_main_frame_not_sent_ = true; |
| +} |
| + |
| void SchedulerStateMachine::WillCommit(bool commit_has_no_updates) { |
| bool can_have_pending_tree = |
| commit_has_no_updates && |
| @@ -701,6 +751,7 @@ void SchedulerStateMachine::WillCommit(bool commit_has_no_updates) { |
| commit_count_++; |
| last_commit_had_no_updates_ = commit_has_no_updates; |
| begin_main_frame_state_ = BEGIN_MAIN_FRAME_STATE_IDLE; |
| + did_commit_during_frame_ = true; |
| if (commit_has_no_updates) { |
| // Pending tree might still exist from prior commit. |
| @@ -1047,7 +1098,9 @@ void SchedulerStateMachine::OnBeginImplFrame(uint32_t source_id, |
| needs_one_begin_impl_frame_ = false; |
| // Clear funnels for any actions we perform during the frame. |
| - send_begin_main_frame_funnel_ = false; |
| + did_notify_begin_main_frame_not_sent_ = false; |
| + did_send_begin_main_frame_for_current_frame_ = false; |
| + did_commit_during_frame_ = false; |
| invalidate_compositor_frame_sink_funnel_ = false; |
| impl_side_invalidation_funnel_ = false; |
| @@ -1085,7 +1138,7 @@ void SchedulerStateMachine::OnBeginImplFrameIdle() { |
| // If we're entering a state where we won't get BeginFrames set all the |
| // funnels so that we don't perform any actions that we shouldn't. |
| if (!BeginFrameNeeded()) |
| - send_begin_main_frame_funnel_ = true; |
| + did_send_begin_main_frame_for_current_frame_ = true; |
| // Synchronous compositor finishes BeginFrames before triggering their |
| // deadline. Therefore, we update sequence numbers when becoming idle, before |