| Index: cc/scheduler/scheduler.cc
|
| diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
|
| index d603086725b002350f2a8733dfd6743129563fc9..84ab533061d770555fa1f7911e0dbaf5695a4e6f 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());
|
|
|
| @@ -200,8 +198,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();
|
| @@ -254,13 +250,12 @@ void Scheduler::SetupNextBeginFrameIfNeeded() {
|
| observing_begin_frame_source_ = false;
|
| if (begin_frame_source_)
|
| begin_frame_source_->RemoveObserver(this);
|
| + missed_begin_frame_task_.Cancel();
|
| BeginImplFrameNotExpectedSoon();
|
| devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_,
|
| false);
|
| }
|
| }
|
| -
|
| - PostBeginRetroFrameIfNeeded();
|
| }
|
|
|
| void Scheduler::OnBeginFrameSourcePausedChanged(bool paused) {
|
| @@ -279,6 +274,12 @@ void Scheduler::OnBeginFrameSourcePausedChanged(bool paused) {
|
| bool Scheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) {
|
| TRACE_EVENT1("cc,benchmark", "Scheduler::BeginFrame", "args", args.AsValue());
|
|
|
| + if (!state_machine_.BeginFrameNeeded()) {
|
| + TRACE_EVENT_INSTANT0("cc", "Scheduler::BeginFrameDropped",
|
| + TRACE_EVENT_SCOPE_THREAD);
|
| + return false;
|
| + }
|
| +
|
| // Trace this begin frame time through the Chrome stack
|
| TRACE_EVENT_FLOW_BEGIN0(
|
| TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs",
|
| @@ -298,26 +299,15 @@ bool Scheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) {
|
| // 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) {
|
| - begin_retro_frame_args_.push_back(adjusted_args);
|
| - PostBeginRetroFrameIfNeeded();
|
| + DCHECK(missed_begin_frame_task_.IsCancelled());
|
| + missed_begin_frame_task_.Reset(
|
| + base::Bind(&Scheduler::BeginImplFrameWithDeadline,
|
| + base::Unretained(this), adjusted_args));
|
| + task_runner_->PostTask(FROM_HERE, missed_begin_frame_task_.callback());
|
| 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);
|
| - }
|
| + BeginImplFrameWithDeadline(adjusted_args);
|
| return true;
|
| }
|
|
|
| @@ -341,77 +331,6 @@ void Scheduler::OnDrawForOutputSurface(bool resourceless_software_draw) {
|
| state_machine_.SetResourcelessSoftwareDraw(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(this, 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();
|
| @@ -421,7 +340,21 @@ void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) {
|
| TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
|
| "MainThreadLatency", main_thread_is_in_high_latency_mode);
|
|
|
| + if (state_machine_.begin_impl_frame_state() ==
|
| + SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME) {
|
| + OnBeginImplFrameDeadline();
|
| + }
|
| +
|
| + DCHECK_EQ(state_machine_.begin_impl_frame_state(),
|
| + SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
|
| +
|
| BeginFrameArgs adjusted_args = args;
|
| +
|
| + // Cancel the missed begin frame task in case the BFS sends a normal begin
|
| + // frame before the missed frame task runs. This should be done after |args|
|
| + // is copied because destroying the task also destroys the storage for |args|.
|
| + missed_begin_frame_task_.Cancel();
|
| +
|
| adjusted_args.deadline -= compositor_timing_history_->DrawDurationEstimate();
|
| adjusted_args.deadline -= kDeadlineFudgeFactor;
|
|
|
| @@ -436,7 +369,7 @@ void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) {
|
| compositor_timing_history_->BeginMainFrameQueueDurationCriticalEstimate();
|
|
|
| state_machine_.SetCriticalBeginMainFrameToActivateIsFast(
|
| - bmf_to_activate_estimate_critical < args.interval);
|
| + bmf_to_activate_estimate_critical < adjusted_args.interval);
|
|
|
| // Update the BeginMainFrame args now that we know whether the main
|
| // thread will be on the critical path or not.
|
| @@ -464,7 +397,7 @@ void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) {
|
| TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency",
|
| TRACE_EVENT_SCOPE_THREAD);
|
| if (begin_frame_source_)
|
| - begin_frame_source_->DidFinishFrame(this, begin_retro_frame_args_.size());
|
| + begin_frame_source_->DidFinishFrame(this, 0);
|
| return;
|
| }
|
|
|
| @@ -493,7 +426,7 @@ void Scheduler::FinishImplFrame() {
|
|
|
| client_->DidFinishImplFrame();
|
| if (begin_frame_source_)
|
| - begin_frame_source_->DidFinishFrame(this, begin_retro_frame_args_.size());
|
| + begin_frame_source_->DidFinishFrame(this, 0);
|
| begin_impl_frame_tracker_.Finish();
|
| }
|
|
|
| @@ -722,12 +655,10 @@ Scheduler::AsValue() 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->SetBoolean("missed_begin_frame_task",
|
| + !missed_begin_frame_task_.IsCancelled());
|
| state->SetString("inside_action",
|
| SchedulerStateMachine::ActionToString(inside_action_));
|
|
|
|
|