diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-08-30 23:21:35 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-08-30 23:21:35 +0000 |
commit | 86d098ecf01c3401061aad14b2df4c43748d08df (patch) | |
tree | c8a0d70cdda8d25fec7306b3e29342b636de930e | |
parent | f9e6004fffd9ef8a518f2863b31a38ee027fa11d (diff) | |
parent | fad66b2c0b0dba8e6df0e023b5f199dbf0598968 (diff) | |
download | native-86d098ecf01c3401061aad14b2df4c43748d08df.tar.gz |
Snap for 9010110 from fad66b2c0b0dba8e6df0e023b5f199dbf0598968 to tm-qpr1-release
Change-Id: I81f03e13a3cce38abb56bf10e9dcaa21922bb218
3 files changed, 140 insertions, 50 deletions
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index ca8349636b..a48c921378 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -40,22 +40,26 @@ namespace { struct RefreshRateScore { DisplayModeIterator modeIt; - float score; + float overallScore; + struct { + float modeBelowThreshold; + float modeAboveThreshold; + } fixedRateBelowThresholdLayersScore; }; template <typename Iterator> const DisplayModePtr& getMaxScoreRefreshRate(Iterator begin, Iterator end) { const auto it = std::max_element(begin, end, [](RefreshRateScore max, RefreshRateScore current) { - const auto& [modeIt, score] = current; + const auto& [modeIt, overallScore, _] = current; std::string name = to_string(modeIt->second->getFps()); - ALOGV("%s scores %.2f", name.c_str(), score); + ALOGV("%s scores %.2f", name.c_str(), overallScore); - ATRACE_INT(name.c_str(), static_cast<int>(std::round(score * 100))); + ATRACE_INT(name.c_str(), static_cast<int>(std::round(overallScore * 100))); constexpr float kEpsilon = 0.0001f; - return score > max.score * (1 + kEpsilon); + return overallScore > max.overallScore * (1 + kEpsilon); }); return it->modeIt->second; @@ -151,31 +155,6 @@ std::pair<nsecs_t, nsecs_t> RefreshRateConfigs::getDisplayFrames(nsecs_t layerPe return {quotient, remainder}; } -bool RefreshRateConfigs::isVoteAllowed(const LayerRequirement& layer, Fps refreshRate) const { - using namespace fps_approx_ops; - - switch (layer.vote) { - case LayerVoteType::ExplicitExactOrMultiple: - case LayerVoteType::Heuristic: - if (mConfig.frameRateMultipleThreshold != 0 && - refreshRate >= Fps::fromValue(mConfig.frameRateMultipleThreshold) && - layer.desiredRefreshRate < Fps::fromValue(mConfig.frameRateMultipleThreshold / 2)) { - // Don't vote high refresh rates past the threshold for layers with a low desired - // refresh rate. For example, desired 24 fps with 120 Hz threshold means no vote for - // 120 Hz, but desired 60 fps should have a vote. - return false; - } - break; - case LayerVoteType::ExplicitDefault: - case LayerVoteType::ExplicitExact: - case LayerVoteType::Max: - case LayerVoteType::Min: - case LayerVoteType::NoVote: - break; - } - return true; -} - float RefreshRateConfigs::calculateNonExactMatchingLayerScoreLocked(const LayerRequirement& layer, Fps refreshRate) const { constexpr float kScoreForFractionalPairs = .8f; @@ -240,10 +219,6 @@ float RefreshRateConfigs::calculateNonExactMatchingLayerScoreLocked(const LayerR float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& layer, Fps refreshRate, bool isSeamlessSwitch) const { - if (!isVoteAllowed(layer, refreshRate)) { - return 0; - } - // Slightly prefer seamless switches. constexpr float kSeamedSwitchPenalty = 0.95f; const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty; @@ -300,6 +275,7 @@ auto RefreshRateConfigs::getBestRefreshRate(const std::vector<LayerRequirement>& auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequirement>& layers, GlobalSignals signals) const -> std::pair<DisplayModePtr, GlobalSignals> { + using namespace fps_approx_ops; ATRACE_CALL(); ALOGV("%s: %zu layers", __func__, layers.size()); @@ -409,7 +385,7 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire const auto weight = layer.weight; - for (auto& [modeIt, score] : scores) { + for (auto& [modeIt, overallScore, fixedRateBelowThresholdLayersScore] : scores) { const auto& [id, mode] = *modeIt; const bool isSeamlessSwitch = mode->getGroup() == mActiveModeIt->second->getGroup(); @@ -451,18 +427,92 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire continue; } - const auto layerScore = + const float layerScore = calculateLayerScoreLocked(layer, mode->getFps(), isSeamlessSwitch); - ALOGV("%s gives %s score of %.4f", formatLayerInfo(layer, weight).c_str(), - to_string(mode->getFps()).c_str(), layerScore); + const float weightedLayerScore = weight * layerScore; + + // Layer with fixed source has a special consideration which depends on the + // mConfig.frameRateMultipleThreshold. We don't want these layers to score + // refresh rates above the threshold, but we also don't want to favor the lower + // ones by having a greater number of layers scoring them. Instead, we calculate + // the score independently for these layers and later decide which + // refresh rates to add it. For example, desired 24 fps with 120 Hz threshold should not + // score 120 Hz, but desired 60 fps should contribute to the score. + const bool fixedSourceLayer = [](LayerVoteType vote) { + switch (vote) { + case LayerVoteType::ExplicitExactOrMultiple: + case LayerVoteType::Heuristic: + return true; + case LayerVoteType::NoVote: + case LayerVoteType::Min: + case LayerVoteType::Max: + case LayerVoteType::ExplicitDefault: + case LayerVoteType::ExplicitExact: + return false; + } + }(layer.vote); + const bool layerBelowThreshold = mConfig.frameRateMultipleThreshold != 0 && + layer.desiredRefreshRate < + Fps::fromValue(mConfig.frameRateMultipleThreshold / 2); + if (fixedSourceLayer && layerBelowThreshold) { + const bool modeAboveThreshold = + mode->getFps() >= Fps::fromValue(mConfig.frameRateMultipleThreshold); + if (modeAboveThreshold) { + ALOGV("%s gives %s fixed source (above threshold) score of %.4f", + formatLayerInfo(layer, weight).c_str(), to_string(mode->getFps()).c_str(), + layerScore); + fixedRateBelowThresholdLayersScore.modeAboveThreshold += weightedLayerScore; + } else { + ALOGV("%s gives %s fixed source (below threshold) score of %.4f", + formatLayerInfo(layer, weight).c_str(), to_string(mode->getFps()).c_str(), + layerScore); + fixedRateBelowThresholdLayersScore.modeBelowThreshold += weightedLayerScore; + } + } else { + ALOGV("%s gives %s score of %.4f", formatLayerInfo(layer, weight).c_str(), + to_string(mode->getFps()).c_str(), layerScore); + overallScore += weightedLayerScore; + } + } + } + + // We want to find the best refresh rate without the fixed source layers, + // so we could know whether we should add the modeAboveThreshold scores or not. + // If the best refresh rate is already above the threshold, it means that + // some non-fixed source layers already scored it, so we can just add the score + // for all fixed source layers, even the ones that are above the threshold. + const bool maxScoreAboveThreshold = [&] { + if (mConfig.frameRateMultipleThreshold == 0 || scores.empty()) { + return false; + } + + const auto maxScoreIt = + std::max_element(scores.begin(), scores.end(), + [](RefreshRateScore max, RefreshRateScore current) { + const auto& [modeIt, overallScore, _] = current; + return overallScore > max.overallScore; + }); + ALOGV("%s is the best refresh rate without fixed source layers. It is %s the threshold for " + "refresh rate multiples", + to_string(maxScoreIt->modeIt->second->getFps()).c_str(), + maxScoreAboveThreshold ? "above" : "below"); + return maxScoreIt->modeIt->second->getFps() >= + Fps::fromValue(mConfig.frameRateMultipleThreshold); + }(); - score += weight * layerScore; + // Now we can add the fixed rate layers score + for (auto& [modeIt, overallScore, fixedRateBelowThresholdLayersScore] : scores) { + overallScore += fixedRateBelowThresholdLayersScore.modeBelowThreshold; + if (maxScoreAboveThreshold) { + overallScore += fixedRateBelowThresholdLayersScore.modeAboveThreshold; } + ALOGV("%s adjusted overallScore is %.4f", to_string(modeIt->second->getFps()).c_str(), + overallScore); } - // Now that we scored all the refresh rates we need to pick the one that got the highest score. - // In case of a tie we will pick the higher refresh rate if any of the layers wanted Max, - // or the lower otherwise. + // Now that we scored all the refresh rates we need to pick the one that got the highest + // overallScore. In case of a tie we will pick the higher refresh rate if any of the layers + // wanted Max, or the lower otherwise. const DisplayModePtr& bestRefreshRate = maxVoteLayers > 0 ? getMaxScoreRefreshRate(scores.rbegin(), scores.rend()) : getMaxScoreRefreshRate(scores.begin(), scores.end()); @@ -471,7 +521,7 @@ auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequire // If we never scored any layers, then choose the rate from the primary // range instead of picking a random score from the app range. if (std::all_of(scores.begin(), scores.end(), - [](RefreshRateScore score) { return score.score == 0; })) { + [](RefreshRateScore score) { return score.overallScore == 0; })) { const DisplayModePtr& max = getMaxRefreshRateByPolicyLocked(anchorGroup); ALOGV("layers not scored - choose %s", to_string(max->getFps()).c_str()); return {max, kNoSignals}; @@ -575,7 +625,7 @@ RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverr continue; } - for (auto& [_, score] : scores) { + for (auto& [_, score, _1] : scores) { score = 0; } @@ -587,7 +637,7 @@ RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverr LOG_ALWAYS_FATAL_IF(layer->vote != LayerVoteType::ExplicitDefault && layer->vote != LayerVoteType::ExplicitExactOrMultiple && layer->vote != LayerVoteType::ExplicitExact); - for (auto& [modeIt, score] : scores) { + for (auto& [modeIt, score, _] : scores) { constexpr bool isSeamlessSwitch = true; const auto layerScore = calculateLayerScoreLocked(*layer, modeIt->second->getFps(), isSeamlessSwitch); @@ -605,7 +655,7 @@ RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverr // If we never scored any layers, we don't have a preferred frame rate if (std::all_of(scores.begin(), scores.end(), - [](RefreshRateScore score) { return score.score == 0; })) { + [](RefreshRateScore score) { return score.overallScore == 0; })) { continue; } diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index 05a8692f51..a79002e959 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -353,9 +353,6 @@ private: const Policy* getCurrentPolicyLocked() const REQUIRES(mLock); bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock); - // Returns whether the layer is allowed to vote for the given refresh rate. - bool isVoteAllowed(const LayerRequirement&, Fps) const; - // 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/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index fcde532b85..188fd58dea 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -564,9 +564,10 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes_mu TestableRefreshRateConfigs configs(kModes_30_60_72_90_120, kModeId60, {.frameRateMultipleThreshold = 120}); - std::vector<LayerRequirement> layers = {{.weight = 1.f}, {.weight = 1.f}}; + std::vector<LayerRequirement> layers = {{.weight = 1.f}, {.weight = 1.f}, {.weight = 1.f}}; auto& lr1 = layers[0]; auto& lr2 = layers[1]; + auto& lr3 = layers[2]; lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitDefault; @@ -639,6 +640,48 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes_mu lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.name = "90Hz ExplicitExactOrMultiple"; EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers)); + + lr1.desiredRefreshRate = 24_Hz; + lr1.vote = LayerVoteType::ExplicitExactOrMultiple; + lr1.name = "24Hz ExplicitExactOrMultiple"; + lr2.vote = LayerVoteType::Max; + lr2.name = "Max"; + EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers)); + + lr1.desiredRefreshRate = 24_Hz; + lr1.vote = LayerVoteType::ExplicitExactOrMultiple; + lr1.name = "24Hz ExplicitExactOrMultiple"; + lr2.desiredRefreshRate = 120_Hz; + lr2.vote = LayerVoteType::ExplicitDefault; + lr2.name = "120Hz ExplicitDefault"; + EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers)); + + lr1.desiredRefreshRate = 24_Hz; + lr1.vote = LayerVoteType::ExplicitExactOrMultiple; + lr1.name = "24Hz ExplicitExactOrMultiple"; + lr2.desiredRefreshRate = 120_Hz; + lr2.vote = LayerVoteType::ExplicitExact; + lr2.name = "120Hz ExplicitExact"; + EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers)); + + lr1.desiredRefreshRate = 10_Hz; + lr1.vote = LayerVoteType::ExplicitExactOrMultiple; + lr1.name = "30Hz ExplicitExactOrMultiple"; + lr2.desiredRefreshRate = 120_Hz; + lr2.vote = LayerVoteType::Heuristic; + lr2.name = "120Hz ExplicitExact"; + EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers)); + + lr1.desiredRefreshRate = 30_Hz; + lr1.vote = LayerVoteType::ExplicitExactOrMultiple; + lr1.name = "30Hz ExplicitExactOrMultiple"; + lr2.desiredRefreshRate = 30_Hz; + lr2.vote = LayerVoteType::ExplicitExactOrMultiple; + lr2.name = "30Hz ExplicitExactOrMultiple"; + lr3.vote = LayerVoteType::Heuristic; + lr3.desiredRefreshRate = 120_Hz; + lr3.name = "120Hz Heuristic"; + EXPECT_EQ(kMode120, configs.getBestRefreshRate(layers)); } TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60) { |