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

Commit ace3d054 authored by Ady Abraham's avatar Ady Abraham
Browse files

SF: add render frame rate to the scheduler

Schedule SF at the rate of the render frame rate instead of
the display refresh rate.

Test: SF unit tests
Bug: 257072060
Change-Id: Idaf9be5f25373d38c0ef6440f9f401dc90de7a91
parent 82251b19
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -18,19 +18,19 @@

#include <ftl/non_null.h>

#include "DisplayHardware/DisplayMode.h"
#include <scheduler/FrameRateMode.h>

namespace android::display {

struct DisplayModeRequest {
    ftl::NonNull<DisplayModePtr> modePtr;
    scheduler::FrameRateMode mode;

    // Whether to emit DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE.
    bool emitEvent = false;
};

inline bool operator==(const DisplayModeRequest& lhs, const DisplayModeRequest& rhs) {
    return lhs.modePtr == rhs.modePtr && lhs.emitEvent == rhs.emitEvent;
    return lhs.mode == rhs.mode && lhs.emitEvent == rhs.emitEvent;
}

} // namespace android::display
+31 −25
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args)
        mCompositionDisplay{args.compositionDisplay},
        mActiveModeFPSTrace("ActiveModeFPS -" + to_string(getId())),
        mActiveModeFPSHwcTrace("ActiveModeFPS_HWC -" + to_string(getId())),
        mRenderFrameRateFPSTrace("RenderRateFPS -" + to_string(getId())),
        mPhysicalOrientation(args.physicalOrientation),
        mIsPrimary(args.isPrimary),
        mRefreshRateSelector(std::move(args.refreshRateSelector)) {
@@ -195,35 +196,32 @@ bool DisplayDevice::isPoweredOn() const {
    return mPowerMode && *mPowerMode != hal::PowerMode::OFF;
}

void DisplayDevice::setActiveMode(DisplayModeId modeId, const display::DisplaySnapshot& snapshot) {
    const auto fpsOpt = snapshot.displayModes().get(modeId).transform(
            [](const DisplayModePtr& mode) { return mode->getFps(); });
void DisplayDevice::setActiveMode(DisplayModeId modeId, Fps displayFps, Fps renderFps) {
    ATRACE_INT(mActiveModeFPSTrace.c_str(), displayFps.getIntValue());
    ATRACE_INT(mRenderFrameRateFPSTrace.c_str(), renderFps.getIntValue());

    LOG_ALWAYS_FATAL_IF(!fpsOpt, "Unknown mode");
    const Fps fps = *fpsOpt;

    ATRACE_INT(mActiveModeFPSTrace.c_str(), fps.getIntValue());

    mRefreshRateSelector->setActiveModeId(modeId);
    mRefreshRateSelector->setActiveMode(modeId, renderFps);

    if (mRefreshRateOverlay) {
        mRefreshRateOverlay->changeRefreshRate(fps);
        mRefreshRateOverlay->changeRefreshRate(displayFps);
    }
}

status_t DisplayDevice::initiateModeChange(const ActiveModeInfo& info,
                                           const hal::VsyncPeriodChangeConstraints& constraints,
                                           hal::VsyncPeriodChangeTimeline* outTimeline) {
    if (!info.mode || info.mode->getPhysicalDisplayId() != getPhysicalId()) {
    if (!info.modeOpt || info.modeOpt->modePtr->getPhysicalDisplayId() != getPhysicalId()) {
        ALOGE("Trying to initiate a mode change to invalid mode %s on display %s",
              info.mode ? std::to_string(info.mode->getId().value()).c_str() : "null",
              info.modeOpt ? std::to_string(info.modeOpt->modePtr->getId().value()).c_str()
                           : "null",
              to_string(getId()).c_str());
        return BAD_VALUE;
    }
    mUpcomingActiveMode = info;
    ATRACE_INT(mActiveModeFPSHwcTrace.c_str(), info.mode->getFps().getIntValue());
    return mHwComposer.setActiveModeWithConstraints(getPhysicalId(), info.mode->getHwcId(),
                                                    constraints, outTimeline);
    ATRACE_INT(mActiveModeFPSHwcTrace.c_str(), info.modeOpt->modePtr->getFps().getIntValue());
    return mHwComposer.setActiveModeWithConstraints(getPhysicalId(),
                                                    info.modeOpt->modePtr->getHwcId(), constraints,
                                                    outTimeline);
}

nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const {
@@ -238,7 +236,7 @@ nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const {
        return vsyncPeriod;
    }

    return refreshRateSelector().getActiveModePtr()->getVsyncPeriod();
    return refreshRateSelector().getActiveMode().modePtr->getVsyncPeriod();
}

ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
@@ -422,7 +420,7 @@ void DisplayDevice::enableRefreshRateOverlay(bool enable, bool showSpinnner) {
    mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(fpsRange, showSpinnner);
    mRefreshRateOverlay->setLayerStack(getLayerStack());
    mRefreshRateOverlay->setViewport(getSize());
    mRefreshRateOverlay->changeRefreshRate(getActiveMode().getFps());
    mRefreshRateOverlay->changeRefreshRate(getActiveMode().modePtr->getFps());
}

bool DisplayDevice::onKernelTimerChanged(std::optional<DisplayModeId> desiredModeId,
@@ -445,13 +443,14 @@ void DisplayDevice::animateRefreshRateOverlay() {
    }
}

bool DisplayDevice::setDesiredActiveMode(const ActiveModeInfo& info) {
auto DisplayDevice::setDesiredActiveMode(const ActiveModeInfo& info) -> DesiredActiveModeAction {
    ATRACE_CALL();

    LOG_ALWAYS_FATAL_IF(!info.mode, "desired mode not provided");
    LOG_ALWAYS_FATAL_IF(getPhysicalId() != info.mode->getPhysicalDisplayId(), "DisplayId mismatch");
    LOG_ALWAYS_FATAL_IF(!info.modeOpt, "desired mode not provided");
    LOG_ALWAYS_FATAL_IF(getPhysicalId() != info.modeOpt->modePtr->getPhysicalDisplayId(),
                        "DisplayId mismatch");

    ALOGV("%s(%s)", __func__, to_string(*info.mode).c_str());
    ALOGV("%s(%s)", __func__, to_string(*info.modeOpt->modePtr).c_str());

    std::scoped_lock lock(mActiveModeLock);
    if (mDesiredActiveModeChanged) {
@@ -459,18 +458,25 @@ bool DisplayDevice::setDesiredActiveMode(const ActiveModeInfo& info) {
        const auto prevConfig = mDesiredActiveMode.event;
        mDesiredActiveMode = info;
        mDesiredActiveMode.event = mDesiredActiveMode.event | prevConfig;
        return false;
        return DesiredActiveModeAction::None;
    }

    const auto& desiredMode = *info.modeOpt->modePtr;

    // Check if we are already at the desired mode
    if (refreshRateSelector().getActiveModePtr()->getId() == info.mode->getId()) {
        return false;
    if (refreshRateSelector().getActiveMode().modePtr->getId() == desiredMode.getId()) {
        if (refreshRateSelector().getActiveMode() == info.modeOpt) {
            return DesiredActiveModeAction::None;
        }

        setActiveMode(desiredMode.getId(), desiredMode.getFps(), info.modeOpt->fps);
        return DesiredActiveModeAction::InitiateRenderRateSwitch;
    }

    // Initiate a mode change.
    mDesiredActiveModeChanged = true;
    mDesiredActiveMode = info;
    return true;
    return DesiredActiveModeAction::InitiateDisplayModeSwitch;
}

std::optional<DisplayDevice::ActiveModeInfo> DisplayDevice::getDesiredActiveMode() const {
+14 −8
Original line number Diff line number Diff line
@@ -190,33 +190,38 @@ public:
        using Event = scheduler::DisplayModeEvent;

        ActiveModeInfo() = default;
        ActiveModeInfo(DisplayModePtr mode, Event event) : mode(std::move(mode)), event(event) {}
        ActiveModeInfo(scheduler::FrameRateMode mode, Event event)
              : modeOpt(std::move(mode)), event(event) {}

        explicit ActiveModeInfo(display::DisplayModeRequest&& request)
              : ActiveModeInfo(std::move(request.modePtr).take(),
              : ActiveModeInfo(std::move(request.mode),
                               request.emitEvent ? Event::Changed : Event::None) {}

        DisplayModePtr mode;
        ftl::Optional<scheduler::FrameRateMode> modeOpt;
        Event event = Event::None;

        bool operator!=(const ActiveModeInfo& other) const {
            return mode != other.mode || event != other.event;
            return modeOpt != other.modeOpt || event != other.event;
        }
    };

    bool setDesiredActiveMode(const ActiveModeInfo&) EXCLUDES(mActiveModeLock);
    enum class DesiredActiveModeAction {
        None,
        InitiateDisplayModeSwitch,
        InitiateRenderRateSwitch
    };
    DesiredActiveModeAction setDesiredActiveMode(const ActiveModeInfo&) EXCLUDES(mActiveModeLock);
    std::optional<ActiveModeInfo> getDesiredActiveMode() const EXCLUDES(mActiveModeLock);
    void clearDesiredActiveModeState() EXCLUDES(mActiveModeLock);
    ActiveModeInfo getUpcomingActiveMode() const REQUIRES(kMainThreadContext) {
        return mUpcomingActiveMode;
    }

    const DisplayMode& getActiveMode() const REQUIRES(kMainThreadContext) {
    scheduler::FrameRateMode getActiveMode() const REQUIRES(kMainThreadContext) {
        return mRefreshRateSelector->getActiveMode();
    }

    // Precondition: DisplaySnapshot must contain a mode with DisplayModeId.
    void setActiveMode(DisplayModeId, const display::DisplaySnapshot&) REQUIRES(kMainThreadContext);
    void setActiveMode(DisplayModeId, Fps displayFps, Fps renderFps);

    status_t initiateModeChange(const ActiveModeInfo&,
                                const hal::VsyncPeriodChangeConstraints& constraints,
@@ -254,6 +259,7 @@ private:
    std::string mDisplayName;
    std::string mActiveModeFPSTrace;
    std::string mActiveModeFPSHwcTrace;
    std::string mRenderFrameRateFPSTrace;

    const ui::Rotation mPhysicalOrientation;
    ui::Rotation mOrientation = ui::ROTATION_0;
+1 −1
Original line number Diff line number Diff line
@@ -3597,7 +3597,7 @@ void Layer::onPostComposition(const DisplayDevice* display,
    }

    if (display) {
        const Fps refreshRate = display->refreshRateSelector().getActiveModePtr()->getFps();
        const Fps refreshRate = display->refreshRateSelector().getActiveMode().fps;
        const std::optional<Fps> renderRate =
                mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());

+32 −35
Original line number Diff line number Diff line
@@ -213,7 +213,7 @@ auto RefreshRateSelector::createFrameRateModes(
    std::vector<FrameRateMode> frameRateModes;
    frameRateModes.reserve(ratesMap.size());
    for (const auto& [key, mode] : ratesMap) {
        frameRateModes.emplace_back(FrameRateMode{key.fps, mode->second});
        frameRateModes.emplace_back(FrameRateMode{key.fps, ftl::as_non_null(mode->second)});
    }

    // We always want that the lowest frame rate will be corresponding to the
@@ -409,7 +409,7 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
    ATRACE_CALL();
    ALOGV("%s: %zu layers", __func__, layers.size());

    const auto& activeMode = *getActiveModeItLocked()->second;
    const auto& activeMode = *getActiveModeLocked().modePtr;

    // Keep the display at max frame rate for the duration of powering on the display.
    if (signals.powerOnImminent) {
@@ -842,7 +842,7 @@ std::optional<Fps> RefreshRateSelector::onKernelTimerChanged(

    const DisplayModePtr& current = desiredActiveModeId
            ? mDisplayModes.get(*desiredActiveModeId)->get()
            : getActiveModeItLocked()->second;
            : getActiveModeLocked().modePtr.get();

    const DisplayModePtr& min = mMinRefreshRateModeIt->second;
    if (current == min) {
@@ -854,11 +854,11 @@ std::optional<Fps> RefreshRateSelector::onKernelTimerChanged(
}

const DisplayModePtr& RefreshRateSelector::getMinRefreshRateByPolicyLocked() const {
    const auto& activeMode = *getActiveModeItLocked()->second;
    const auto& activeMode = *getActiveModeLocked().modePtr;

    for (const FrameRateMode& mode : mPrimaryFrameRates) {
        if (activeMode.getGroup() == mode.modePtr->getGroup()) {
            return mode.modePtr;
            return mode.modePtr.get();
        }
    }

@@ -866,12 +866,12 @@ const DisplayModePtr& RefreshRateSelector::getMinRefreshRateByPolicyLocked() con
          to_string(activeMode).c_str());

    // Default to the lowest refresh rate.
    return mPrimaryFrameRates.front().modePtr;
    return mPrimaryFrameRates.front().modePtr.get();
}

const DisplayModePtr& RefreshRateSelector::getMaxRefreshRateByPolicyLocked(int anchorGroup) const {
    const DisplayModePtr* maxByAnchor = &mPrimaryFrameRates.back().modePtr;
    const DisplayModePtr* max = &mPrimaryFrameRates.back().modePtr;
    const ftl::NonNull<DisplayModePtr>* maxByAnchor = &mPrimaryFrameRates.back().modePtr;
    const ftl::NonNull<DisplayModePtr>* max = &mPrimaryFrameRates.back().modePtr;

    bool maxByAnchorFound = false;
    for (auto it = mPrimaryFrameRates.rbegin(); it != mPrimaryFrameRates.rend(); ++it) {
@@ -888,13 +888,13 @@ const DisplayModePtr& RefreshRateSelector::getMaxRefreshRateByPolicyLocked(int a
    }

    if (maxByAnchorFound) {
        return *maxByAnchor;
        return maxByAnchor->get();
    }

    ALOGE("Can't find max refresh rate by policy with the same group %d", anchorGroup);

    // Default to the highest refresh rate.
    return *max;
    return max->get();
}

auto RefreshRateSelector::rankFrameRates(std::optional<int> anchorGroupOpt,
@@ -946,31 +946,26 @@ auto RefreshRateSelector::rankFrameRates(std::optional<int> anchorGroupOpt,
    return rankFrameRates(kNoAnchorGroup, refreshRateOrder, preferredDisplayModeOpt);
}

DisplayModePtr RefreshRateSelector::getActiveModePtr() const {
FrameRateMode RefreshRateSelector::getActiveMode() const {
    std::lock_guard lock(mLock);
    return getActiveModeItLocked()->second;
    return getActiveModeLocked();
}

const DisplayMode& RefreshRateSelector::getActiveMode() const {
    // Reads from kMainThreadContext do not require mLock.
    ftl::FakeGuard guard(mLock);
    return *mActiveModeIt->second;
}

DisplayModeIterator RefreshRateSelector::getActiveModeItLocked() const {
    // Reads under mLock do not require kMainThreadContext.
    return FTL_FAKE_GUARD(kMainThreadContext, mActiveModeIt);
const FrameRateMode& RefreshRateSelector::getActiveModeLocked() const {
    return *mActiveModeOpt;
}

void RefreshRateSelector::setActiveModeId(DisplayModeId modeId) {
void RefreshRateSelector::setActiveMode(DisplayModeId modeId, Fps renderFrameRate) {
    std::lock_guard lock(mLock);

    // Invalidate the cached invocation to getRankedFrameRates. This forces
    // the refresh rate to be recomputed on the next call to getRankedFrameRates.
    mGetRankedFrameRatesCache.reset();

    mActiveModeIt = mDisplayModes.find(modeId);
    LOG_ALWAYS_FATAL_IF(mActiveModeIt == mDisplayModes.end());
    const auto activeModeOpt = mDisplayModes.get(modeId);
    LOG_ALWAYS_FATAL_IF(!activeModeOpt);

    mActiveModeOpt.emplace(FrameRateMode{renderFrameRate, ftl::as_non_null(activeModeOpt->get())});
}

RefreshRateSelector::RefreshRateSelector(DisplayModes modes, DisplayModeId activeModeId,
@@ -1007,8 +1002,10 @@ void RefreshRateSelector::updateDisplayModes(DisplayModes modes, DisplayModeId a
    mGetRankedFrameRatesCache.reset();

    mDisplayModes = std::move(modes);
    mActiveModeIt = mDisplayModes.find(activeModeId);
    LOG_ALWAYS_FATAL_IF(mActiveModeIt == mDisplayModes.end());
    const auto activeModeOpt = mDisplayModes.get(activeModeId);
    LOG_ALWAYS_FATAL_IF(!activeModeOpt);
    mActiveModeOpt =
            FrameRateMode{activeModeOpt->get()->getFps(), ftl::as_non_null(activeModeOpt->get())};

    const auto sortedModes = sortByRefreshRate(mDisplayModes);
    mMinRefreshRateModeIt = sortedModes.front();
@@ -1064,6 +1061,7 @@ bool RefreshRateSelector::isPolicyValidLocked(const Policy& policy) const {

auto RefreshRateSelector::setPolicy(const PolicyVariant& policy) -> SetPolicyResult {
    Policy oldPolicy;
    PhysicalDisplayId displayId;
    {
        std::lock_guard lock(mLock);
        oldPolicy = *getCurrentPolicyLocked();
@@ -1103,9 +1101,10 @@ auto RefreshRateSelector::setPolicy(const PolicyVariant& policy) -> SetPolicyRes
            return SetPolicyResult::Unchanged;
        }
        constructAvailableRefreshRates();

        displayId = getActiveModeLocked().modePtr->getPhysicalDisplayId();
    }

    const auto displayId = getActiveMode().getPhysicalDisplayId();
    const unsigned numModeChanges = std::exchange(mNumModeSwitchesInPolicy, 0u);

    ALOGI("Display %s policy changed\n"
@@ -1132,12 +1131,10 @@ auto RefreshRateSelector::getDisplayManagerPolicy() const -> Policy {
    return mDisplayManagerPolicy;
}

bool RefreshRateSelector::isModeAllowed(DisplayModeId modeId) const {
bool RefreshRateSelector::isModeAllowed(const FrameRateMode& mode) const {
    std::lock_guard lock(mLock);
    return std::any_of(mAppRequestFrameRates.begin(), mAppRequestFrameRates.end(),
                       [modeId](const FrameRateMode& frameRateMode) {
                           return frameRateMode.modePtr->getId() == modeId;
                       });
    return std::find(mAppRequestFrameRates.begin(), mAppRequestFrameRates.end(), mode) !=
            mAppRequestFrameRates.end();
}

void RefreshRateSelector::constructAvailableRefreshRates() {
@@ -1211,7 +1208,7 @@ auto RefreshRateSelector::getIdleTimerAction() const -> KernelIdleTimerAction {
    }

    const DisplayModePtr& maxByPolicy =
            getMaxRefreshRateByPolicyLocked(getActiveModeItLocked()->second->getGroup());
            getMaxRefreshRateByPolicyLocked(getActiveModeLocked().modePtr->getGroup());
    if (minByPolicy == maxByPolicy) {
        // Turn on the timer when the min of the primary range is below the device min.
        if (const Policy* currentPolicy = getCurrentPolicyLocked();
@@ -1257,8 +1254,8 @@ void RefreshRateSelector::dump(utils::Dumper& dumper) const {

    std::lock_guard lock(mLock);

    const auto activeModeId = getActiveModeItLocked()->first;
    dumper.dump("activeModeId"sv, std::to_string(activeModeId.value()));
    const auto activeMode = getActiveModeLocked();
    dumper.dump("activeMode"sv, to_string(activeMode));

    dumper.dump("displayModes"sv);
    {
Loading