Loading services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +31 −5 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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] = Loading Loading @@ -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; } Loading Loading @@ -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) { Loading @@ -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; } Loading Loading @@ -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) { Loading @@ -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", Loading services/surfaceflinger/Scheduler/RefreshRateConfigs.h +4 −0 Original line number Diff line number Diff line Loading @@ -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. // Loading services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +175 −2 Original line number Diff line number Diff line Loading @@ -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()); Loading @@ -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, Loading @@ -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), Loading Loading @@ -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()); } } Loading Loading @@ -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); Loading Loading @@ -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) { Loading Loading
services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +31 −5 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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] = Loading Loading @@ -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; } Loading Loading @@ -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) { Loading @@ -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; } Loading Loading @@ -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) { Loading @@ -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", Loading
services/surfaceflinger/Scheduler/RefreshRateConfigs.h +4 −0 Original line number Diff line number Diff line Loading @@ -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. // Loading
services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +175 −2 Original line number Diff line number Diff line Loading @@ -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()); Loading @@ -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, Loading @@ -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), Loading Loading @@ -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()); } } Loading Loading @@ -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); Loading Loading @@ -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) { Loading