Chromium Code Reviews| Index: cc/scheduler/scheduler.cc |
| diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc |
| index e2a531fc04975334761aafa63bde2401c1748a40..01ce0aaf5298d530db9c018cdd3c38f6a90f28ff 100644 |
| --- a/cc/scheduler/scheduler.cc |
| +++ b/cc/scheduler/scheduler.cc |
| @@ -64,8 +64,6 @@ Scheduler::Scheduler( |
| DCHECK(client_); |
| DCHECK(!state_machine_.BeginFrameNeeded()); |
| - begin_retro_frame_closure_ = |
| - base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); |
| begin_impl_frame_deadline_closure_ = base::Bind( |
| &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); |
| @@ -202,8 +200,6 @@ void Scheduler::DidPrepareTiles() { |
| void Scheduler::DidLoseOutputSurface() { |
| TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); |
| - begin_retro_frame_args_.clear(); |
| - begin_retro_frame_task_.Cancel(); |
| state_machine_.DidLoseOutputSurface(); |
| UpdateCompositorTimingHistoryRecordingEnabled(); |
| ProcessScheduledActions(); |
| @@ -261,8 +257,6 @@ void Scheduler::SetupNextBeginFrameIfNeeded() { |
| false); |
| } |
| } |
| - |
| - PostBeginRetroFrameIfNeeded(); |
| } |
| void Scheduler::OnBeginFrameSourcePausedChanged(bool paused) { |
| @@ -274,11 +268,19 @@ void Scheduler::OnBeginFrameSourcePausedChanged(bool paused) { |
| ProcessScheduledActions(); |
| } |
| +const BeginFrameArgs& Scheduler::LastUsedBeginFrameArgs() const { |
| + return begin_impl_frame_tracker_.DangerousMethodCurrentOrLast(); |
| +} |
| + |
| // BeginFrame is the mechanism that tells us that now is a good time to start |
| // making a frame. Usually this means that user input for the frame is complete. |
| -// If the scheduler is busy, we queue the BeginFrame to be handled later as |
| -// a BeginRetroFrame. |
| -bool Scheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { |
| +void Scheduler::OnBeginFrame(const BeginFrameArgs& args) { |
| + if (!observing_begin_frame_source_ || |
| + state_machine_.begin_impl_frame_state() != |
| + SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) { |
| + return; |
| + } |
| + |
| TRACE_EVENT1("cc,benchmark", "Scheduler::BeginFrame", "args", args.AsValue()); |
| // Trace this begin frame time through the Chrome stack |
| @@ -297,35 +299,9 @@ bool Scheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { |
| if (settings_.using_synchronous_renderer_compositor) { |
| BeginImplFrameSynchronous(adjusted_args); |
| - return true; |
| - } |
| - |
| - // We have just called SetNeedsBeginFrame(true) and the BeginFrameSource has |
| - // sent us the last BeginFrame we have missed. As we might not be able to |
| - // actually make rendering for this call, handle it like a "retro frame". |
| - // TODO(brainderson): Add a test for this functionality ASAP! |
| - if (adjusted_args.type == BeginFrameArgs::MISSED) { |
|
enne (OOO)
2016/04/18 21:30:38
The removal of this might break https://codereview
|
| - begin_retro_frame_args_.push_back(adjusted_args); |
| - PostBeginRetroFrameIfNeeded(); |
| - return true; |
| - } |
| - |
| - bool should_defer_begin_frame = |
| - !begin_retro_frame_args_.empty() || |
| - !begin_retro_frame_task_.IsCancelled() || |
| - !observing_begin_frame_source_ || |
| - (state_machine_.begin_impl_frame_state() != |
| - SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
| - |
| - if (should_defer_begin_frame) { |
| - begin_retro_frame_args_.push_back(adjusted_args); |
| - TRACE_EVENT_INSTANT0( |
| - "cc", "Scheduler::BeginFrame deferred", TRACE_EVENT_SCOPE_THREAD); |
| - // Queuing the frame counts as "using it", so we need to return true. |
| } else { |
| BeginImplFrameWithDeadline(adjusted_args); |
| } |
| - return true; |
| } |
| void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) { |
| @@ -353,80 +329,6 @@ void Scheduler::OnDrawForOutputSurface(bool resourceless_software_draw) { |
| state_machine_.SetResourcelessSoftareDraw(false); |
| } |
| -// BeginRetroFrame is called for BeginFrames that we've deferred because |
| -// the scheduler was in the middle of processing a previous BeginFrame. |
| -void Scheduler::BeginRetroFrame() { |
| - TRACE_EVENT0("cc,benchmark", "Scheduler::BeginRetroFrame"); |
| - DCHECK(!settings_.using_synchronous_renderer_compositor); |
| - DCHECK(!begin_retro_frame_args_.empty()); |
| - DCHECK(!begin_retro_frame_task_.IsCancelled()); |
| - DCHECK_EQ(state_machine_.begin_impl_frame_state(), |
| - SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
| - |
| - begin_retro_frame_task_.Cancel(); |
| - |
| - // Discard expired BeginRetroFrames |
| - // Today, we should always end up with at most one un-expired BeginRetroFrame |
| - // because deadlines will not be greater than the next frame time. We don't |
| - // DCHECK though because some systems don't always have monotonic timestamps. |
| - // TODO(brianderson): In the future, long deadlines could result in us not |
| - // draining the queue if we don't catch up. If we consistently can't catch |
| - // up, our fallback should be to lower our frame rate. |
| - base::TimeTicks now = Now(); |
| - |
| - while (!begin_retro_frame_args_.empty()) { |
| - const BeginFrameArgs& args = begin_retro_frame_args_.front(); |
| - base::TimeTicks expiration_time = args.deadline; |
| - if (now <= expiration_time) |
| - break; |
| - TRACE_EVENT_INSTANT2( |
| - "cc", "Scheduler::BeginRetroFrame discarding", TRACE_EVENT_SCOPE_THREAD, |
| - "expiration_time - now", (expiration_time - now).InMillisecondsF(), |
| - "BeginFrameArgs", begin_retro_frame_args_.front().AsValue()); |
| - begin_retro_frame_args_.pop_front(); |
| - if (begin_frame_source_) |
| - begin_frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); |
| - } |
| - |
| - if (begin_retro_frame_args_.empty()) { |
| - TRACE_EVENT_INSTANT0("cc", |
| - "Scheduler::BeginRetroFrames all expired", |
| - TRACE_EVENT_SCOPE_THREAD); |
| - } else { |
| - BeginFrameArgs front = begin_retro_frame_args_.front(); |
| - begin_retro_frame_args_.pop_front(); |
| - BeginImplFrameWithDeadline(front); |
| - } |
| -} |
| - |
| -// There could be a race between the posted BeginRetroFrame and a new |
| -// BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame |
| -// will check if there is a pending BeginRetroFrame to ensure we handle |
| -// BeginFrames in FIFO order. |
| -void Scheduler::PostBeginRetroFrameIfNeeded() { |
| - TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
| - "Scheduler::PostBeginRetroFrameIfNeeded", |
| - "state", |
| - AsValue()); |
| - if (!observing_begin_frame_source_) |
| - return; |
| - |
| - if (begin_retro_frame_args_.empty() || !begin_retro_frame_task_.IsCancelled()) |
| - return; |
| - |
| - // begin_retro_frame_args_ should always be empty for the |
| - // synchronous compositor. |
| - DCHECK(!settings_.using_synchronous_renderer_compositor); |
| - |
| - if (state_machine_.begin_impl_frame_state() != |
| - SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) |
| - return; |
| - |
| - begin_retro_frame_task_.Reset(begin_retro_frame_closure_); |
| - |
| - task_runner_->PostTask(FROM_HERE, begin_retro_frame_task_.callback()); |
| -} |
| - |
| void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) { |
| bool main_thread_is_in_high_latency_mode = |
| state_machine_.main_thread_missed_last_deadline(); |
| @@ -478,16 +380,10 @@ void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) { |
| can_activate_before_deadline)) { |
| TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency", |
| TRACE_EVENT_SCOPE_THREAD); |
| - if (begin_frame_source_) |
| - begin_frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); |
| return; |
| } |
| BeginImplFrame(adjusted_args); |
| - |
| - // The deadline will be scheduled in ProcessScheduledActions. |
| - state_machine_.OnBeginImplFrameDeadlinePending(); |
| - ProcessScheduledActions(); |
| } |
| void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { |
| @@ -510,10 +406,12 @@ void Scheduler::FinishImplFrame() { |
| state_machine_.OnBeginImplFrameIdle(); |
| ProcessScheduledActions(); |
| + begin_impl_frame_tracker_.Finish(); |
| + |
| client_->DidFinishImplFrame(); |
| + |
| if (begin_frame_source_) |
| - begin_frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); |
| - begin_impl_frame_tracker_.Finish(); |
| + begin_frame_source_->DidFinishFrame(this); |
| } |
| // BeginImplFrame starts a compositor frame that will wait up until a deadline |
| @@ -661,85 +559,85 @@ void Scheduler::SetDeferCommits(bool defer_commits) { |
| void Scheduler::ProcessScheduledActions() { |
| // We do not allow ProcessScheduledActions to be recursive. |
| // The top-level call will iteratively execute the next action for us anyway. |
| - if (inside_process_scheduled_actions_) |
| - return; |
| + if (!inside_process_scheduled_actions_) { |
| + base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); |
| + SchedulerStateMachine::Action action; |
| + do { |
| + action = state_machine_.NextAction(); |
| + PerformAction(action); |
| + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
| + "SchedulerStateMachine", "state", AsValue()); |
| + } while (action != SchedulerStateMachine::ACTION_NONE); |
| + } |
| + SetupNextBeginFrameIfNeeded(); |
| + ScheduleBeginImplFrameDeadlineIfNeeded(); |
| +} |
| - base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); |
| - |
| - SchedulerStateMachine::Action action; |
| - do { |
| - action = state_machine_.NextAction(); |
| - TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
| - "SchedulerStateMachine", |
| - "state", |
| - AsValue()); |
| - base::AutoReset<SchedulerStateMachine::Action> |
| - mark_inside_action(&inside_action_, action); |
| - switch (action) { |
| - case SchedulerStateMachine::ACTION_NONE: |
| - break; |
| - case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME: |
| - compositor_timing_history_->WillBeginMainFrame( |
| - begin_main_frame_args_.on_critical_path, |
| - begin_main_frame_args_.frame_time); |
| - state_machine_.WillSendBeginMainFrame(); |
| - // TODO(brianderson): Pass begin_main_frame_args_ directly to client. |
| - client_->ScheduledActionSendBeginMainFrame(begin_main_frame_args_); |
| - break; |
| - case SchedulerStateMachine::ACTION_COMMIT: { |
| - // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is |
| - // fixed. |
| - tracked_objects::ScopedTracker tracking_profile4( |
| - FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| - "461509 Scheduler::ProcessScheduledActions4")); |
| - bool commit_has_no_updates = false; |
| - state_machine_.WillCommit(commit_has_no_updates); |
| - client_->ScheduledActionCommit(); |
| - break; |
| - } |
| - case SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE: |
| - compositor_timing_history_->WillActivate(); |
| - state_machine_.WillActivate(); |
| - client_->ScheduledActionActivateSyncTree(); |
| - compositor_timing_history_->DidActivate(); |
| - break; |
| - case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE: { |
| - // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is |
| - // fixed. |
| - tracked_objects::ScopedTracker tracking_profile6( |
| - FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| - "461509 Scheduler::ProcessScheduledActions6")); |
| - DrawAndSwapIfPossible(); |
| - break; |
| - } |
| - case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED: |
| - DrawAndSwapForced(); |
| - break; |
| - case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT: { |
| - // No action is actually performed, but this allows the state machine to |
| - // drain the pipeline without actually drawing. |
| - state_machine_.AbortDrawAndSwap(); |
| - compositor_timing_history_->DrawAborted(); |
| - break; |
| - } |
| - case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: |
| - state_machine_.WillBeginOutputSurfaceCreation(); |
| - client_->ScheduledActionBeginOutputSurfaceCreation(); |
| - break; |
| - case SchedulerStateMachine::ACTION_PREPARE_TILES: |
| - state_machine_.WillPrepareTiles(); |
| - client_->ScheduledActionPrepareTiles(); |
| - break; |
| - case SchedulerStateMachine::ACTION_INVALIDATE_OUTPUT_SURFACE: { |
| - state_machine_.WillInvalidateOutputSurface(); |
| - client_->ScheduledActionInvalidateOutputSurface(); |
| - break; |
| - } |
| +void Scheduler::PerformAction(SchedulerStateMachine::Action action) { |
| + base::AutoReset<SchedulerStateMachine::Action> mark_inside_action( |
| + &inside_action_, action); |
| + switch (action) { |
| + case SchedulerStateMachine::ACTION_NONE: |
| + break; |
| + case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME: |
| + compositor_timing_history_->WillBeginMainFrame( |
| + begin_main_frame_args_.on_critical_path, |
| + begin_main_frame_args_.frame_time); |
| + state_machine_.WillSendBeginMainFrame(); |
| + // TODO(brianderson): Pass begin_main_frame_args_ directly to client. |
| + client_->ScheduledActionSendBeginMainFrame(begin_main_frame_args_); |
| + break; |
| + case SchedulerStateMachine::ACTION_COMMIT: { |
| + // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is |
| + // fixed. |
| + tracked_objects::ScopedTracker tracking_profile4( |
| + FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| + "461509 Scheduler::ProcessScheduledActions4")); |
| + bool commit_has_no_updates = false; |
| + state_machine_.WillCommit(commit_has_no_updates); |
| + client_->ScheduledActionCommit(); |
| + break; |
| } |
| - } while (action != SchedulerStateMachine::ACTION_NONE); |
| - |
| - ScheduleBeginImplFrameDeadlineIfNeeded(); |
| - SetupNextBeginFrameIfNeeded(); |
| + case SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE: |
| + compositor_timing_history_->WillActivate(); |
| + state_machine_.WillActivate(); |
| + client_->ScheduledActionActivateSyncTree(); |
| + compositor_timing_history_->DidActivate(); |
| + break; |
| + case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE: { |
| + // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is |
| + // fixed. |
| + tracked_objects::ScopedTracker tracking_profile6( |
| + FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| + "461509 Scheduler::ProcessScheduledActions6")); |
| + DrawAndSwapIfPossible(); |
| + break; |
| + } |
| + case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED: |
| + DrawAndSwapForced(); |
| + break; |
| + case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT: { |
| + // No action is actually performed, but this allows the state machine |
| + // to |
| + // drain the pipeline without actually drawing. |
| + state_machine_.AbortDrawAndSwap(); |
| + compositor_timing_history_->DrawAborted(); |
| + break; |
| + } |
| + case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: |
| + state_machine_.WillBeginOutputSurfaceCreation(); |
| + client_->ScheduledActionBeginOutputSurfaceCreation(); |
| + break; |
| + case SchedulerStateMachine::ACTION_PREPARE_TILES: |
| + state_machine_.WillPrepareTiles(); |
| + client_->ScheduledActionPrepareTiles(); |
| + break; |
| + case SchedulerStateMachine::ACTION_INVALIDATE_OUTPUT_SURFACE: { |
| + state_machine_.WillInvalidateOutputSurface(); |
| + client_->ScheduledActionInvalidateOutputSurface(); |
| + break; |
| + } |
| + } |
| } |
| std::unique_ptr<base::trace_event::ConvertableToTraceFormat> |
| @@ -775,10 +673,6 @@ void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const { |
| estimated_parent_draw_time_.InMillisecondsF()); |
| state->SetBoolean("observing_begin_frame_source", |
| observing_begin_frame_source_); |
| - state->SetInteger("begin_retro_frame_args", |
| - static_cast<int>(begin_retro_frame_args_.size())); |
| - state->SetBoolean("begin_retro_frame_task", |
| - !begin_retro_frame_task_.IsCancelled()); |
| state->SetBoolean("begin_impl_frame_deadline_task", |
| !begin_impl_frame_deadline_task_.IsCancelled()); |
| state->SetString("inside_action", |