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

Commit aa5f85e8 authored by Su Hong Koo's avatar Su Hong Koo Committed by Android (Google) Code Review
Browse files

Merge "SF: Prefer external displays as pacesetters given equal refresh rates" into main

parents 58f4d57e 342b3bed
Loading
Loading
Loading
Loading
+29 −8
Original line number Diff line number Diff line
@@ -162,6 +162,7 @@ PhysicalDisplayId Scheduler::selectPacesetterDisplayLocked(
    // The first display should be the new pacesetter if none of the displays are powered on.
    const auto& [firstDisplayId, firstDisplay] = *mDisplays.begin();
    PhysicalDisplayId newPacesetterId = firstDisplayId;
    ui::DisplayConnectionType newPacesetterConnectionType = firstDisplay.connectionType;
    // Only assigning the actual refresh rate if the first display is powered on ensures that any
    // other powered-on display will take over the new pacesetter designation regardless of its
    // refresh rate.
@@ -179,24 +180,44 @@ PhysicalDisplayId Scheduler::selectPacesetterDisplayLocked(
        const Fps displayVsyncRate = display.selectorPtr->getActiveMode().modePtr->getVsyncRate();
        if (isStrictlyLess(newPacesetterVsyncRate, displayVsyncRate)) {
            newPacesetterId = id;
            newPacesetterConnectionType = display.connectionType;
            newPacesetterVsyncRate = displayVsyncRate;
        }
    }

    // The slack in the difference between refresh rate difference to consider them roughly equal
    // for pacesetter selection purposes. E.g. 59.98 and 60.02Hz Should be considered roughly equal.
    const auto isVsyncRateApproxEqual = [&](const Display& display, Fps otherFps) -> bool {
        constexpr float kRefreshRateEpsilon = 0.1f;
        const Fps displayVsyncRate = display.selectorPtr->getActiveMode().modePtr->getVsyncRate();
        return std::abs(displayVsyncRate.getValue() - otherFps.getValue()) < kRefreshRateEpsilon;
    };

    // If the current pacesetter display is powered on and its refresh rate is not too far off from
    // the newly selected pacesetter display, prefer to keep the current one to avoid churn.
    if (const auto pacesetterOpt = pacesetterDisplayLocked()) {
        const auto& pacesetter = pacesetterOpt->get();
        if (pacesetter.powerMode == hal::PowerMode::ON) {
            const Fps currentPacesetterVsyncRate =
            if (isVsyncRateApproxEqual(pacesetter, newPacesetterVsyncRate)) {
                newPacesetterId = pacesetter.displayId;
                newPacesetterConnectionType = pacesetter.connectionType;
                newPacesetterVsyncRate =
                        pacesetter.selectorPtr->getActiveMode().modePtr->getVsyncRate();
            const float rateDiff =
                    newPacesetterVsyncRate.getValue() - currentPacesetterVsyncRate.getValue();
            constexpr float kRefreshRateEpsilon = 0.1f;
            }
        }
    }

            if (rateDiff < kRefreshRateEpsilon) {
                newPacesetterId = pacesetter.displayId;
                newPacesetterVsyncRate = currentPacesetterVsyncRate;
    // Prefer external displays as pacesetter, as it is more likely the external display will be the
    // user's main display.
    if (newPacesetterConnectionType != ui::DisplayConnectionType::External) {
        for (const auto& [id, display] : mDisplays) {
            if (display.powerMode != hal::PowerMode::ON ||
                display.connectionType != ui::DisplayConnectionType::External) {
                continue;
            }

            if (isVsyncRateApproxEqual(display, newPacesetterVsyncRate)) {
                return id;
            }
        }
    }
+20 −0
Original line number Diff line number Diff line
@@ -1539,6 +1539,26 @@ TEST_F(SelectPacesetterDisplayTest, TwoDisplaysWithinEpsilon) FTL_FAKE_GUARD(kMa
    EXPECT_EQ(mScheduler->pacesetterDisplayId(), kDisplayId1);
}

TEST_F(SelectPacesetterDisplayTest, SameRefreshRateOneInternalOneExternal)
FTL_FAKE_GUARD(kMainThreadContext) {
    SET_FLAG_FOR_TEST(flags::pacesetter_selection, true);

    constexpr PhysicalDisplayId kActiveDisplayId = kDisplayId1;
    mScheduler->registerDisplay(kDisplayId1, ui::DisplayConnectionType::Internal,
                                std::make_shared<RefreshRateSelector>(kDisplay1Modes,
                                                                      kDisplay1Mode60->getId()),
                                kActiveDisplayId);
    mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON);

    auto selector2 =
            std::make_shared<RefreshRateSelector>(kDisplay2Modes, kDisplay2Mode60->getId());
    mScheduler->registerDisplay(kDisplayId2, ui::DisplayConnectionType::External, selector2,
                                kActiveDisplayId);
    mScheduler->setDisplayPowerMode(kDisplayId2, hal::PowerMode::ON);

    EXPECT_EQ(mScheduler->pacesetterDisplayId(), kDisplayId2);
}

TEST_F(SchedulerTest, selectorPtrForLayerStack) FTL_FAKE_GUARD(kMainThreadContext) {
    SET_FLAG_FOR_TEST(flags::follower_arbitrary_refresh_rate_selection, true);