diff options
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=*/ |