blob: 6ce1b3bfd39574fa9a6c96b9c6a0e3a90ae78c4c [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cc/slim/delayed_scheduler.h"
namespace cc::slim {
DelayedScheduler::DelayedScheduler() = default;
DelayedScheduler::~DelayedScheduler() = default;
void DelayedScheduler::Initialize(SchedulerClient* client) {
DCHECK(!client_);
DCHECK(client);
client_ = client;
}
void DelayedScheduler::OnBeginFrameFromViz(
const viz::BeginFrameArgs& begin_frame_args) {
if (!needs_begin_frame_) {
// If begin frames are not needed anymore, then just rely immediately with
// DidNotProduceFrame for all args.
if (unused_args_.IsValid()) {
SendDidNotProduceFrameAndResetArgs(unused_args_);
}
client_->SendDidNotProduceFrame(begin_frame_args);
return;
}
viz::BeginFrameArgs args;
if (unused_args_.IsValid()) {
// If there is cached args, use it and cache new args.
args = unused_args_;
unused_args_ = begin_frame_args;
} else {
// There is no existing cached args. Decide whether to begin frame with
// new args or skip and cache new args.
if (missed_composite_now_ && !is_swap_throttled_) {
// If already missed a `MaybeCompositeNow` and can produce frame now, try
// to catch up and begin frame immediately.
args = begin_frame_args;
} else {
// Cache args and skip begin frame.
unused_args_ = begin_frame_args;
}
}
if (!args.IsValid()) {
return;
}
missed_composite_now_ = false;
BeginFrameAndResetArgs(args);
}
void DelayedScheduler::OnBeginFramePausedChanged(bool paused) {
// If there are no more begin frames even when requested, then try to produce
// frame with any cached args since client probably still wants begin frames.
if (paused && unused_args_.IsValid()) {
BeginFrameAndResetArgs(unused_args_);
}
}
void DelayedScheduler::SetNeedsBeginFrame(bool needs_begin_frame) {
needs_begin_frame_ = needs_begin_frame;
if (!needs_begin_frame && unused_args_.IsValid()) {
// Make sure there are no un-acked frame when idle.
SendDidNotProduceFrameAndResetArgs(unused_args_);
}
}
void DelayedScheduler::SetIsSwapThrottled(bool is_swap_throttled) {
is_swap_throttled_ = is_swap_throttled;
// A begin frame was missed due to being throttled, begin frame immediately
// when no longer throttled.
if (!is_swap_throttled && missed_composite_now_ && unused_args_.IsValid()) {
BeginFrameAndResetArgs(unused_args_);
}
}
void DelayedScheduler::MaybeCompositeNow() {
// Begin frame immediately if possible, or mark a MaybeCompositeNow was
// missed.
if (!unused_args_.IsValid() || is_swap_throttled_) {
missed_composite_now_ = true;
return;
}
BeginFrameAndResetArgs(unused_args_);
}
void DelayedScheduler::BeginFrameAndResetArgs(viz::BeginFrameArgs& args) {
// Make a copy and clear immediately to avoid re-entrancy issues.
viz::BeginFrameArgs copy = args;
args = viz::BeginFrameArgs();
if (!client_->DoBeginFrame(copy)) {
SendDidNotProduceFrameAndResetArgs(copy);
}
}
void DelayedScheduler::SendDidNotProduceFrameAndResetArgs(
viz::BeginFrameArgs& args) {
// Make a copy and clear immediately to avoid re-entrancy issues.
viz::BeginFrameArgs copy = args;
args = viz::BeginFrameArgs();
client_->SendDidNotProduceFrame(copy);
}
} // namespace cc::slim