You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
7.0 KiB
182 lines
7.0 KiB
/*
|
|
* Copyright 2020 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#undef LOG_TAG
|
|
#define LOG_TAG "LayerInfoTest"
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "Fps.h"
|
|
#include "Scheduler/LayerHistory.h"
|
|
#include "Scheduler/LayerInfo.h"
|
|
|
|
namespace android::scheduler {
|
|
|
|
class LayerInfoTest : public testing::Test {
|
|
protected:
|
|
using FrameTimeData = LayerInfo::FrameTimeData;
|
|
|
|
void setFrameTimes(const std::deque<FrameTimeData>& frameTimes) {
|
|
layerInfo.mFrameTimes = frameTimes;
|
|
}
|
|
|
|
void setLastRefreshRate(Fps fps) {
|
|
layerInfo.mLastRefreshRate.reported = fps;
|
|
layerInfo.mLastRefreshRate.calculated = fps;
|
|
}
|
|
|
|
auto calculateAverageFrameTime() { return layerInfo.calculateAverageFrameTime(); }
|
|
|
|
LayerInfo layerInfo{"TestLayerInfo", 0, LayerHistory::LayerVoteType::Heuristic};
|
|
};
|
|
|
|
namespace {
|
|
|
|
TEST_F(LayerInfoTest, prefersPresentTime) {
|
|
std::deque<FrameTimeData> frameTimes;
|
|
constexpr auto kExpectedFps = Fps(50.0f);
|
|
constexpr auto kPeriod = kExpectedFps.getPeriodNsecs();
|
|
constexpr int kNumFrames = 10;
|
|
for (int i = 1; i <= kNumFrames; i++) {
|
|
frameTimes.push_back(FrameTimeData{.presentTime = kPeriod * i,
|
|
.queueTime = 0,
|
|
.pendingModeChange = false});
|
|
}
|
|
setFrameTimes(frameTimes);
|
|
const auto averageFrameTime = calculateAverageFrameTime();
|
|
ASSERT_TRUE(averageFrameTime.has_value());
|
|
const auto averageFps = Fps::fromPeriodNsecs(*averageFrameTime);
|
|
ASSERT_TRUE(kExpectedFps.equalsWithMargin(averageFps))
|
|
<< "Expected " << averageFps << " to be equal to " << kExpectedFps;
|
|
}
|
|
|
|
TEST_F(LayerInfoTest, fallbacksToQueueTimeIfNoPresentTime) {
|
|
std::deque<FrameTimeData> frameTimes;
|
|
constexpr auto kExpectedFps = Fps(50.0f);
|
|
constexpr auto kPeriod = kExpectedFps.getPeriodNsecs();
|
|
constexpr int kNumFrames = 10;
|
|
for (int i = 1; i <= kNumFrames; i++) {
|
|
frameTimes.push_back(FrameTimeData{.presentTime = 0,
|
|
.queueTime = kPeriod * i,
|
|
.pendingModeChange = false});
|
|
}
|
|
setFrameTimes(frameTimes);
|
|
setLastRefreshRate(Fps(20.0f)); // Set to some valid value
|
|
const auto averageFrameTime = calculateAverageFrameTime();
|
|
ASSERT_TRUE(averageFrameTime.has_value());
|
|
const auto averageFps = Fps::fromPeriodNsecs(*averageFrameTime);
|
|
ASSERT_TRUE(kExpectedFps.equalsWithMargin(averageFps))
|
|
<< "Expected " << averageFps << " to be equal to " << kExpectedFps;
|
|
}
|
|
|
|
TEST_F(LayerInfoTest, returnsNulloptIfThereWasConfigChange) {
|
|
std::deque<FrameTimeData> frameTimesWithoutConfigChange;
|
|
const auto period = Fps(50.0f).getPeriodNsecs();
|
|
constexpr int kNumFrames = 10;
|
|
for (int i = 1; i <= kNumFrames; i++) {
|
|
frameTimesWithoutConfigChange.push_back(FrameTimeData{.presentTime = period * i,
|
|
.queueTime = period * i,
|
|
.pendingModeChange = false});
|
|
}
|
|
|
|
setFrameTimes(frameTimesWithoutConfigChange);
|
|
ASSERT_TRUE(calculateAverageFrameTime().has_value());
|
|
|
|
{
|
|
// Config change in the first record
|
|
auto frameTimes = frameTimesWithoutConfigChange;
|
|
frameTimes[0].pendingModeChange = true;
|
|
setFrameTimes(frameTimes);
|
|
ASSERT_FALSE(calculateAverageFrameTime().has_value());
|
|
}
|
|
|
|
{
|
|
// Config change in the last record
|
|
auto frameTimes = frameTimesWithoutConfigChange;
|
|
frameTimes[frameTimes.size() - 1].pendingModeChange = true;
|
|
setFrameTimes(frameTimes);
|
|
ASSERT_FALSE(calculateAverageFrameTime().has_value());
|
|
}
|
|
|
|
{
|
|
// Config change in the middle
|
|
auto frameTimes = frameTimesWithoutConfigChange;
|
|
frameTimes[frameTimes.size() / 2].pendingModeChange = true;
|
|
setFrameTimes(frameTimes);
|
|
ASSERT_FALSE(calculateAverageFrameTime().has_value());
|
|
}
|
|
}
|
|
|
|
// A frame can be recorded twice with very close presentation or queue times.
|
|
// Make sure that this doesn't influence the calculated average FPS.
|
|
TEST_F(LayerInfoTest, ignoresSmallPeriods) {
|
|
std::deque<FrameTimeData> frameTimes;
|
|
constexpr auto kExpectedFps = Fps(50.0f);
|
|
constexpr auto kExpectedPeriod = kExpectedFps.getPeriodNsecs();
|
|
constexpr auto kSmallPeriod = Fps(250.0f).getPeriodNsecs();
|
|
constexpr int kNumIterations = 10;
|
|
for (int i = 1; i <= kNumIterations; i++) {
|
|
frameTimes.push_back(FrameTimeData{.presentTime = kExpectedPeriod * i,
|
|
.queueTime = 0,
|
|
.pendingModeChange = false});
|
|
|
|
// A duplicate frame
|
|
frameTimes.push_back(FrameTimeData{.presentTime = kExpectedPeriod * i + kSmallPeriod,
|
|
.queueTime = 0,
|
|
.pendingModeChange = false});
|
|
}
|
|
setFrameTimes(frameTimes);
|
|
const auto averageFrameTime = calculateAverageFrameTime();
|
|
ASSERT_TRUE(averageFrameTime.has_value());
|
|
const auto averageFps = Fps::fromPeriodNsecs(*averageFrameTime);
|
|
ASSERT_TRUE(kExpectedFps.equalsWithMargin(averageFps))
|
|
<< "Expected " << averageFps << " to be equal to " << kExpectedFps;
|
|
}
|
|
|
|
// There may be a big period of time between two frames. Make sure that
|
|
// this doesn't influence the calculated average FPS.
|
|
TEST_F(LayerInfoTest, ignoresLargePeriods) {
|
|
std::deque<FrameTimeData> frameTimes;
|
|
constexpr auto kExpectedFps = Fps(50.0f);
|
|
constexpr auto kExpectedPeriod = kExpectedFps.getPeriodNsecs();
|
|
constexpr auto kLargePeriod = Fps(9.0f).getPeriodNsecs();
|
|
|
|
auto record = [&](nsecs_t time) {
|
|
frameTimes.push_back(
|
|
FrameTimeData{.presentTime = time, .queueTime = 0, .pendingModeChange = false});
|
|
};
|
|
|
|
auto time = kExpectedPeriod; // Start with non-zero time.
|
|
record(time);
|
|
time += kLargePeriod;
|
|
record(time);
|
|
constexpr int kNumIterations = 10;
|
|
for (int i = 1; i <= kNumIterations; i++) {
|
|
time += kExpectedPeriod;
|
|
record(time);
|
|
}
|
|
|
|
setFrameTimes(frameTimes);
|
|
const auto averageFrameTime = calculateAverageFrameTime();
|
|
ASSERT_TRUE(averageFrameTime.has_value());
|
|
const auto averageFps = Fps::fromPeriodNsecs(*averageFrameTime);
|
|
ASSERT_TRUE(kExpectedFps.equalsWithMargin(averageFps))
|
|
<< "Expected " << averageFps << " to be equal to " << kExpectedFps;
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace android::scheduler
|