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

Commit e7973bec authored by Marin Shalamanov's avatar Marin Shalamanov Committed by Android (Google) Code Review
Browse files

Merge "Tune RefreshRateConfigs for fractional refresh rates"

parents 4fb3da09 15a0fc65
Loading
Loading
Loading
Loading
+31 −5
Original line number Diff line number Diff line
@@ -140,6 +140,8 @@ float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& laye
        return 0;
    }

    constexpr float kScoreForFractionalPairs = .8f;

    // Slightly prefer seamless switches.
    constexpr float kSeamedSwitchPenalty = 0.95f;
    const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty;
@@ -156,19 +158,29 @@ float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& laye
    const auto layerPeriod = layer.desiredRefreshRate.getPeriodNsecs();
    if (layer.vote == LayerVoteType::ExplicitDefault) {
        // Find the actual rate the layer will render, assuming
        // that layerPeriod is the minimal time to render a frame
        // that layerPeriod is the minimal period to render a frame.
        // For example if layerPeriod is 20ms and displayPeriod is 16ms,
        // then the actualLayerPeriod will be 32ms, because it is the
        // smallest multiple of the display period which is >= layerPeriod.
        auto actualLayerPeriod = displayPeriod;
        int multiplier = 1;
        while (layerPeriod > actualLayerPeriod + MARGIN_FOR_PERIOD_CALCULATION) {
            multiplier++;
            actualLayerPeriod = displayPeriod * multiplier;
        }

        // Because of the threshold we used above it's possible that score is slightly
        // above 1.
        return std::min(1.0f,
                        static_cast<float>(layerPeriod) / static_cast<float>(actualLayerPeriod));
    }

    if (layer.vote == LayerVoteType::ExplicitExactOrMultiple ||
        layer.vote == LayerVoteType::Heuristic) {
        if (isFractionalPairOrMultiple(refreshRate.getFps(), layer.desiredRefreshRate)) {
            return kScoreForFractionalPairs * seamlessness;
        }

        // Calculate how many display vsyncs we need to present a single frame for this
        // layer
        const auto [displayFramesQuotient, displayFramesRemainder] =
@@ -421,7 +433,7 @@ RefreshRate RefreshRateConfigs::getBestRefreshRateLocked(

            const auto layerScore =
                    calculateLayerScoreLocked(layer, *scores[i].refreshRate, isSeamlessSwitch);
            ALOGV("%s gives %s score of %.2f", formatLayerInfo(layer, weight).c_str(),
            ALOGV("%s gives %s score of %.4f", formatLayerInfo(layer, weight).c_str(),
                  scores[i].refreshRate->getName().c_str(), layerScore);
            scores[i].score += weight * layerScore;
        }
@@ -582,7 +594,7 @@ RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverr

template <typename Iter>
const RefreshRate* RefreshRateConfigs::getBestRefreshRate(Iter begin, Iter end) const {
    constexpr auto EPSILON = 0.001f;
    constexpr auto kEpsilon = 0.0001f;
    const RefreshRate* bestRefreshRate = begin->refreshRate;
    float max = begin->score;
    for (auto i = begin; i != end; ++i) {
@@ -591,7 +603,7 @@ const RefreshRate* RefreshRateConfigs::getBestRefreshRate(Iter begin, Iter end)

        ATRACE_INT(refreshRate->getName().c_str(), round<int>(score * 100));

        if (score > max * (1 + EPSILON)) {
        if (score > max * (1 + kEpsilon)) {
            max = score;
            bestRefreshRate = refreshRate;
        }
@@ -910,7 +922,10 @@ RefreshRateConfigs::KernelIdleTimerAction RefreshRateConfigs::getIdleTimerAction
int RefreshRateConfigs::getFrameRateDivider(Fps displayFrameRate, Fps layerFrameRate) {
    // This calculation needs to be in sync with the java code
    // in DisplayManagerService.getDisplayInfoForFrameRateOverride
    constexpr float kThreshold = 0.1f;

    // The threshold must be smaller than 0.001 in order to differentiate
    // between the fractional pairs (e.g. 59.94 and 60).
    constexpr float kThreshold = 0.0009f;
    const auto numPeriods = displayFrameRate.getValue() / layerFrameRate.getValue();
    const auto numPeriodsRounded = std::round(numPeriods);
    if (std::abs(numPeriods - numPeriodsRounded) > kThreshold) {
@@ -920,6 +935,17 @@ int RefreshRateConfigs::getFrameRateDivider(Fps displayFrameRate, Fps layerFrame
    return static_cast<int>(numPeriodsRounded);
}

bool RefreshRateConfigs::isFractionalPairOrMultiple(Fps smaller, Fps bigger) {
    if (smaller.getValue() > bigger.getValue()) {
        return isFractionalPairOrMultiple(bigger, smaller);
    }

    const auto multiplier = std::round(bigger.getValue() / smaller.getValue());
    constexpr float kCoef = 1000.f / 1001.f;
    return bigger.equalsWithMargin(Fps(smaller.getValue() * multiplier / kCoef)) ||
            bigger.equalsWithMargin(Fps(smaller.getValue() * multiplier * kCoef));
}

void RefreshRateConfigs::dump(std::string& result) const {
    std::lock_guard lock(mLock);
    base::StringAppendF(&result, "DesiredDisplayModeSpecs (DisplayManager): %s\n\n",
+4 −0
Original line number Diff line number Diff line
@@ -335,6 +335,10 @@ public:
    // layer refresh rate.
    static int getFrameRateDivider(Fps displayFrameRate, Fps layerFrameRate);

    // Returns if the provided frame rates have a ratio t*1000/1001 or t*1001/1000
    // for an integer t.
    static bool isFractionalPairOrMultiple(Fps, Fps);

    using UidToFrameRateOverride = std::map<uid_t, Fps>;
    // Returns the frame rate override for each uid.
    //
+175 −2
Original line number Diff line number Diff line
@@ -98,9 +98,15 @@ protected:
    static inline const DisplayModeId HWC_CONFIG_ID_30 = DisplayModeId(4);
    static inline const DisplayModeId HWC_CONFIG_ID_25 = DisplayModeId(5);
    static inline const DisplayModeId HWC_CONFIG_ID_50 = DisplayModeId(6);
    static inline const DisplayModeId HWC_CONFIG_ID_24 = DisplayModeId(7);
    static inline const DisplayModeId HWC_CONFIG_ID_24_FRAC = DisplayModeId(8);
    static inline const DisplayModeId HWC_CONFIG_ID_30_FRAC = DisplayModeId(9);
    static inline const DisplayModeId HWC_CONFIG_ID_60_FRAC = DisplayModeId(10);

    // Test configs
    DisplayModePtr mConfig60 = createDisplayMode(HWC_CONFIG_ID_60, 0, Fps(60.0f).getPeriodNsecs());
    DisplayModePtr mConfig60Frac =
            createDisplayMode(HWC_CONFIG_ID_60_FRAC, 0, Fps(59.94f).getPeriodNsecs());
    DisplayModePtr mConfig90 = createDisplayMode(HWC_CONFIG_ID_90, 0, Fps(90.0f).getPeriodNsecs());
    DisplayModePtr mConfig90DifferentGroup =
            createDisplayMode(HWC_CONFIG_ID_90, 1, Fps(90.0f).getPeriodNsecs());
@@ -116,9 +122,15 @@ protected:
    DisplayModePtr mConfig30 = createDisplayMode(HWC_CONFIG_ID_30, 0, Fps(30.0f).getPeriodNsecs());
    DisplayModePtr mConfig30DifferentGroup =
            createDisplayMode(HWC_CONFIG_ID_30, 1, Fps(30.0f).getPeriodNsecs());
    DisplayModePtr mConfig30Frac =
            createDisplayMode(HWC_CONFIG_ID_30_FRAC, 0, Fps(29.97f).getPeriodNsecs());
    DisplayModePtr mConfig25 = createDisplayMode(HWC_CONFIG_ID_25, 0, Fps(25.0f).getPeriodNsecs());
    DisplayModePtr mConfig25DifferentGroup =
            createDisplayMode(HWC_CONFIG_ID_25, 1, Fps(25.0f).getPeriodNsecs());
    DisplayModePtr mConfig50 = createDisplayMode(HWC_CONFIG_ID_50, 0, Fps(50.0f).getPeriodNsecs());
    DisplayModePtr mConfig24 = createDisplayMode(HWC_CONFIG_ID_24, 0, Fps(24.0f).getPeriodNsecs());
    DisplayModePtr mConfig24Frac =
            createDisplayMode(HWC_CONFIG_ID_24_FRAC, 0, Fps(23.976f).getPeriodNsecs());

    // Test device configurations
    // The positions of the configs in the arrays below MUST match their IDs. For example,
@@ -145,6 +157,11 @@ protected:
                                       mConfig50};
    DisplayModes m60_120Device = {mConfig60, mConfig120};

    // This is a typical TV configuration.
    DisplayModes m24_25_30_50_60WithFracDevice = {mConfig24, mConfig24Frac, mConfig25,
                                                  mConfig30, mConfig30Frac, mConfig50,
                                                  mConfig60, mConfig60Frac};

    // Expected RefreshRate objects
    RefreshRate mExpected60Config = {mConfig60, RefreshRate::ConstructorTag(0)};
    RefreshRate mExpectedAlmost60Config = {createDisplayMode(HWC_CONFIG_ID_60, 0, 16666665),
@@ -1230,7 +1247,109 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitDefault) {
        const auto& refreshRate =
                refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false});
        EXPECT_TRUE(refreshRate.getFps().equalsWithMargin(Fps(test.second)))
                << "Expecting " << test.first << "fps => " << test.second << "Hz";
                << "Expecting " << test.first << "fps => " << test.second << "Hz"
                << " but it was " << refreshRate.getFps();
    }
}

TEST_F(RefreshRateConfigsTest,
       getBestRefreshRate_ExplicitExactOrMultiple_WithFractionalRefreshRates) {
    auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
    auto& lr = layers[0];

    // Test that 23.976 will choose 24 if 23.976 is not supported
    {
        android::DisplayModes modes = {mConfig24,     mConfig25, mConfig30,
                                       mConfig30Frac, mConfig60, mConfig60Frac};
        auto refreshRateConfigs =
                std::make_unique<RefreshRateConfigs>(modes, /*currentConfigId=*/HWC_CONFIG_ID_60);

        lr.vote = LayerVoteType::ExplicitExactOrMultiple;
        lr.desiredRefreshRate = Fps(23.976f);
        lr.name = "ExplicitExactOrMultiple 23.976 fps";
        EXPECT_EQ(HWC_CONFIG_ID_24,
                  refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
                          .getModeId());
    }

    // Test that 24 will choose 23.976 if 24 is not supported
    {
        android::DisplayModes modes = {mConfig24Frac, mConfig25, mConfig30,
                                       mConfig30Frac, mConfig60, mConfig60Frac};
        auto refreshRateConfigs =
                std::make_unique<RefreshRateConfigs>(modes, /*currentConfigId=*/HWC_CONFIG_ID_60);
        lr.desiredRefreshRate = Fps(24.f);
        lr.name = "ExplicitExactOrMultiple 24 fps";
        EXPECT_EQ(HWC_CONFIG_ID_24_FRAC,
                  refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
                          .getModeId());
    }

    // Test that 29.97 will prefer 59.94 over 60 and 30
    {
        android::DisplayModes modes = {mConfig24, mConfig24Frac, mConfig25,
                                       mConfig30, mConfig60,     mConfig60Frac};
        auto refreshRateConfigs =
                std::make_unique<RefreshRateConfigs>(modes, /*currentConfigId=*/HWC_CONFIG_ID_60);
        lr.desiredRefreshRate = Fps(29.97f);
        lr.name = "ExplicitExactOrMultiple 29.97f fps";
        EXPECT_EQ(HWC_CONFIG_ID_60_FRAC,
                  refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
                          .getModeId());
    }
}

TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExact_WithFractionalRefreshRates) {
    auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
    auto& lr = layers[0];

    // Test that voting for supported refresh rate will select this refresh rate
    {
        auto refreshRateConfigs =
                std::make_unique<RefreshRateConfigs>(m24_25_30_50_60WithFracDevice,
                                                     /*currentConfigId=*/HWC_CONFIG_ID_60);

        for (auto desiredRefreshRate : {23.976f, 24.f, 25.f, 29.97f, 30.f, 50.f, 59.94f, 60.f}) {
            lr.vote = LayerVoteType::ExplicitExact;
            lr.desiredRefreshRate = Fps(desiredRefreshRate);
            std::stringstream ss;
            ss << "ExplicitExact " << desiredRefreshRate << " fps";
            lr.name = ss.str();

            auto selecteRefreshRate =
                    refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false});

            EXPECT_TRUE(selecteRefreshRate.getFps().equalsWithMargin(lr.desiredRefreshRate))
                    << "Expecting " << lr.desiredRefreshRate << " but it was "
                    << selecteRefreshRate.getFps();
        }
    }

    // Test that 23.976 will choose 24 if 23.976 is not supported
    {
        android::DisplayModes modes = {mConfig24,     mConfig25, mConfig30,
                                       mConfig30Frac, mConfig60, mConfig60Frac};
        auto refreshRateConfigs =
                std::make_unique<RefreshRateConfigs>(modes, /*currentConfigId=*/HWC_CONFIG_ID_60);
        lr.vote = LayerVoteType::ExplicitExact;
        lr.desiredRefreshRate = Fps(23.976f);
        lr.name = "ExplicitExact 23.976 fps";
        EXPECT_EQ(HWC_CONFIG_ID_24,
                  refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
                          .getModeId());
    }

    // Test that 24 will choose 23.976 if 24 is not supported
    {
        android::DisplayModes modes = {mConfig24Frac, mConfig25, mConfig30,
                                       mConfig30Frac, mConfig60, mConfig60Frac};
        auto refreshRateConfigs =
                std::make_unique<RefreshRateConfigs>(modes, /*currentConfigId=*/HWC_CONFIG_ID_60);
        lr.desiredRefreshRate = Fps(24.f);
        lr.name = "ExplicitExact 24 fps";
        EXPECT_EQ(HWC_CONFIG_ID_24_FRAC,
                  refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
                          .getModeId());
    }
}

@@ -2028,6 +2147,29 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExactTouchBoost) {
              refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}));
}

