diff options
| author | 2022-01-26 17:51:32 +0000 | |
|---|---|---|
| committer | 2022-01-26 17:51:32 +0000 | |
| commit | 2d9f9037b02dc0cfbea5679dd428833b9e57d1cc (patch) | |
| tree | 04bb9ba15527f502b77aee0c32c806e88ca170c3 | |
| parent | 16257f6e7d11804b83750981b5257861814e5f7c (diff) | |
| parent | e09237fbc1a3afcd2561f7ecf60349a690c13907 (diff) | |
Tune RefreshRateConfigs for fractional refresh rates am: e09237fbc1
Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/1953898
Change-Id: Ib63ee14b3a3cdcfae7a3b82f58f0c6f82abf3025
3 files changed, 201 insertions, 5 deletions
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 73b7b6365c..ddc05a7da8 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -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;          } @@ -924,6 +936,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", diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index dfd13953e7..2157675e1e 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -342,6 +342,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.      // diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index 3b2bd818b7..407f6903ec 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -99,9 +99,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()); @@ -117,9 +123,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, @@ -146,6 +158,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 = {HWC_CONFIG_ID_60, mConfig60, Fps(60),                                       RefreshRate::ConstructorTag(0)}; @@ -1237,7 +1254,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());      }  } @@ -2035,6 +2154,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); @@ -2130,6 +2272,33 @@ TEST_F(RefreshRateConfigsTest, getFrameRateDivider) {      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) {      auto refreshRateConfigs =              std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/  |