Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 37d46920 authored by Ady Abraham's avatar Ady Abraham
Browse files

SF: avoid changing refresh rate for ExplicitExact

When a layer with ExplicitExact vote is present and the corresponding
refresh rate is not available, the refresh rate should remain the same.

Bug: 246230302
Test: SF unit tests
Change-Id: I3e1712d6494fc9fc46b8d26fdae310231f57e7b1
parent 19a25ec0
Loading
Loading
Loading
Loading
+50 −16
Original line number Diff line number Diff line
@@ -314,7 +314,8 @@ auto RefreshRateConfigs::getRankedRefreshRatesLocked(const std::vector<LayerRequ
    // Keep the display at max refresh rate for the duration of powering on the display.
    if (signals.powerOnImminent) {
        ALOGV("Power On Imminent");
        return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Descending),
        return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Descending,
                                              /*preferredDisplayModeOpt*/ std::nullopt),
                GlobalSignals{.powerOnImminent = true}};
    }

@@ -374,7 +375,8 @@ auto RefreshRateConfigs::getRankedRefreshRatesLocked(const std::vector<LayerRequ
    // selected a refresh rate to see if we should apply touch boost.
    if (signals.touch && !hasExplicitVoteLayers) {
        ALOGV("Touch Boost");
        return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending),
        return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending,
                                              /*preferredDisplayModeOpt*/ std::nullopt),
                GlobalSignals{.touch = true}};
    }

@@ -386,20 +388,23 @@ auto RefreshRateConfigs::getRankedRefreshRatesLocked(const std::vector<LayerRequ

    if (!signals.touch && signals.idle && !(primaryRangeIsSingleRate && hasExplicitVoteLayers)) {
        ALOGV("Idle");
        return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Ascending),
        return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Ascending,
                                              /*preferredDisplayModeOpt*/ std::nullopt),
                GlobalSignals{.idle = true}};
    }

    if (layers.empty() || noVoteLayers == layers.size()) {
        ALOGV("No layers with votes");
        return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending),
        return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending,
                                              /*preferredDisplayModeOpt*/ std::nullopt),
                kNoSignals};
    }

    // Only if all layers want Min we should return Min
    if (noVoteLayers + minVoteLayers == layers.size()) {
        ALOGV("All layers Min");
        return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Ascending),
        return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Ascending,
                                              /*preferredDisplayModeOpt*/ std::nullopt),
                kNoSignals};
    }

@@ -560,13 +565,17 @@ auto RefreshRateConfigs::getRankedRefreshRatesLocked(const std::vector<LayerRequ
                       return RefreshRateRanking{score.modeIt->second, score.overallScore};
                   });

    const bool noLayerScore = std::all_of(scores.begin(), scores.end(), [](RefreshRateScore score) {
        return score.overallScore == 0;
    });

    if (primaryRangeIsSingleRate) {
        // 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.overallScore == 0; })) {
        if (noLayerScore) {
            ALOGV("Layers not scored");
            return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending),
            return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending,
                                                  /*preferredDisplayModeOpt*/ std::nullopt),
                    kNoSignals};
        } else {
            return {rankedRefreshRates, kNoSignals};
@@ -588,7 +597,8 @@ auto RefreshRateConfigs::getRankedRefreshRatesLocked(const std::vector<LayerRequ
    }();

    const auto& touchRefreshRates =
            getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending);
            getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending,
                                          /*preferredDisplayModeOpt*/ std::nullopt);
    using fps_approx_ops::operator<;

    if (signals.touch && explicitDefaultVoteLayers == 0 && touchBoostForExplicitExact &&
@@ -598,6 +608,15 @@ auto RefreshRateConfigs::getRankedRefreshRatesLocked(const std::vector<LayerRequ
        return {touchRefreshRates, GlobalSignals{.touch = true}};
    }

    // If we never scored any layers, and we don't favor high refresh rates, prefer to stay with the
    // current config
    if (noLayerScore && refreshRateOrder == RefreshRateOrder::Ascending) {
        const auto preferredDisplayMode = activeMode.getId();
        return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Ascending,
                                              preferredDisplayMode),
                kNoSignals};
    }

    return {rankedRefreshRates, kNoSignals};
}

@@ -765,15 +784,29 @@ const DisplayModePtr& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked(int an
}

