diff options
Diffstat (limited to 'chromium/cc/scheduler/scheduler.cc')
-rw-r--r-- | chromium/cc/scheduler/scheduler.cc | 83 |
1 files changed, 42 insertions, 41 deletions
diff --git a/chromium/cc/scheduler/scheduler.cc b/chromium/cc/scheduler/scheduler.cc index f2be14bef49..fcdbde8a7c0 100644 --- a/chromium/cc/scheduler/scheduler.cc +++ b/chromium/cc/scheduler/scheduler.cc @@ -265,7 +265,7 @@ void Scheduler::CancelPendingBeginFrameTask() { if (pending_begin_frame_args_.IsValid()) { TRACE_EVENT_INSTANT0("cc", "Scheduler::BeginFrameDropped", TRACE_EVENT_SCOPE_THREAD); - SendBeginFrameAck(pending_begin_frame_args_, kBeginFrameSkipped); + SendDidNotProduceFrame(pending_begin_frame_args_); // Make pending begin frame invalid so that we don't accidentally use it. pending_begin_frame_args_ = viz::BeginFrameArgs(); } @@ -312,7 +312,7 @@ bool Scheduler::OnBeginFrameDerivedImpl(const viz::BeginFrameArgs& args) { // Since we don't use the BeginFrame, we may later receive the same // BeginFrame again. Thus, we can't confirm it at this point, even though we // don't have any updates right now. - SendBeginFrameAck(args, kBeginFrameSkipped); + SendDidNotProduceFrame(args); return false; } @@ -340,7 +340,7 @@ bool Scheduler::OnBeginFrameDerivedImpl(const viz::BeginFrameArgs& args) { if (pending_begin_frame_args_.IsValid()) { TRACE_EVENT_INSTANT0("cc", "Scheduler::BeginFrameDropped", TRACE_EVENT_SCOPE_THREAD); - SendBeginFrameAck(pending_begin_frame_args_, kBeginFrameSkipped); + SendDidNotProduceFrame(pending_begin_frame_args_); } pending_begin_frame_args_ = args; // ProcessScheduledActions() will post the previous frame's deadline if it @@ -415,7 +415,7 @@ void Scheduler::BeginImplFrameWithDeadline(const viz::BeginFrameArgs& args) { TRACE_EVENT_INSTANT0("cc", "Scheduler::MissedBeginFrameDropped", TRACE_EVENT_SCOPE_THREAD); skipped_last_frame_missed_exceeded_deadline_ = true; - SendBeginFrameAck(args, kBeginFrameSkipped); + SendDidNotProduceFrame(args); return; } skipped_last_frame_missed_exceeded_deadline_ = false; @@ -515,7 +515,7 @@ void Scheduler::BeginImplFrameWithDeadline(const viz::BeginFrameArgs& args) { TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency", TRACE_EVENT_SCOPE_THREAD); skipped_last_frame_to_reduce_latency_ = true; - SendBeginFrameAck(begin_main_frame_args_, kBeginFrameSkipped); + SendDidNotProduceFrame(args); return; } @@ -545,7 +545,9 @@ void Scheduler::FinishImplFrame() { // Send ack before calling ProcessScheduledActions() because it might send an // ack for any pending begin frame if we are going idle after this. This // ensures that the acks are sent in order. - SendBeginFrameAck(begin_main_frame_args_, kBeginFrameFinished); + if (!state_machine_.did_submit_in_last_frame()) + SendDidNotProduceFrame(begin_impl_frame_tracker_.Current()); + begin_impl_frame_tracker_.Finish(); ProcessScheduledActions(); @@ -554,24 +556,19 @@ void Scheduler::FinishImplFrame() { base::AutoReset<bool> mark_inside(&inside_scheduled_action_, true); client_->DidFinishImplFrame(); } -} - -void Scheduler::SendBeginFrameAck(const viz::BeginFrameArgs& args, - BeginFrameResult result) { - bool did_submit = false; - if (result == kBeginFrameFinished) - did_submit = state_machine_.did_submit_in_last_frame(); - - if (!did_submit) { - DCHECK(!inside_scheduled_action_); - base::AutoReset<bool> mark_inside(&inside_scheduled_action_, true); - client_->DidNotProduceFrame(viz::BeginFrameAck(args, did_submit)); - } if (begin_frame_source_) begin_frame_source_->DidFinishFrame(this); } +void Scheduler::SendDidNotProduceFrame(const viz::BeginFrameArgs& args) { + if (last_begin_frame_ack_.source_id == args.source_id && + last_begin_frame_ack_.sequence_number == args.sequence_number) + return; + last_begin_frame_ack_ = viz::BeginFrameAck(args, false /* has_damage */); + client_->DidNotProduceFrame(last_begin_frame_ack_); +} + // BeginImplFrame starts a compositor frame that will wait up until a deadline // for a BeginMainFrame+activation to complete before it times out and draws // any asynchronous animation and scroll/pinch updates. @@ -605,21 +602,18 @@ void Scheduler::BeginImplFrame(const viz::BeginFrameArgs& args, } void Scheduler::ScheduleBeginImplFrameDeadline() { - base::TimeTicks new_deadline; + using DeadlineMode = SchedulerStateMachine::BeginImplFrameDeadlineMode; + deadline_mode_ = state_machine_.CurrentBeginImplFrameDeadlineMode(); - begin_impl_frame_deadline_mode_ = - state_machine_.CurrentBeginImplFrameDeadlineMode(); - // Avoid using Now() for immediate deadlines because it's expensive, and this - // method is called in every ProcessScheduledActions() call. Using - // base::TimeTicks() achieves the same result. - switch (begin_impl_frame_deadline_mode_) { - case SchedulerStateMachine::BeginImplFrameDeadlineMode::NONE: + base::TimeTicks new_deadline; + switch (deadline_mode_) { + case DeadlineMode::NONE: // NONE is returned when deadlines aren't used (synchronous compositor), // or when outside a begin frame. In either case deadline task shouldn't // be posted or should be cancelled already. DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); return; - case SchedulerStateMachine::BeginImplFrameDeadlineMode::BLOCKED: { + case DeadlineMode::BLOCKED: { // TODO(sunnyps): Posting the deadline for pending begin frame is required // for browser compositor (commit_to_active_tree) to make progress in some // cases. Change browser compositor deadline to LATE in state machine to @@ -631,37 +625,44 @@ void Scheduler::ScheduleBeginImplFrameDeadline() { bool has_pending_begin_frame = pending_begin_frame_args_.IsValid(); if (has_pending_begin_frame) { new_deadline = base::TimeTicks(); + break; } else { begin_impl_frame_deadline_task_.Cancel(); return; } - break; } - case SchedulerStateMachine::BeginImplFrameDeadlineMode::LATE: - // We are waiting for a commit without needing active tree draw or we have - // nothing to do. + case DeadlineMode::LATE: { + // We are waiting for a commit without needing active tree draw or we + // have nothing to do. new_deadline = begin_impl_frame_tracker_.Current().frame_time + begin_impl_frame_tracker_.Current().interval; + // Send early DidNotProduceFrame if we don't expect to produce a frame + // soon so that display scheduler doesn't wait unnecessarily. + // Note: This will only send one DidNotProduceFrame ack per begin frame. + if (!state_machine_.NewActiveTreeLikely()) + SendDidNotProduceFrame(begin_impl_frame_tracker_.Current()); break; - case SchedulerStateMachine::BeginImplFrameDeadlineMode::REGULAR: + } + case DeadlineMode::REGULAR: // We are animating the active tree but we're also waiting for commit. new_deadline = begin_impl_frame_tracker_.Current().deadline; break; - case SchedulerStateMachine::BeginImplFrameDeadlineMode::IMMEDIATE: + case DeadlineMode::IMMEDIATE: + // Avoid using Now() for immediate deadlines because it's expensive, and + // this method is called in every ProcessScheduledActions() call. Using + // base::TimeTicks() achieves the same result. new_deadline = base::TimeTicks(); break; } - bool has_no_deadline_task = begin_impl_frame_deadline_task_.IsCancelled(); // Post deadline task only if we didn't have one already or something caused - // us to change the deadline. Comparing deadline mode is not sufficient - // because the calculated deadline also depends on whether we have a pending - // begin frame which the state machine doesn't know about. + // us to change the deadline. + bool has_no_deadline_task = begin_impl_frame_deadline_task_.IsCancelled(); if (has_no_deadline_task || new_deadline != deadline_) { TRACE_EVENT2("cc", "Scheduler::ScheduleBeginImplFrameDeadline", "new deadline", new_deadline, "deadline mode", SchedulerStateMachine::BeginImplFrameDeadlineModeToString( - begin_impl_frame_deadline_mode_)); + deadline_mode_)); deadline_ = new_deadline; deadline_scheduled_at_ = Now(); @@ -862,9 +863,9 @@ void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const { skipped_last_frame_to_reduce_latency_); state->SetString("inside_action", SchedulerStateMachine::ActionToString(inside_action_)); - state->SetString("begin_impl_frame_deadline_mode", + state->SetString("deadline_mode", SchedulerStateMachine::BeginImplFrameDeadlineModeToString( - begin_impl_frame_deadline_mode_)); + deadline_mode_)); state->SetDouble("deadline_ms", deadline_.since_origin().InMillisecondsF()); state->SetDouble("deadline_scheduled_at_ms", |