diff options
author | 2023-10-25 16:20:29 -0700 | |
---|---|---|
committer | 2023-11-29 16:12:57 -0800 | |
commit | e5514a7bf2da6d82aa9166edb359c6806bb4dcc9 (patch) | |
tree | 4b3fe2666954da6ff68133e8bc145280fc2c6226 | |
parent | 791b234ccf11e7ee347eb8f881baff88cfc4fc63 (diff) |
Add frame rate compatibility GTE logic
Bug: 306080972
Test: atest libsurfaceflinger_unittest
Test: atest SetFrameRateTest
Change-Id: I65551be0f96fd7d4137e49259436e1a9c74bfe90
7 files changed, 115 insertions, 9 deletions
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index e41aa06541..a98ea86073 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -1057,7 +1057,12 @@ enum { /** * This surface will vote for the minimum refresh rate. */ - ANATIVEWINDOW_FRAME_RATE_MIN + ANATIVEWINDOW_FRAME_RATE_MIN, + + /** + * The surface requests a frame rate that is greater than or equal to `frameRate`. + */ + ANATIVEWINDOW_FRAME_RATE_GTE }; /* diff --git a/services/surfaceflinger/Scheduler/FrameRateCompatibility.h b/services/surfaceflinger/Scheduler/FrameRateCompatibility.h index 405c982494..d8c408f485 100644 --- a/services/surfaceflinger/Scheduler/FrameRateCompatibility.h +++ b/services/surfaceflinger/Scheduler/FrameRateCompatibility.h @@ -29,6 +29,8 @@ enum class FrameRateCompatibility { ExactOrMultiple, // Layer needs the exact frame rate (or a multiple of it) to present the // content properly. Any other value will result in a pull down. + Gte, // Layer needs greater than or equal to the frame rate. + NoVote, // Layer doesn't have any requirements for the refresh rate and // should not be considered when the display refresh rate is determined. diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index d309adccf8..9c003026ea 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -278,6 +278,8 @@ void LayerHistory::partitionLayers(nsecs_t now) { return LayerVoteType::NoVote; case Layer::FrameRateCompatibility::Exact: return LayerVoteType::ExplicitExact; + case Layer::FrameRateCompatibility::Gte: + return LayerVoteType::ExplicitGte; } }(); diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 71ad45153f..d3ff2361b6 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -485,6 +485,8 @@ FrameRateCompatibility LayerInfo::FrameRate::convertCompatibility(int8_t compati return FrameRateCompatibility::Exact; case ANATIVEWINDOW_FRAME_RATE_MIN: return FrameRateCompatibility::Min; + case ANATIVEWINDOW_FRAME_RATE_GTE: + return FrameRateCompatibility::Gte; case ANATIVEWINDOW_FRAME_RATE_NO_VOTE: return FrameRateCompatibility::NoVote; default: diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp index 6a7063e40f..e06221a43d 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp @@ -332,6 +332,15 @@ float RefreshRateSelector::calculateNonExactMatchingLayerScoreLocked(const Layer return calculateNonExactMatchingDefaultLayerScoreLocked(displayPeriod, layerPeriod); } + if (layer.vote == LayerVoteType::ExplicitGte) { + using fps_approx_ops::operator>=; + if (refreshRate >= layer.desiredRefreshRate) { + return 1.0f; + } else { + return calculateDistanceScoreLocked(layer.desiredRefreshRate, refreshRate); + } + } + if (layer.vote == LayerVoteType::ExplicitExactOrMultiple || layer.vote == LayerVoteType::Heuristic) { using fps_approx_ops::operator<; @@ -390,13 +399,20 @@ float RefreshRateSelector::calculateNonExactMatchingLayerScoreLocked(const Layer return 0; } -float RefreshRateSelector::calculateDistanceScoreFromMax(Fps refreshRate) const { - const auto& maxFps = mAppRequestFrameRates.back().fps; - const float ratio = refreshRate.getValue() / maxFps.getValue(); - // Use ratio^2 to get a lower score the more we get further from peak +float RefreshRateSelector::calculateDistanceScoreLocked(Fps referenceRate, Fps refreshRate) const { + using fps_approx_ops::operator>=; + const float ratio = referenceRate >= refreshRate + ? refreshRate.getValue() / referenceRate.getValue() + : referenceRate.getValue() / refreshRate.getValue(); + // Use ratio^2 to get a lower score the more we get further from the reference rate. return ratio * ratio; } +float RefreshRateSelector::calculateDistanceScoreFromMaxLocked(Fps refreshRate) const { + const auto& maxFps = mAppRequestFrameRates.back().fps; + return calculateDistanceScoreLocked(maxFps, refreshRate); +} + float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& layer, Fps refreshRate, bool isSeamlessSwitch) const { // Slightly prefer seamless switches. @@ -421,7 +437,7 @@ float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& lay // If the layer wants Max, give higher score to the higher refresh rate if (layer.vote == LayerVoteType::Max) { - return calculateDistanceScoreFromMax(refreshRate); + return calculateDistanceScoreFromMaxLocked(refreshRate); } if (layer.vote == LayerVoteType::ExplicitExact) { @@ -489,6 +505,7 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi int explicitDefaultVoteLayers = 0; int explicitExactOrMultipleVoteLayers = 0; int explicitExact = 0; + int explicitGteLayers = 0; int explicitCategoryVoteLayers = 0; int seamedFocusedLayers = 0; int categorySmoothSwitchOnlyLayers = 0; @@ -513,6 +530,9 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi case LayerVoteType::ExplicitExact: explicitExact++; break; + case LayerVoteType::ExplicitGte: + explicitGteLayers++; + break; case LayerVoteType::ExplicitCategory: explicitCategoryVoteLayers++; if (layer.frameRateCategory == FrameRateCategory::NoPreference) { @@ -535,7 +555,7 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi } const bool hasExplicitVoteLayers = explicitDefaultVoteLayers > 0 || - explicitExactOrMultipleVoteLayers > 0 || explicitExact > 0 || + explicitExactOrMultipleVoteLayers > 0 || explicitExact > 0 || explicitGteLayers > 0 || explicitCategoryVoteLayers > 0; const Policy* policy = getCurrentPolicyLocked(); @@ -688,6 +708,7 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi case LayerVoteType::Max: case LayerVoteType::ExplicitDefault: case LayerVoteType::ExplicitExact: + case LayerVoteType::ExplicitGte: case LayerVoteType::ExplicitCategory: return false; } @@ -1081,7 +1102,7 @@ auto RefreshRateSelector::rankFrameRates(std::optional<int> anchorGroupOpt, return; } - float score = calculateDistanceScoreFromMax(frameRateMode.fps); + float score = calculateDistanceScoreFromMaxLocked(frameRateMode.fps); if (ascending) { score = 1.0f / score; diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.h b/services/surfaceflinger/Scheduler/RefreshRateSelector.h index 40e9a8310f..9f6a29cbc9 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.h +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.h @@ -149,6 +149,7 @@ public: // ExactOrMultiple compatibility ExplicitExact, // Specific refresh rate that was provided by the app with // Exact compatibility + ExplicitGte, // Greater than or equal to frame rate provided by the app ExplicitCategory, // Specific frame rate category was provided by the app ftl_last = ExplicitCategory @@ -460,7 +461,11 @@ private: bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock); // Returns the refresh rate score as a ratio to max refresh rate, which has a score of 1. - float calculateDistanceScoreFromMax(Fps refreshRate) const REQUIRES(mLock); + float calculateDistanceScoreFromMaxLocked(Fps refreshRate) const REQUIRES(mLock); + + // Returns the refresh rate score based on its distance from the reference rate. + float calculateDistanceScoreLocked(Fps referenceRate, Fps refreshRate) const REQUIRES(mLock); + // calculates a score for a layer. Used to determine the display refresh rate // and the frame rate override for certains applications. float calculateLayerScoreLocked(const LayerRequirement&, Fps refreshRate, diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp index a9567b2881..0cacf810c0 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp @@ -1150,6 +1150,75 @@ TEST_P(RefreshRateSelectorTest, scrollWhileWatching60fps_60_90) { EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); } +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_ExplicitGte) { + auto selector = createSelector(makeModes(kMode30, kMode60, kMode90, kMode120), kModeId120); + + std::vector<LayerRequirement> layers = {{.weight = 1.f}, {.weight = 1.f}}; + auto& lr1 = layers[0]; + auto& lr2 = layers[1]; + + lr1.vote = LayerVoteType::ExplicitGte; + lr1.desiredRefreshRate = 60_Hz; + lr1.name = "60Hz ExplicitGte"; + lr2.vote = LayerVoteType::NoVote; + lr2.name = "NoVote"; + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); + + lr1.vote = LayerVoteType::ExplicitGte; + lr1.desiredRefreshRate = 25_Hz; + lr1.name = "25Hz ExplicitGte"; + lr2.vote = LayerVoteType::NoVote; + lr2.name = "NoVote"; + EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers).modePtr); + + lr1.vote = LayerVoteType::ExplicitGte; + lr1.desiredRefreshRate = 91_Hz; + lr1.name = "91Hz ExplicitGte"; + lr2.vote = LayerVoteType::NoVote; + lr2.name = "NoVote"; + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr); + + lr1.vote = LayerVoteType::ExplicitGte; + lr1.desiredRefreshRate = 60_Hz; + lr1.name = "60Hz ExplicitGte"; + lr2.vote = LayerVoteType::ExplicitDefault; + lr2.desiredRefreshRate = 30_Hz; + lr2.name = "30Hz ExplicitDefault"; + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); + + lr1.vote = LayerVoteType::ExplicitGte; + lr1.desiredRefreshRate = 60_Hz; + lr1.name = "60Hz ExplicitGte"; + lr2.vote = LayerVoteType::ExplicitExactOrMultiple; + lr2.desiredRefreshRate = 30_Hz; + lr2.name = "30Hz ExplicitExactOrMultiple"; + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); + + lr1.vote = LayerVoteType::ExplicitGte; + lr1.desiredRefreshRate = 60_Hz; + lr1.name = "60Hz ExplicitGte"; + lr2.vote = LayerVoteType::ExplicitExactOrMultiple; + lr2.desiredRefreshRate = 60_Hz; + lr2.name = "60Hz ExplicitExactOrMultiple"; + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); + + lr1.vote = LayerVoteType::ExplicitGte; + lr1.desiredRefreshRate = 60_Hz; + lr1.name = "60Hz ExplicitGte"; + lr2.vote = LayerVoteType::ExplicitExactOrMultiple; + lr2.desiredRefreshRate = 90_Hz; + lr2.name = "90Hz ExplicitExactOrMultiple"; + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); + + lr1.vote = LayerVoteType::ExplicitGte; + lr1.desiredRefreshRate = 60_Hz; + lr1.name = "60Hz ExplicitGte"; + lr2.vote = LayerVoteType::ExplicitExactOrMultiple; + lr2.desiredRefreshRate = 120_Hz; + lr2.name = "120Hz ExplicitExactOrMultiple"; + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr); +} + TEST_P(RefreshRateSelectorTest, getMaxRefreshRatesByPolicy) { // The kModes_30_60_90 contains two kMode72_G1, kMode120_G1 which are from the // different group. |