blob: 3873cb92bcea34ebc79e23baaa3dcd1770cee045 [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 <optional>
#include "cc/slim/delayed_scheduler.h"
#include "cc/slim/scheduler.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc::slim {
namespace {
class TestSchedulerClient : public SchedulerClient {
public:
explicit TestSchedulerClient(Scheduler* scheduler) : scheduler_(scheduler) {}
bool DoBeginFrame(const viz::BeginFrameArgs& begin_frame_args) override {
last_do_begin_frame_args_ = begin_frame_args;
if (do_begin_frame_result_) {
scheduler_->SetIsSwapThrottled(true);
}
return do_begin_frame_result_;
}
void SendDidNotProduceFrame(
const viz::BeginFrameArgs& begin_frame_args) override {
last_did_not_produce_frame_args_ = begin_frame_args;
}
void SetDoBeginFrameResult(bool result) { do_begin_frame_result_ = result; }
std::optional<viz::BeginFrameArgs> TakeLastDoBeginFrameArgs() {
auto rv = last_do_begin_frame_args_;
last_do_begin_frame_args_.reset();
return rv;
}
std::optional<viz::BeginFrameArgs> TakeLastDidNotProduceFrameArgs() {
auto rv = last_did_not_produce_frame_args_;
last_did_not_produce_frame_args_.reset();
return rv;
}
private:
const raw_ptr<Scheduler> scheduler_;
std::optional<viz::BeginFrameArgs> last_do_begin_frame_args_;
std::optional<viz::BeginFrameArgs> last_did_not_produce_frame_args_;
bool do_begin_frame_result_ = false;
};
class SlimDelayedSchedulerTest : public testing::Test {
public:
void SetUp() override { scheduler_.Initialize(&client_); }
viz::BeginFrameArgs GenBeginFrameArgs() {
base::TimeTicks frame_time = base::TimeTicks::Now();
base::TimeDelta interval = viz::BeginFrameArgs::DefaultInterval();
return viz::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE,
/*source_id=*/1, ++sequence_id_,
frame_time, frame_time + interval,
interval, viz::BeginFrameArgs::NORMAL);
}
void CheckDoBeginFrameCalledWith(const viz::BeginFrameArgs& args) {
auto args_opt = client_.TakeLastDoBeginFrameArgs();
ASSERT_TRUE(args_opt);
EXPECT_EQ(args_opt->frame_id, args.frame_id);
}
void CheckDidNotProcueFrameCalledWith(const viz::BeginFrameArgs& args) {
auto args_opt = client_.TakeLastDidNotProduceFrameArgs();
ASSERT_TRUE(args_opt);
EXPECT_EQ(args_opt->frame_id, args.frame_id);
}
void CheckDoBeginFrameNotCalled() {
EXPECT_FALSE(client_.TakeLastDoBeginFrameArgs());
}
void CheckDidNotProcueFrameNotCalled() {
EXPECT_FALSE(client_.TakeLastDidNotProduceFrameArgs());
}
protected:
uint64_t sequence_id_ = 0;
DelayedScheduler scheduler_;
TestSchedulerClient client_{&scheduler_};
};
TEST_F(SlimDelayedSchedulerTest, DelayedBeginFrame) {
scheduler_.SetNeedsBeginFrame(true);
client_.SetDoBeginFrameResult(false);
viz::BeginFrameArgs args1 = GenBeginFrameArgs();
scheduler_.OnBeginFrameFromViz(args1);
CheckDoBeginFrameNotCalled();
CheckDidNotProcueFrameNotCalled();
viz::BeginFrameArgs args2 = GenBeginFrameArgs();
scheduler_.OnBeginFrameFromViz(args2);
CheckDoBeginFrameCalledWith(args1);
CheckDidNotProcueFrameCalledWith(args1);
viz::BeginFrameArgs args3 = GenBeginFrameArgs();
scheduler_.OnBeginFrameFromViz(args3);
CheckDoBeginFrameCalledWith(args2);
CheckDidNotProcueFrameCalledWith(args2);
client_.SetDoBeginFrameResult(true);
viz::BeginFrameArgs args4 = GenBeginFrameArgs();
scheduler_.OnBeginFrameFromViz(args4);
CheckDoBeginFrameCalledWith(args3);
CheckDidNotProcueFrameNotCalled();
scheduler_.SetIsSwapThrottled(false);
viz::BeginFrameArgs args5 = GenBeginFrameArgs();
scheduler_.OnBeginFrameFromViz(args5);
CheckDoBeginFrameCalledWith(args4);
CheckDidNotProcueFrameNotCalled();
scheduler_.SetIsSwapThrottled(false);
scheduler_.SetNeedsBeginFrame(false);
CheckDoBeginFrameNotCalled();
CheckDidNotProcueFrameCalledWith(args5);
}
TEST_F(SlimDelayedSchedulerTest, MaybeCompositeNow) {
scheduler_.SetNeedsBeginFrame(true);
client_.SetDoBeginFrameResult(false);
viz::BeginFrameArgs args1 = GenBeginFrameArgs();
scheduler_.OnBeginFrameFromViz(args1);
CheckDoBeginFrameNotCalled();
CheckDidNotProcueFrameNotCalled();
scheduler_.MaybeCompositeNow();
CheckDoBeginFrameCalledWith(args1);
CheckDidNotProcueFrameCalledWith(args1);
viz::BeginFrameArgs args2 = GenBeginFrameArgs();
scheduler_.OnBeginFrameFromViz(args2);
CheckDoBeginFrameNotCalled();
CheckDidNotProcueFrameNotCalled();
scheduler_.MaybeCompositeNow();
CheckDoBeginFrameCalledWith(args2);
CheckDidNotProcueFrameCalledWith(args2);
scheduler_.MaybeCompositeNow();
CheckDoBeginFrameNotCalled();
CheckDidNotProcueFrameNotCalled();
viz::BeginFrameArgs args3 = GenBeginFrameArgs();
scheduler_.OnBeginFrameFromViz(args3);
// Missed MaybeCompositeNow so begin frame immediately.
CheckDoBeginFrameCalledWith(args3);
CheckDidNotProcueFrameCalledWith(args3);
scheduler_.SetNeedsBeginFrame(false);
CheckDoBeginFrameNotCalled();
CheckDidNotProcueFrameNotCalled();
}
TEST_F(SlimDelayedSchedulerTest, SwapThrottled) {
scheduler_.SetNeedsBeginFrame(true);
client_.SetDoBeginFrameResult(true);
viz::BeginFrameArgs args1 = GenBeginFrameArgs();
scheduler_.OnBeginFrameFromViz(args1);
CheckDoBeginFrameNotCalled();
CheckDidNotProcueFrameNotCalled();
scheduler_.MaybeCompositeNow();
CheckDoBeginFrameCalledWith(args1);
CheckDidNotProcueFrameNotCalled();
// Swap throttled at this point.
viz::BeginFrameArgs args2 = GenBeginFrameArgs();
scheduler_.OnBeginFrameFromViz(args1);
CheckDoBeginFrameNotCalled();
CheckDidNotProcueFrameNotCalled();
scheduler_.MaybeCompositeNow();
CheckDoBeginFrameNotCalled();
CheckDidNotProcueFrameNotCalled();
scheduler_.SetIsSwapThrottled(false);
CheckDoBeginFrameCalledWith(args1);
CheckDidNotProcueFrameNotCalled();
scheduler_.SetNeedsBeginFrame(false);
CheckDoBeginFrameNotCalled();
CheckDidNotProcueFrameNotCalled();
}
TEST_F(SlimDelayedSchedulerTest, BeginFramePaused) {
scheduler_.SetNeedsBeginFrame(true);
client_.SetDoBeginFrameResult(true);
viz::BeginFrameArgs args1 = GenBeginFrameArgs();
scheduler_.OnBeginFrameFromViz(args1);
CheckDoBeginFrameNotCalled();
CheckDidNotProcueFrameNotCalled();
scheduler_.OnBeginFramePausedChanged(true);
CheckDoBeginFrameCalledWith(args1);
CheckDidNotProcueFrameNotCalled();
}
} // namespace
} // namespace cc::slim