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 Original line 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
    // 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
    // the same reason we are allowing touch boost for those layers. See
    // RefreshRateSelector::rankRefreshRates for details.
    // RefreshRateSelector::rankFrameRates for details.
    const auto layerVotedWithDefaultCompatibility =
    const auto layerVotedWithDefaultCompatibility =
            frameRate.rate.isValid() && frameRate.type == FrameRateCompatibility::Default;
            frameRate.rate.isValid() && frameRate.type == FrameRateCompatibility::Default;
    const auto layerVotedWithNoVote = frameRate.type == FrameRateCompatibility::NoVote;
    const auto layerVotedWithNoVote = frameRate.type == FrameRateCompatibility::NoVote;
+268 −148

File changed.

Preview size limit exceeded, changes collapsed.

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


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


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


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


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

    class Policy {
    class Policy {
        static constexpr int kAllowGroupSwitchingDefault = false;
        static constexpr int kAllowGroupSwitchingDefault = false;


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


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


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


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


        struct DescendingScore {
        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);
                return lhs.score > rhs.score && !scoresEqual(lhs.score, rhs.score);
            }
            }
        };
        };
    };
    };


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


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


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


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


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


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


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

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


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


    // Returns whether switching modes (refresh rate or resolution) is possible.
    // 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
    // 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) {
    bool canSwitch() const EXCLUDES(mLock) {
        std::lock_guard lock(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.
    // Class to enumerate options around toggling the kernel timer on and off.
@@ -307,10 +318,14 @@ public:
    // refresh rates.
    // refresh rates.
    KernelIdleTimerAction getIdleTimerAction() const;
    KernelIdleTimerAction getIdleTimerAction() const;


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


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

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


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


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


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


    const Policy* getCurrentPolicyLocked() const REQUIRES(mLock);
    const Policy* getCurrentPolicyLocked() const REQUIRES(mLock);
    bool isPolicyValidLocked(const Policy& policy) 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.
    // 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
    // calculates a score for a layer. Used to determine the display refresh rate
    // and the frame rate override for certains applications.
    // and the frame rate override for certains applications.
    float calculateLayerScoreLocked(const LayerRequirement&, Fps refreshRate,
    float calculateLayerScoreLocked(const LayerRequirement&, Fps refreshRate,
@@ -436,11 +457,27 @@ private:
                                                             : mIdleTimerCallbacks->platform;
                                                             : 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
    // 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
    // this container, so must be invalidated whenever the DisplayModes change. The Policy below
    // is also dependent, so must be reset as well.
    // is also dependent, so must be reset as well.
    DisplayModes mDisplayModes GUARDED_BY(mLock);
    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
    // Written under mLock exclusively from kMainThreadContext, so reads from kMainThreadContext
    // need not be under mLock.
    // need not be under mLock.
    DisplayModeIterator mActiveModeIt GUARDED_BY(mLock) GUARDED_BY(kMainThreadContext);
    DisplayModeIterator mActiveModeIt GUARDED_BY(mLock) GUARDED_BY(kMainThreadContext);
@@ -449,8 +486,8 @@ private:
    DisplayModeIterator mMaxRefreshRateModeIt GUARDED_BY(mLock);
    DisplayModeIterator mMaxRefreshRateModeIt GUARDED_BY(mLock);


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


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


    struct GetRankedRefreshRatesCache {
    struct GetRankedFrameRatesCache {
        std::pair<std::vector<LayerRequirement>, GlobalSignals> arguments;
        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.
    // Declare mIdleTimer last to ensure its thread joins before the mutex/callbacks are destroyed.
    std::mutex mIdleTimerCallbacksMutex;
    std::mutex mIdleTimerCallbacksMutex;
+14 −11
Original line number Original line Diff line number Diff line
@@ -152,7 +152,7 @@ std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource(


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


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


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


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


    // Tallies the score of a refresh rate across `displayCount` displays.
    // 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) {
    for (const auto& [id, selectorPtr] : mRefreshRateSelectors) {
        auto rankedRefreshRates =
        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);
            const auto [it, inserted] = refreshRateTallies.try_emplace(modePtr->getFps(), score);


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


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


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


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


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


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

    bool valid() const;
};
};


static_assert(std::is_trivially_copyable_v<Fps>);
static_assert(std::is_trivially_copyable_v<Fps>);
@@ -159,6 +162,16 @@ inline bool FpsRange::includes(Fps fps) const {
    return min <= fps && fps <= max;
    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 {
struct FpsApproxEqual {
    bool operator()(Fps lhs, Fps rhs) const { return isApproxEqual(lhs, rhs); }
    bool operator()(Fps lhs, Fps rhs) const { return isApproxEqual(lhs, rhs); }
};
};
Loading