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

Commit d1c36ee0 authored by Ady Abraham's avatar Ady Abraham Committed by Android (Google) Code Review
Browse files

Merge "SF: add render frame rate dimension to RefreshRateSelector"

parents 5866b697 68636061
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1123,7 +1123,7 @@ bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* tran

    // We return whether this layer ot its children has a vote. We ignore ExactOrMultiple votes for
    // the same reason we are allowing touch boost for those layers. See
    // RefreshRateSelector::rankRefreshRates for details.
    // RefreshRateSelector::rankFrameRates for details.
    const auto layerVotedWithDefaultCompatibility =
            frameRate.rate.isValid() && frameRate.type == FrameRateCompatibility::Default;
    const auto layerVotedWithNoVote = frameRate.type == FrameRateCompatibility::NoVote;
+268 −148

File changed.

Preview size limit exceeded, changes collapsed.

+64 −27
Original line number Diff line number Diff line
@@ -24,9 +24,11 @@

#include <ftl/concat.h>
#include <ftl/optional.h>
#include <ftl/unit.h>
#include <gui/DisplayEventReceiver.h>

#include <scheduler/Fps.h>
#include <scheduler/FrameRateMode.h>
#include <scheduler/Seamlessness.h>

#include "DisplayHardware/DisplayMode.h"
@@ -58,6 +60,9 @@ public:
    static constexpr nsecs_t MARGIN_FOR_PERIOD_CALCULATION =
            std::chrono::nanoseconds(800us).count();

    // The lowest Render Frame Rate that will ever be selected
    static constexpr Fps kMinSupportedFrameRate = 20_Hz;

    class Policy {
        static constexpr int kAllowGroupSwitchingDefault = false;

@@ -196,12 +201,12 @@ public:
        }
    };

    struct ScoredRefreshRate {
        DisplayModePtr modePtr;
    struct ScoredFrameRate {
        FrameRateMode frameRateMode;
        float score = 0.0f;

        bool operator==(const ScoredRefreshRate& other) const {
            return modePtr == other.modePtr && score == other.score;
        bool operator==(const ScoredFrameRate& other) const {
            return frameRateMode == other.frameRateMode && score == other.score;
        }

        static bool scoresEqual(float lhs, float rhs) {
@@ -210,25 +215,25 @@ public:
        }

        struct DescendingScore {
            bool operator()(const ScoredRefreshRate& lhs, const ScoredRefreshRate& rhs) const {
            bool operator()(const ScoredFrameRate& lhs, const ScoredFrameRate& rhs) const {
                return lhs.score > rhs.score && !scoresEqual(lhs.score, rhs.score);
            }
        };
    };

    using RefreshRateRanking = std::vector<ScoredRefreshRate>;
    using FrameRateRanking = std::vector<ScoredFrameRate>;

    struct RankedRefreshRates {
        RefreshRateRanking ranking; // Ordered by descending score.
    struct RankedFrameRates {
        FrameRateRanking ranking; // Ordered by descending score.
        GlobalSignals consideredSignals;

        bool operator==(const RankedRefreshRates& other) const {
        bool operator==(const RankedFrameRates& other) const {
            return ranking == other.ranking && consideredSignals == other.consideredSignals;
        }
    };

    RankedRefreshRates getRankedRefreshRates(const std::vector<LayerRequirement>&,
                                             GlobalSignals) const EXCLUDES(mLock);
    RankedFrameRates getRankedFrameRates(const std::vector<LayerRequirement>&, GlobalSignals) const
            EXCLUDES(mLock);

    FpsRange getSupportedRefreshRateRange() const EXCLUDES(mLock) {
        std::lock_guard lock(mLock);
@@ -257,9 +262,12 @@ public:

            // Override the frame rate for an app to a value which is also
            // a display refresh rate
            EnabledForNativeRefreshRates,
            AppOverrideNativeRefreshRates,

            // Override the frame rate for an app to any value
            AppOverride,

            // Override the frame rate for all apps and all values.
            Enabled,

            ftl_last = Enabled
@@ -291,10 +299,13 @@ public:

    // Returns whether switching modes (refresh rate or resolution) is possible.
    // TODO(b/158780872): Consider HAL support, and skip frame rate detection if the modes only
    // differ in resolution.
    //  differ in resolution. Once Config::FrameRateOverride::Enabled becomes the default,
    //  we can probably remove canSwitch altogether since all devices will be able
    //  to switch to a frame rate divisor.
    bool canSwitch() const EXCLUDES(mLock) {
        std::lock_guard lock(mLock);
        return mDisplayModes.size() > 1;
        return mDisplayModes.size() > 1 ||
                mFrameRateOverrideConfig == Config::FrameRateOverride::Enabled;
    }

    // Class to enumerate options around toggling the kernel timer on and off.
@@ -307,10 +318,14 @@ public:
    // refresh rates.
    KernelIdleTimerAction getIdleTimerAction() const;

    bool supportsFrameRateOverrideByContent() const {
    bool supportsAppFrameRateOverrideByContent() const {
        return mFrameRateOverrideConfig != Config::FrameRateOverride::Disabled;
    }

    bool supportsFrameRateOverride() const {
        return mFrameRateOverrideConfig == Config::FrameRateOverride::Enabled;
    }

    // Return the display refresh rate divisor to match the layer
    // frame rate, or 0 if the display refresh rate is not a multiple of the
    // layer refresh rate.
@@ -387,8 +402,8 @@ private:
    // See mActiveModeIt for thread safety.
    DisplayModeIterator getActiveModeItLocked() const REQUIRES(mLock);

    RankedRefreshRates getRankedRefreshRatesLocked(const std::vector<LayerRequirement>&,
                                                   GlobalSignals) const REQUIRES(mLock);
    RankedFrameRates getRankedFrameRatesLocked(const std::vector<LayerRequirement>& layers,
                                               GlobalSignals signals) const REQUIRES(mLock);

    // Returns number of display frames and remainder when dividing the layer refresh period by
    // display refresh period.
@@ -404,18 +419,24 @@ private:

    struct RefreshRateScoreComparator;

    enum class RefreshRateOrder { Ascending, Descending };
    enum class RefreshRateOrder {
        Ascending,
        Descending,

        ftl_last = Descending
    };

    // Only uses the primary range, not the app request range.
    RefreshRateRanking rankRefreshRates(std::optional<int> anchorGroupOpt, RefreshRateOrder,
                                        std::optional<DisplayModeId> preferredDisplayModeOpt =
                                                std::nullopt) const REQUIRES(mLock);
    FrameRateRanking rankFrameRates(
            std::optional<int> anchorGroupOpt, RefreshRateOrder refreshRateOrder,
            std::optional<DisplayModeId> preferredDisplayModeOpt = std::nullopt) const
            REQUIRES(mLock);

    const Policy* getCurrentPolicyLocked() const REQUIRES(mLock);
    bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock);

    // Returns the refresh rate score as a ratio to max refresh rate, which has a score of 1.
    float calculateRefreshRateScoreForFps(Fps refreshRate) const REQUIRES(mLock);
    float calculateDistanceScoreFromMax(Fps refreshRate) const REQUIRES(mLock);
    // calculates a score for a layer. Used to determine the display refresh rate
    // and the frame rate override for certains applications.
    float calculateLayerScoreLocked(const LayerRequirement&, Fps refreshRate,
@@ -436,11 +457,27 @@ private:
                                                             : mIdleTimerCallbacks->platform;
    }

    bool isNativeRefreshRate(Fps fps) const REQUIRES(mLock) {
        LOG_ALWAYS_FATAL_IF(mConfig.enableFrameRateOverride !=
                                    Config::FrameRateOverride::AppOverrideNativeRefreshRates,
                            "should only be called when "
                            "Config::FrameRateOverride::AppOverrideNativeRefreshRates is used");
        return mAppOverrideNativeRefreshRates.contains(fps);
    }

    std::vector<FrameRateMode> createFrameRateModes(
            std::function<bool(const DisplayMode&)>&& filterModes, const FpsRange&) const
            REQUIRES(mLock);

    // The display modes of the active display. The DisplayModeIterators below are pointers into
    // this container, so must be invalidated whenever the DisplayModes change. The Policy below
    // is also dependent, so must be reset as well.
    DisplayModes mDisplayModes GUARDED_BY(mLock);

    // Set of supported display refresh rates for easy lookup
    // when FrameRateOverride::AppOverrideNativeRefreshRates is in use.
    ftl::SmallMap<Fps, ftl::Unit, 8, FpsApproxEqual> mAppOverrideNativeRefreshRates;

    // Written under mLock exclusively from kMainThreadContext, so reads from kMainThreadContext
    // need not be under mLock.
    DisplayModeIterator mActiveModeIt GUARDED_BY(mLock) GUARDED_BY(kMainThreadContext);
@@ -449,8 +486,8 @@ private:
    DisplayModeIterator mMaxRefreshRateModeIt GUARDED_BY(mLock);

    // Display modes that satisfy the Policy's ranges, filtered and sorted by refresh rate.
    std::vector<DisplayModeIterator> mPrimaryRefreshRates GUARDED_BY(mLock);
    std::vector<DisplayModeIterator> mAppRequestRefreshRates GUARDED_BY(mLock);
    std::vector<FrameRateMode> mPrimaryFrameRates GUARDED_BY(mLock);
    std::vector<FrameRateMode> mAppRequestFrameRates GUARDED_BY(mLock);

    Policy mDisplayManagerPolicy GUARDED_BY(mLock);
    std::optional<Policy> mOverridePolicy GUARDED_BY(mLock);
@@ -466,11 +503,11 @@ private:
    const Config mConfig;
    Config::FrameRateOverride mFrameRateOverrideConfig;

    struct GetRankedRefreshRatesCache {
    struct GetRankedFrameRatesCache {
        std::pair<std::vector<LayerRequirement>, GlobalSignals> arguments;
        RankedRefreshRates result;
        RankedFrameRates result;
    };
    mutable std::optional<GetRankedRefreshRatesCache> mGetRankedRefreshRatesCache GUARDED_BY(mLock);
    mutable std::optional<GetRankedFrameRatesCache> mGetRankedFrameRatesCache GUARDED_BY(mLock);

    // Declare mIdleTimer last to ensure its thread joins before the mutex/callbacks are destroyed.
    std::mutex mIdleTimerCallbacksMutex;
+14 −11
Original line number Diff line number Diff line
@@ -152,7 +152,7 @@ std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource(

std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const {
    const bool supportsFrameRateOverrideByContent =
            leaderSelectorPtr()->supportsFrameRateOverrideByContent();
            leaderSelectorPtr()->supportsAppFrameRateOverrideByContent();
    return mFrameRateOverrideMappings
            .getFrameRateOverrideForUid(uid, supportsFrameRateOverrideByContent);
}
@@ -268,7 +268,7 @@ void Scheduler::onScreenReleased(ConnectionHandle handle) {

void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) {
    const bool supportsFrameRateOverrideByContent =
            leaderSelectorPtr()->supportsFrameRateOverrideByContent();
            leaderSelectorPtr()->supportsAppFrameRateOverrideByContent();

    std::vector<FrameRateOverride> overrides =
            mFrameRateOverrideMappings.getAllFrameRateOverrides(supportsFrameRateOverrideByContent);
@@ -707,7 +707,7 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals
auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap {
    ATRACE_CALL();

    using RankedRefreshRates = RefreshRateSelector::RankedRefreshRates;
    using RankedRefreshRates = RefreshRateSelector::RankedFrameRates;
    display::PhysicalDisplayVector<RankedRefreshRates> perDisplayRanking;

    // Tallies the score of a refresh rate across `displayCount` displays.
@@ -726,9 +726,10 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap {

    for (const auto& [id, selectorPtr] : mRefreshRateSelectors) {
        auto rankedRefreshRates =
                selectorPtr->getRankedRefreshRates(mPolicy.contentRequirements, globalSignals);
                selectorPtr->getRankedFrameRates(mPolicy.contentRequirements, globalSignals);

        for (const auto& [modePtr, score] : rankedRefreshRates.ranking) {
        for (const auto& [frameRateMode, score] : rankedRefreshRates.ranking) {
            const auto& modePtr = frameRateMode.modePtr;
            const auto [it, inserted] = refreshRateTallies.try_emplace(modePtr->getFps(), score);

            if (!inserted) {
@@ -771,16 +772,18 @@ auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap {

    for (auto& [ranking, signals] : perDisplayRanking) {
        if (!chosenFps) {
            auto& [modePtr, _] = ranking.front();
            const auto& [frameRateMode, _] = ranking.front();
            const auto& modePtr = frameRateMode.modePtr;
            modeChoices.try_emplace(modePtr->getPhysicalDisplayId(),
                                    DisplayModeChoice{std::move(modePtr), signals});
                                    DisplayModeChoice{modePtr, signals});
            continue;
        }

        for (auto& [modePtr, _] : ranking) {
        for (auto& [frameRateMode, _] : ranking) {
            const auto& modePtr = frameRateMode.modePtr;
            if (modePtr->getFps() == *chosenFps) {
                modeChoices.try_emplace(modePtr->getPhysicalDisplayId(),
                                        DisplayModeChoice{std::move(modePtr), signals});
                                        DisplayModeChoice{modePtr, signals});
                break;
            }
        }
@@ -804,10 +807,10 @@ DisplayModePtr Scheduler::getPreferredDisplayMode() {
    if (mPolicy.mode) {
        const auto ranking =
                leaderSelectorPtr()
                        ->getRankedRefreshRates(mPolicy.contentRequirements, makeGlobalSignals())
                        ->getRankedFrameRates(mPolicy.contentRequirements, makeGlobalSignals())
                        .ranking;

        mPolicy.mode = ranking.front().modePtr;
        mPolicy.mode = ranking.front().frameRateMode.modePtr;
    }
    return mPolicy.mode;
}
+13 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ struct FpsRange {
    Fps max = Fps::fromValue(std::numeric_limits<float>::max());

    bool includes(Fps) const;
    bool includes(FpsRange) const;
};

struct FpsRanges {
@@ -75,6 +76,8 @@ struct FpsRanges {
    // the range of frame rates that refers to the render rate, which is
    // the rate that frames are swapped.
    FpsRange render;

    bool valid() const;
};

static_assert(std::is_trivially_copyable_v<Fps>);
@@ -159,6 +162,16 @@ inline bool FpsRange::includes(Fps fps) const {
    return min <= fps && fps <= max;
}

inline bool FpsRange::includes(FpsRange range) const {
    using namespace fps_approx_ops;
    return min <= range.min && max >= range.max;
}

inline bool FpsRanges::valid() const {
    using fps_approx_ops::operator>=;
    return physical.max >= render.max;
}

struct FpsApproxEqual {
    bool operator()(Fps lhs, Fps rhs) const { return isApproxEqual(lhs, rhs); }
};
Loading