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

Commit 8f2eea4c authored by Rachel Lee's avatar Rachel Lee
Browse files

Set frame rate GTE to Max for MRR

For animation, scroll/fling, and other velocity, the frame rate might
change after start, which can be specified with GTE setFrameRate.
However changing display refresh rate on an MRR
device will jank, so the stand-in solution is to equate GTE votes to Max
for MRR.

Bug: 330222554
Test: atest libsurfaceflinger_unittest
Test: ABTD
Change-Id: I95dda0048ed6ac749c226221f708bd1303924fdb
parent 0dd479e7
Loading
Loading
Loading
Loading
+14 −4
Original line number Diff line number Diff line
@@ -280,9 +280,18 @@ void LayerHistory::partitionLayers(nsecs_t now, bool isVrrDevice) {
                    case Layer::FrameRateCompatibility::Exact:
                        return LayerVoteType::ExplicitExact;
                    case Layer::FrameRateCompatibility::Gte:
                        if (isVrrDevice) {
                            return LayerVoteType::ExplicitGte;
                        } else {
                            // For MRR, treat GTE votes as Max because it is used for animations and
                            // scroll. MRR cannot change frame rate without jank, so it should
                            // prefer smoothness.
                            return LayerVoteType::Max;
                        }
                }
            }();
            const bool isValuelessVote = voteType == LayerVoteType::NoVote ||
                    voteType == LayerVoteType::Min || voteType == LayerVoteType::Max;

            if (FlagManager::getInstance().game_default_frame_rate()) {
                // Determine the layer frame rate considering the following priorities:
@@ -307,7 +316,8 @@ void LayerHistory::partitionLayers(nsecs_t now, bool isVrrDevice) {
                              gameModeFrameRateOverride.getIntValue());
                    }
                } else if (frameRate.isValid() && frameRate.isVoteValidForMrr(isVrrDevice)) {
                    info->setLayerVote({setFrameRateVoteType, frameRate.vote.rate,
                    info->setLayerVote({setFrameRateVoteType,
                                        isValuelessVote ? 0_Hz : frameRate.vote.rate,
                                        frameRate.vote.seamlessness, frameRate.category});
                    if (CC_UNLIKELY(mTraceEnabled)) {
                        trace(*info, gameFrameRateOverrideVoteType,
@@ -335,8 +345,8 @@ void LayerHistory::partitionLayers(nsecs_t now, bool isVrrDevice) {
            } else {
                if (frameRate.isValid() && frameRate.isVoteValidForMrr(isVrrDevice)) {
                    const auto type = info->isVisible() ? voteType : LayerVoteType::NoVote;
                    info->setLayerVote({type, frameRate.vote.rate, frameRate.vote.seamlessness,
                                        frameRate.category});
                    info->setLayerVote({type, isValuelessVote ? 0_Hz : frameRate.vote.rate,
                                        frameRate.vote.seamlessness, frameRate.category});
                } else {
                    if (!frameRate.isVoteValidForMrr(isVrrDevice)) {
                        ATRACE_FORMAT_INSTANT("Reset layer to ignore explicit vote on MRR %s: %s "
+19 −2
Original line number Diff line number Diff line
@@ -563,8 +563,25 @@ bool LayerInfo::FrameRate::isNoVote() const {
    return vote.type == FrameRateCompatibility::NoVote;
}

bool LayerInfo::FrameRate::isValuelessType() const {
    // For a valueless frame rate compatibility (type), the frame rate should be unspecified (0 Hz).
    if (!isApproxEqual(vote.rate, 0_Hz)) {
        return false;
    }
    switch (vote.type) {
        case FrameRateCompatibility::Min:
        case FrameRateCompatibility::NoVote:
            return true;
        case FrameRateCompatibility::Default:
        case FrameRateCompatibility::ExactOrMultiple:
        case FrameRateCompatibility::Exact:
        case FrameRateCompatibility::Gte:
            return false;
    }
}

bool LayerInfo::FrameRate::isValid() const {
    return isNoVote() || vote.rate.isValid() || category != FrameRateCategory::Default;
    return isValuelessType() || vote.rate.isValid() || category != FrameRateCategory::Default;
}

bool LayerInfo::FrameRate::isVoteValidForMrr(bool isVrrDevice) const {
@@ -572,7 +589,7 @@ bool LayerInfo::FrameRate::isVoteValidForMrr(bool isVrrDevice) const {
        return true;
    }

    if (category == FrameRateCategory::Default && vote.type != FrameRateCompatibility::Gte) {
    if (category == FrameRateCategory::Default) {
        return true;
    }

+3 −0
Original line number Diff line number Diff line
@@ -146,6 +146,9 @@ public:
        // selection.
        bool isNoVote() const;

        // Returns true if the FrameRate has a valid valueless (0 Hz) frame rate type.
        bool isValuelessType() const;

        // Checks whether the given FrameRate's vote specifications is valid for MRR devices
        // given the current flagging.
        bool isVoteValidForMrr(bool isVrrDevice) const;
+90 −6
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ namespace android::scheduler {
using MockLayer = android::mock::MockLayer;

using android::mock::createDisplayMode;
using android::mock::createVrrDisplayMode;

// WARNING: LEGACY TESTS FOR LEGACY FRONT END
// Update LayerHistoryIntegrationTest instead
@@ -138,11 +139,13 @@ protected:
        ASSERT_EQ(desiredRefreshRate, summary[0].desiredRefreshRate);
    }

    std::shared_ptr<RefreshRateSelector> mSelector =
            std::make_shared<RefreshRateSelector>(makeModes(createDisplayMode(DisplayModeId(0),
                                                                              LO_FPS),
                                                            createDisplayMode(DisplayModeId(1),
                                                                              HI_FPS)),
    static constexpr auto kVrrModeId = DisplayModeId(2);
    std::shared_ptr<RefreshRateSelector> mSelector = std::make_shared<RefreshRateSelector>(
            makeModes(createDisplayMode(DisplayModeId(0), LO_FPS),
                      createDisplayMode(DisplayModeId(1), HI_FPS),
                      createVrrDisplayMode(kVrrModeId, HI_FPS,
                                           hal::VrrConfig{.minFrameIntervalNs =
                                                                  HI_FPS.getPeriodNsecs()})),
            DisplayModeId(0));

    mock::SchedulerCallback mSchedulerCallback;
@@ -548,6 +551,87 @@ TEST_F(LayerHistoryTest, oneLayerExplicitExactVote) {
    EXPECT_EQ(0, frequentLayerCount(time));
}

TEST_F(LayerHistoryTest, oneLayerExplicitGte_vrr) {
    // Set the test to be on a vrr mode.
    SET_FLAG_FOR_TEST(flags::vrr_config, true);
    mSelector->setActiveMode(kVrrModeId, HI_FPS);

    auto layer = createLayer();
    EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
    EXPECT_CALL(*layer, getFrameRateForLayerTree())
            .WillRepeatedly(Return(Layer::FrameRate(33_Hz, Layer::FrameRateCompatibility::Gte,
                                                    Seamlessness::OnlySeamless,
                                                    FrameRateCategory::Default)));

    EXPECT_EQ(1, layerCount());
    EXPECT_EQ(0, activeLayerCount());

    nsecs_t time = systemTime();
    for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
        history().record(layer->getSequence(), layer->getLayerProps(), time, time,
                         LayerHistory::LayerUpdateType::Buffer);
        time += HI_FPS_PERIOD;
    }

    ASSERT_EQ(1, summarizeLayerHistory(time).size());
    EXPECT_EQ(1, activeLayerCount());
    EXPECT_EQ(1, frequentLayerCount(time));
    EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitGte, summarizeLayerHistory(time)[0].vote);
    EXPECT_EQ(33_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate);
    EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory);

    // layer became inactive, but the vote stays
    setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);
    time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
    ASSERT_EQ(1, summarizeLayerHistory(time).size());
    EXPECT_EQ(1, activeLayerCount());
    EXPECT_EQ(0, frequentLayerCount(time));
    EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitGte, summarizeLayerHistory(time)[0].vote);
    EXPECT_EQ(33_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate);
    EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory);
}

// Test for MRR device with VRR features enabled.
TEST_F(LayerHistoryTest, oneLayerExplicitGte_nonVrr) {
    SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, true);
    // The vrr_config flag is explicitly not set false because this test for an MRR device
    // should still work in a VRR-capable world.

    auto layer = createLayer();
    EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
    EXPECT_CALL(*layer, getFrameRateForLayerTree())
            .WillRepeatedly(Return(Layer::FrameRate(33_Hz, Layer::FrameRateCompatibility::Gte,
                                                    Seamlessness::OnlySeamless,
                                                    FrameRateCategory::Default)));

    EXPECT_EQ(1, layerCount());
    EXPECT_EQ(0, activeLayerCount());

    nsecs_t time = systemTime();
    for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
        history().record(layer->getSequence(), layer->getLayerProps(), time, time,
                         LayerHistory::LayerUpdateType::Buffer);
        time += HI_FPS_PERIOD;
    }

    ASSERT_EQ(1, summarizeLayerHistory(time).size());
    EXPECT_EQ(1, activeLayerCount());
    EXPECT_EQ(1, frequentLayerCount(time));
    EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
    EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate);
    EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory);

    // layer became infrequent, but the vote stays
    setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);
    time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
    ASSERT_EQ(1, summarizeLayerHistory(time).size());
    EXPECT_EQ(1, activeLayerCount());
    EXPECT_EQ(0, frequentLayerCount(time));
    EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
    EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate);
    EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory);
}

TEST_F(LayerHistoryTest, oneLayerExplicitVoteWithCategory_vrrFeatureOff) {
    SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, false);