std::vector<RefreshRateRanking> RefreshRateConfigs::getRefreshRatesByPolicyLocked(
        std::optional<int> anchorGroupOpt, RefreshRateOrder refreshRateOrder) const {
    std::vector<RefreshRateRanking> rankings;
        std::optional<int> anchorGroupOpt, RefreshRateOrder refreshRateOrder,
        std::optional<DisplayModeId> preferredDisplayModeOpt) const {
    std::deque<RefreshRateRanking> rankings;
    const auto makeRanking = [&](const DisplayModeIterator it) REQUIRES(mLock) {
        const auto& mode = it->second;
        if (anchorGroupOpt && mode->getGroup() != anchorGroupOpt) {
            return;
        }

        float score = calculateRefreshRateScoreForFps(mode->getFps());
        const bool inverseScore = (refreshRateOrder == RefreshRateOrder::Ascending);
        const float score = calculateRefreshRateScoreForFps(mode->getFps());
        if (!anchorGroupOpt || mode->getGroup() == anchorGroupOpt) {
            rankings.push_back(RefreshRateRanking{mode, inverseScore ? 1.0f / score : score});
        if (inverseScore) {
            score = 1.0f / score;
        }
        if (preferredDisplayModeOpt) {
            if (*preferredDisplayModeOpt == mode->getId()) {
                rankings.push_front(RefreshRateRanking{mode, /*score*/ 1.0f});
                return;
            }
            constexpr float kNonPreferredModePenalty = 0.95f;
            score *= kNonPreferredModePenalty;
        }
        rankings.push_back(RefreshRateRanking{mode, score});
    };

    if (refreshRateOrder == RefreshRateOrder::Ascending) {
@@ -783,14 +816,15 @@ std::vector<RefreshRateRanking> RefreshRateConfigs::getRefreshRatesByPolicyLocke
    }

    if (!rankings.empty() || !anchorGroupOpt) {
        return rankings;
        return {rankings.begin(), rankings.end()};
    }

    ALOGW("Can't find %s refresh rate by policy with the same mode group"
          " as the mode group %d",
          refreshRateOrder == RefreshRateOrder::Ascending ? "min" : "max", anchorGroupOpt.value());

    return getRefreshRatesByPolicyLocked(/*anchorGroupOpt*/ std::nullopt, refreshRateOrder);
    return getRefreshRatesByPolicyLocked(/*anchorGroupOpt*/ std::nullopt, refreshRateOrder,
                                         preferredDisplayModeOpt);
}

DisplayModePtr RefreshRateConfigs::getActiveModePtr() const {
+3 −3
Original line number Diff line number Diff line
@@ -375,9 +375,9 @@ private:

    // Returns the rankings in RefreshRateOrder. May change at runtime.
    // Only uses the primary range, not the app request range.
    std::vector<RefreshRateRanking> getRefreshRatesByPolicyLocked(std::optional<int> anchorGroupOpt,
                                                                  RefreshRateOrder) const
            REQUIRES(mLock);
    std::vector<RefreshRateRanking> getRefreshRatesByPolicyLocked(
            std::optional<int> anchorGroupOpt, RefreshRateOrder,
            std::optional<DisplayModeId> preferredDisplayModeOpt) const REQUIRES(mLock);

    const Policy* getCurrentPolicyLocked() const REQUIRES(mLock);
    bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock);
+15 −24
Original line number Diff line number Diff line
@@ -77,7 +77,9 @@ struct TestableRefreshRateConfigs : RefreshRateConfigs {
    std::vector<RefreshRateRanking> getRefreshRatesByPolicy(
            std::optional<int> anchorGroupOpt, RefreshRateOrder refreshRateOrder) const {
        std::lock_guard lock(mLock);
        return RefreshRateConfigs::getRefreshRatesByPolicyLocked(anchorGroupOpt, refreshRateOrder);
        return RefreshRateConfigs::
                getRefreshRatesByPolicyLocked(anchorGroupOpt, refreshRateOrder,
                                              /*preferredDisplayModeOpt*/ std::nullopt);
    }

    const std::vector<Fps>& knownFrameRates() const { return mKnownFrameRates; }
@@ -344,6 +346,18 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_noLayers) {
    }
}

TEST_F(RefreshRateConfigsTest, getBestRefreshRate_exactDontChangeRefreshRateWhenNotInPolicy) {
    TestableRefreshRateConfigs configs(kModes_30_60_72_90_120, kModeId72);

    std::vector<LayerRequirement> layers = {{.weight = 1.f}};
    layers[0].vote = LayerVoteType::ExplicitExact;
    layers[0].desiredRefreshRate = 120_Hz;

    EXPECT_EQ(SetPolicyResult::Changed,
              configs.setDisplayManagerPolicy({kModeId72, {0_Hz, 90_Hz}}));
    EXPECT_EQ(kMode72, configs.getBestRefreshRate(layers));
}

TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_90) {
    TestableRefreshRateConfigs configs(kModes_60_90, kModeId60);

@@ -1318,29 +1332,6 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExact_WithFractionalRe
            EXPECT_EQ(lr.desiredRefreshRate, configs.getBestRefreshRate(layers)->getFps());
        }
    }

    // Test that 23.976 will choose 24 if 23.976 is not supported
    {
        TestableRefreshRateConfigs configs(makeModes(kMode24, kMode25, kMode30, kMode30Frac,
                                                     kMode60, kMode60Frac),
                                           kModeId60);

        lr.vote = LayerVoteType::ExplicitExact;
        lr.desiredRefreshRate = 23.976_Hz;
        lr.name = "ExplicitExact 23.976 Hz";
        EXPECT_EQ(kModeId24, configs.getBestRefreshRate(layers)->getId());
    }

    // Test that 24 will choose 23.976 if 24 is not supported
    {
        TestableRefreshRateConfigs configs(makeModes(kMode24Frac, kMode25, kMode30, kMode30Frac,
                                                     kMode60, kMode60Frac),
                                           kModeId60);

        lr.desiredRefreshRate = 24_Hz;
        lr.name = "ExplicitExact 24 Hz";
        EXPECT_EQ(kModeId24Frac, configs.getBestRefreshRate(layers)->getId());
    }
}

TEST_F(RefreshRateConfigsTest,