SurfaceFlinger: fix Sf/App offsets provided in getDisplayConfigs()
In getDisplayConfigs() SF needs to return the corresponding offsets
based on the config it is requested for and not the current config.
Test: manual
Fixes: 130257355
Change-Id: Ie151701cb8765c8bdaea683f328d9c43065ba6b0
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
index 7e2b03d..16f6729 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -86,8 +86,9 @@
mHighRefreshRateOffsets.late = {highFpsLateSfOffsetNs, highFpsLateAppOffsetNs};
}
-PhaseOffsets::Offsets PhaseOffsets::getCurrentOffsets() const {
- switch (mRefreshRateType) {
+PhaseOffsets::Offsets PhaseOffsets::getOffsetsForRefreshRate(
+ android::scheduler::RefreshRateConfigs::RefreshRateType refreshRateType) const {
+ switch (refreshRateType) {
case RefreshRateConfigs::RefreshRateType::PERFORMANCE:
return mHighRefreshRateOffsets;
default:
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.h b/services/surfaceflinger/Scheduler/PhaseOffsets.h
index cbcaade..f26259a 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.h
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.h
@@ -42,6 +42,8 @@
virtual nsecs_t getCurrentAppOffset() = 0;
virtual nsecs_t getCurrentSfOffset() = 0;
+ virtual Offsets getOffsetsForRefreshRate(
+ RefreshRateConfigs::RefreshRateType refreshRateType) const = 0;
virtual Offsets getCurrentOffsets() const = 0;
virtual void setRefreshRateType(RefreshRateConfigs::RefreshRateType refreshRateType) = 0;
virtual void dump(std::string& result) const = 0;
@@ -55,8 +57,14 @@
nsecs_t getCurrentAppOffset() override;
nsecs_t getCurrentSfOffset() override;
+ // Returns early, early GL, and late offsets for Apps and SF for a given refresh rate.
+ Offsets getOffsetsForRefreshRate(
+ RefreshRateConfigs::RefreshRateType refreshRateType) const override;
+
// Returns early, early GL, and late offsets for Apps and SF.
- Offsets getCurrentOffsets() const override;
+ Offsets getCurrentOffsets() const override {
+ return getOffsetsForRefreshRate(mRefreshRateType);
+ }
// This function should be called when the device is switching between different
// refresh rates, to properly update the offsets.
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index eb9ae35..d730058 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -47,6 +47,8 @@
std::string name;
// Refresh rate in frames per second, rounded to the nearest integer.
uint32_t fps = 0;
+ // config Id (returned from HWC2::Display::Config::getId())
+ hwc2_config_t id;
};
// TODO(b/122916473): Get this information from configs prepared by vendors, instead of
@@ -62,13 +64,24 @@
return nullptr;
}
+ RefreshRateType getRefreshRateType(hwc2_config_t id) const {
+ for (const auto& [type, refreshRate] : mRefreshRates) {
+ if (refreshRate->id == id) {
+ return type;
+ }
+ }
+
+ return RefreshRateType::DEFAULT;
+ }
+
void populate(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
mRefreshRates.clear();
// This is the rate that HWC encapsulates right now when the device is in DOZE mode.
mRefreshRates.emplace(RefreshRateType::POWER_SAVING,
std::make_shared<RefreshRate>(
- RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0}));
+ RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0,
+ HWC2_SCREEN_OFF_CONFIG_ID}));
if (configs.size() < 1) {
ALOGE("Device does not have valid configs. Config size is 0.");
@@ -91,11 +104,12 @@
nsecs_t vsyncPeriod = configIdToVsyncPeriod[0].second;
if (vsyncPeriod != 0) {
const float fps = 1e9 / vsyncPeriod;
+ const int configId = configIdToVsyncPeriod[0].first;
mRefreshRates.emplace(RefreshRateType::DEFAULT,
std::make_shared<RefreshRate>(
- RefreshRate{configIdToVsyncPeriod[0].first,
- base::StringPrintf("%2.ffps", fps),
- static_cast<uint32_t>(fps)}));
+ RefreshRate{configId, base::StringPrintf("%2.ffps", fps),
+ static_cast<uint32_t>(fps),
+ configs.at(configId)->getId()}));
}
if (configs.size() < 2) {
@@ -107,11 +121,12 @@
vsyncPeriod = configIdToVsyncPeriod[1].second;
if (vsyncPeriod != 0) {
const float fps = 1e9 / vsyncPeriod;
+ const int configId = configIdToVsyncPeriod[1].first;
mRefreshRates.emplace(RefreshRateType::PERFORMANCE,
std::make_shared<RefreshRate>(
- RefreshRate{configIdToVsyncPeriod[1].first,
- base::StringPrintf("%2.ffps", fps),
- static_cast<uint32_t>(fps)}));
+ RefreshRate{configId, base::StringPrintf("%2.ffps", fps),
+ static_cast<uint32_t>(fps),
+ configs.at(configId)->getId()}));
}
}
diff --git a/services/surfaceflinger/Scheduler/SchedulerUtils.h b/services/surfaceflinger/Scheduler/SchedulerUtils.h
index a935cac..3bf3922 100644
--- a/services/surfaceflinger/Scheduler/SchedulerUtils.h
+++ b/services/surfaceflinger/Scheduler/SchedulerUtils.h
@@ -34,6 +34,7 @@
// the config is not visible to SF, and is completely maintained by HWC. However, we would
// still like to keep track of time when the device is in this config.
static constexpr int SCREEN_OFF_CONFIG_ID = -1;
+static constexpr uint32_t HWC2_SCREEN_OFF_CONFIG_ID = 0xffffffff;
// This number is used when we try to determine how long does a given layer stay relevant.
// Currently it is set to 100ms, because that would indicate 10Hz rendering.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index fb0c712..716da12 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -860,7 +860,9 @@
info.xdpi = xdpi;
info.ydpi = ydpi;
info.fps = 1e9 / hwConfig->getVsyncPeriod();
- info.appVsyncOffset = mPhaseOffsets->getCurrentAppOffset();
+ const auto refreshRateType = mRefreshRateConfigs.getRefreshRateType(hwConfig->getId());
+ const auto offset = mPhaseOffsets->getOffsetsForRefreshRate(refreshRateType);
+ info.appVsyncOffset = offset.late.app;
// This is how far in advance a buffer must be queued for
// presentation at a given time. If you want a buffer to appear
@@ -874,8 +876,7 @@
//
// We add an additional 1ms to allow for processing time and
// differences between the ideal and actual refresh rate.
- info.presentationDeadline =
- hwConfig->getVsyncPeriod() - mPhaseOffsets->getCurrentSfOffset() + 1000000;
+ info.presentationDeadline = hwConfig->getVsyncPeriod() - offset.late.sf + 1000000;
// All non-virtual displays are currently considered secure.
info.secure = true;
diff --git a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
index 0739f15..cfa8337 100644
--- a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
+++ b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
@@ -33,6 +33,11 @@
nsecs_t getCurrentAppOffset() override { return FAKE_PHASE_OFFSET_NS; }
nsecs_t getCurrentSfOffset() override { return FAKE_PHASE_OFFSET_NS; }
+ PhaseOffsets::Offsets getOffsetsForRefreshRate(
+ RefreshRateConfigs::RefreshRateType /*refreshRateType*/) const override {
+ return getCurrentOffsets();
+ }
+
// Returns early, early GL, and late offsets for Apps and SF.
PhaseOffsets::Offsets getCurrentOffsets() const override {
return Offsets{{FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 8b37c22..5067fe8 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -37,7 +37,9 @@
class RefreshRateConfigsTest : public testing::Test {
protected:
static constexpr int CONFIG_ID_60 = 0;
+ static constexpr hwc2_config_t HWC2_CONFIG_ID_60 = 0;
static constexpr int CONFIG_ID_90 = 1;
+ static constexpr hwc2_config_t HWC2_CONFIG_ID_90 = 1;
static constexpr int64_t VSYNC_60 = 16666667;
static constexpr int64_t VSYNC_90 = 11111111;
@@ -81,7 +83,8 @@
ASSERT_EQ(rates.end(), rates.find(RefreshRateType::PERFORMANCE));
ASSERT_EQ(rates.end(), rates.find(RefreshRateType::DEFAULT));
- RefreshRate expectedConfig = RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0};
+ RefreshRate expectedConfig =
+ RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0, HWC2_SCREEN_OFF_CONFIG_ID};
assertRatesEqual(expectedConfig, *powerSavingRate->second);
ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
@@ -109,9 +112,10 @@
ASSERT_NE(rates.end(), defaultRate);
ASSERT_EQ(rates.end(), rates.find(RefreshRateType::PERFORMANCE));
- RefreshRate expectedPowerSavingConfig = RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0};
+ RefreshRate expectedPowerSavingConfig =
+ RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0, HWC2_SCREEN_OFF_CONFIG_ID};
assertRatesEqual(expectedPowerSavingConfig, *powerSavingRate->second);
- RefreshRate expectedDefaultConfig = RefreshRate{CONFIG_ID_60, "60fps", 60};
+ RefreshRate expectedDefaultConfig = RefreshRate{CONFIG_ID_60, "60fps", 60, HWC2_CONFIG_ID_60};
assertRatesEqual(expectedDefaultConfig, *defaultRate->second);
ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));
@@ -145,11 +149,13 @@
ASSERT_NE(rates.end(), defaultRate);
ASSERT_NE(rates.end(), performanceRate);
- RefreshRate expectedPowerSavingConfig = RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0};
+ RefreshRate expectedPowerSavingConfig =
+ RefreshRate{SCREEN_OFF_CONFIG_ID, "ScreenOff", 0, HWC2_SCREEN_OFF_CONFIG_ID};
assertRatesEqual(expectedPowerSavingConfig, *powerSavingRate->second);
- RefreshRate expectedDefaultConfig = RefreshRate{CONFIG_ID_60, "60fps", 60};
+ RefreshRate expectedDefaultConfig = RefreshRate{CONFIG_ID_60, "60fps", 60, HWC2_CONFIG_ID_60};
assertRatesEqual(expectedDefaultConfig, *defaultRate->second);
- RefreshRate expectedPerformanceConfig = RefreshRate{CONFIG_ID_90, "90fps", 90};
+ RefreshRate expectedPerformanceConfig =
+ RefreshRate{CONFIG_ID_90, "90fps", 90, HWC2_CONFIG_ID_90};
assertRatesEqual(expectedPerformanceConfig, *performanceRate->second);
ASSERT_TRUE(mConfigs.getRefreshRate(RefreshRateType::POWER_SAVING));