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

Commit 64c2fc0e authored by Ady Abraham's avatar Ady Abraham
Browse files

SurfaceFlinger: optimize frame rate override

On devices that frame rate override cannot be supported
as the device doesn't support refresh rates that are divisors of
each other, there is no point in trying to find a a frame rate override.

Bug: 170502573
Test: atest FrameRateOverrideHostTest
Change-Id: Idfce2573ee58fa695e81a00c85206990baad978e
parent 56b42a45
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -390,8 +390,9 @@ std::vector<RefreshRateScore> initializeScoresForAllRefreshRates(
RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverrides(
        const std::vector<LayerRequirement>& layers, Fps displayFrameRate) const {
    ATRACE_CALL();
    ALOGV("getFrameRateOverrides %zu layers", layers.size());
    if (!mSupportsFrameRateOverride) return {};

    ALOGV("getFrameRateOverrides %zu layers", layers.size());
    std::lock_guard lock(mLock);
    std::vector<RefreshRateScore> scores = initializeScoresForAllRefreshRates(mRefreshRates);
    std::unordered_map<uid_t, std::vector<const LayerRequirement*>> layersByUid =
@@ -547,6 +548,16 @@ RefreshRateConfigs::RefreshRateConfigs(
    mDisplayManagerPolicy.defaultConfig = currentConfigId;
    mMinSupportedRefreshRate = sortedConfigs.front();
    mMaxSupportedRefreshRate = sortedConfigs.back();

    mSupportsFrameRateOverride = false;
    for (const auto& config1 : sortedConfigs) {
        for (const auto& config2 : sortedConfigs) {
            if (getFrameRateDivider(config1->getFps(), config2->getFps()) >= 2) {
                mSupportsFrameRateOverride = true;
                break;
            }
        }
    }
    constructAvailableRefreshRates();
}

@@ -783,6 +794,8 @@ void RefreshRateConfigs::dump(std::string& result) const {
        base::StringAppendF(&result, "\t%s\n", refreshRate->toString().c_str());
    }

    base::StringAppendF(&result, "Supports Frame Rate Override: %s\n",
                        mSupportsFrameRateOverride ? "yes" : "no");
    result.append("\n");
}

+4 −0
Original line number Diff line number Diff line
@@ -318,6 +318,8 @@ public:
    // refresh rates.
    KernelIdleTimerAction getIdleTimerAction() const;

    bool supportsFrameRateOverride() const { return mSupportsFrameRateOverride; }

    // Returns a divider for the current refresh rate
    int getRefreshRateDivider(Fps frameRate) const EXCLUDES(mLock);

@@ -405,6 +407,8 @@ private:
    // A sorted list of known frame rates that a Heuristic layer will choose
    // from based on the closest value.
    const std::vector<Fps> mKnownFrameRates;

    bool mSupportsFrameRateOverride;
};

} // namespace android::scheduler
+19 −3
Original line number Diff line number Diff line
@@ -226,6 +226,10 @@ std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const {
}

bool Scheduler::isVsyncValid(nsecs_t expectedVsyncTimestamp, uid_t uid) const {
    if (!mRefreshRateConfigs.supportsFrameRateOverride()) {
        return true;
    }

    const auto frameRate = getFrameRateOverride(uid);
    if (!frameRate.has_value()) {
        return true;
@@ -239,14 +243,22 @@ bool Scheduler::isVsyncValid(nsecs_t expectedVsyncTimestamp, uid_t uid) const {
    return mVsyncSchedule.tracker->isVSyncInPhase(expectedVsyncTimestamp, divider);
}

impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() const {
    if (!mRefreshRateConfigs.supportsFrameRateOverride()) {
        return {};
    }

    return [this](nsecs_t expectedVsyncTimestamp, uid_t uid) {
        return !isVsyncValid(expectedVsyncTimestamp, uid);
    };
}

Scheduler::ConnectionHandle Scheduler::createConnection(
        const char* connectionName, frametimeline::TokenManager* tokenManager,
        std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
        impl::EventThread::InterceptVSyncsCallback interceptCallback) {
    auto vsyncSource = makePrimaryDispSyncSource(connectionName, workDuration, readyDuration);
    auto throttleVsync = [this](nsecs_t expectedVsyncTimestamp, uid_t uid) {
        return !isVsyncValid(expectedVsyncTimestamp, uid);
    };
    auto throttleVsync = makeThrottleVsyncCallback();
    auto eventThread = std::make_unique<impl::EventThread>(std::move(vsyncSource), tokenManager,
                                                           std::move(interceptCallback),
                                                           std::move(throttleVsync));
@@ -744,6 +756,10 @@ void Scheduler::dumpVsync(std::string& s) const {

bool Scheduler::updateFrameRateOverrides(
        scheduler::RefreshRateConfigs::GlobalSignals consideredSignals, Fps displayRefreshRate) {
    if (!mRefreshRateConfigs.supportsFrameRateOverride()) {
        return false;
    }

    if (consideredSignals.touch) {
        std::lock_guard lock(mFrameRateOverridesMutex);
        const bool changed = !mFrameRateOverridesByContent.empty();
+1 −0
Original line number Diff line number Diff line
@@ -237,6 +237,7 @@ private:
            EXCLUDES(mFrameRateOverridesMutex);

    std::optional<Fps> getFrameRateOverride(uid_t uid) const EXCLUDES(mFrameRateOverridesMutex);
    impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const;

    // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
    struct Connection {