TEST_F(RefreshRateConfigsTest, getBestRefreshRate_FractionalRefreshRates_ExactAndDefault) {
    RefreshRateConfigs::Config config = {.enableFrameRateOverride = true};
    auto refreshRateConfigs =
            std::make_unique<RefreshRateConfigs>(m24_25_30_50_60WithFracDevice,
                                                 /*currentConfigId=*/HWC_CONFIG_ID_60, config);

    auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 0.5f},
                                                LayerRequirement{.weight = 0.5f}};
    auto& explicitDefaultLayer = layers[0];
    auto& explicitExactOrMultipleLayer = layers[1];

    explicitExactOrMultipleLayer.vote = LayerVoteType::ExplicitExactOrMultiple;
    explicitExactOrMultipleLayer.name = "ExplicitExactOrMultiple";
    explicitExactOrMultipleLayer.desiredRefreshRate = Fps(60);

    explicitDefaultLayer.vote = LayerVoteType::ExplicitDefault;
    explicitDefaultLayer.name = "ExplicitDefault";
    explicitDefaultLayer.desiredRefreshRate = Fps(59.94f);

    EXPECT_EQ(mExpected60Config,
              refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
}

TEST_F(RefreshRateConfigsTest, testComparisonOperator) {
    EXPECT_TRUE(mExpected60Config < mExpected90Config);
    EXPECT_FALSE(mExpected60Config < mExpected60Config);
@@ -2116,7 +2258,38 @@ TEST_F(RefreshRateConfigsTest, getFrameRateDivider) {
    refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90);
    displayRefreshRate = refreshRateConfigs->getCurrentRefreshRate().getFps();
    EXPECT_EQ(4, RefreshRateConfigs::getFrameRateDivider(displayRefreshRate, Fps(22.5f)));
    EXPECT_EQ(4, RefreshRateConfigs::getFrameRateDivider(displayRefreshRate, Fps(22.6f)));

    EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivider(Fps(24.f), Fps(25.f)));
    EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivider(Fps(24.f), Fps(23.976f)));
    EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivider(Fps(30.f), Fps(29.97f)));
    EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivider(Fps(60.f), Fps(59.94f)));
}

TEST_F(RefreshRateConfigsTest, isFractionalPairOrMultiple) {
    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(23.976f), Fps(24.f)));
    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(24.f), Fps(23.976f)));

    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(29.97f), Fps(30.f)));
    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(30.f), Fps(29.97f)));

    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(59.94f), Fps(60.f)));
    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(60.f), Fps(59.94f)));

    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(29.97f), Fps(60.f)));
    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(60.f), Fps(29.97f)));

    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(59.94f), Fps(30.f)));
    EXPECT_TRUE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(30.f), Fps(59.94f)));

    const std::vector<float> refreshRates = {23.976f, 24.f, 25.f, 29.97f, 30.f, 50.f, 59.94f, 60.f};
    for (auto refreshRate : refreshRates) {
        EXPECT_FALSE(
                RefreshRateConfigs::isFractionalPairOrMultiple(Fps(refreshRate), Fps(refreshRate)));
    }

    EXPECT_FALSE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(24.f), Fps(25.f)));
    EXPECT_FALSE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(23.978f), Fps(25.f)));
    EXPECT_FALSE(RefreshRateConfigs::isFractionalPairOrMultiple(Fps(29.97f), Fps(59.94f)));
}

TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_noLayers) {