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

Commit 5cc2e266 authored by Ady Abraham's avatar Ady Abraham
Browse files

SurfaceFlinger: fix refresh rate override when changing refresh rate

If an app's frame rate is same as the display refresh rate, keep it
on the frame rate override list. The reason for this is if an app
is added to the list after the display refresh rate changed, the few
first frames would be running the the display refresh rate and not at
the override one.

Test: atest FrameRateOverrideHostTest
Test: run TouchLatency while changing refresh rates and collect systrace
Bug: 182544360
Change-Id: I66472a1230affae9336520083f0950ae252ede02
parent cb45c138
Loading
Loading
Loading
Loading
+1 −10
Original line number Diff line number Diff line
@@ -499,12 +499,8 @@ RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverr
        // Now that we scored all the refresh rates we need to pick the one that got the highest
        // score.
        const RefreshRate* bestRefreshRate = getBestRefreshRate(scores.begin(), scores.end());

        // If the nest refresh rate is the current one, we don't have an override
        if (!bestRefreshRate->getFps().equalsWithMargin(displayFrameRate)) {
        frameRateOverrides.emplace(uid, bestRefreshRate->getFps());
    }
    }

    return frameRateOverrides;
}
@@ -839,11 +835,6 @@ int RefreshRateConfigs::getFrameRateDivider(Fps displayFrameRate, Fps layerFrame
    return static_cast<int>(numPeriodsRounded);
}

int RefreshRateConfigs::getRefreshRateDivider(Fps frameRate) const {
    std::lock_guard lock(mLock);
    return getFrameRateDivider(mCurrentRefreshRate->getFps(), frameRate);
}

void RefreshRateConfigs::dump(std::string& result) const {
    std::lock_guard lock(mLock);
    base::StringAppendF(&result, "DesiredDisplayModeSpecs (DisplayManager): %s\n\n",
+4 −7
Original line number Diff line number Diff line
@@ -324,8 +324,10 @@ public:

    bool supportsFrameRateOverride() const { return mSupportsFrameRateOverride; }

    // Returns a divider for the current refresh rate
    int getRefreshRateDivider(Fps frameRate) const EXCLUDES(mLock);
    // Return the display refresh rate divider to match the layer
    // frame rate, or 0 if the display refresh rate is not a multiple of the
    // layer refresh rate.
    static int getFrameRateDivider(Fps displayFrameRate, Fps layerFrameRate);

    using UidToFrameRateOverride = std::map<uid_t, Fps>;
    // Returns the frame rate override for each uid.
@@ -373,11 +375,6 @@ private:
    const Policy* getCurrentPolicyLocked() const REQUIRES(mLock);
    bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock);

    // Return the display refresh rate divider to match the layer
    // frame rate, or 0 if the display refresh rate is not a multiple of the
    // layer refresh rate.
    static int getFrameRateDivider(Fps displayFrameRate, Fps layerFrameRate);

    // 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&, const RefreshRate&,
+5 −6
Original line number Diff line number Diff line
@@ -235,12 +235,7 @@ bool Scheduler::isVsyncValid(nsecs_t expectedVsyncTimestamp, uid_t uid) const {
        return true;
    }

    const auto divider = mRefreshRateConfigs.getRefreshRateDivider(*frameRate);
    if (divider <= 1) {
        return true;
    }

    return mVsyncSchedule.tracker->isVSyncInPhase(expectedVsyncTimestamp, divider);
    return mVsyncSchedule.tracker->isVSyncInPhase(expectedVsyncTimestamp, *frameRate);
}

impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() const {
@@ -354,6 +349,10 @@ void Scheduler::onPrimaryDisplayModeChanged(ConnectionHandle handle, PhysicalDis
        std::lock_guard<std::mutex> lock(mFeatureStateLock);
        // Cache the last reported modes for primary display.
        mFeatures.cachedModeChangedParams = {handle, displayId, modeId, vsyncPeriod};

        // Invalidate content based refresh rate selection so it could be calculated
        // again for the new refresh rate.
        mFeatures.contentRequirements.clear();
    }
    onNonPrimaryDisplayModeChanged(handle, displayId, modeId, vsyncPeriod);
}
+11 −7
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <algorithm>
#include <chrono>
#include <sstream>
#include "RefreshRateConfigs.h"

#undef LOG_TAG
#define LOG_TAG "VSyncPredictor"
@@ -225,13 +226,14 @@ nsecs_t VSyncPredictor::nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const {
}

/*
 * Returns whether a given vsync timestamp is in phase with a vsync divider.
 * For example, if the vsync timestamps are (16,32,48,64):
 * isVSyncInPhase(16, 2) = true
 * isVSyncInPhase(32, 2) = false
 * isVSyncInPhase(48, 2) = true
 * Returns whether a given vsync timestamp is in phase with a frame rate.
 * If the frame rate is not a divider of the refresh rate, it is always considered in phase.
 * For example, if the vsync timestamps are (16.6,33.3,50.0,66.6):
 * isVSyncInPhase(16.6, 30) = true
 * isVSyncInPhase(33.3, 30) = false
 * isVSyncInPhase(50.0, 30) = true
 */
bool VSyncPredictor::isVSyncInPhase(nsecs_t timePoint, int divider) const {
bool VSyncPredictor::isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const {
    struct VsyncError {
        nsecs_t vsyncTimestamp;
        float error;
@@ -239,11 +241,13 @@ bool VSyncPredictor::isVSyncInPhase(nsecs_t timePoint, int divider) const {
        bool operator<(const VsyncError& other) const { return error < other.error; }
    };

    std::lock_guard lock(mMutex);
    const auto divider =
            RefreshRateConfigs::getFrameRateDivider(Fps::fromPeriodNsecs(mIdealPeriod), frameRate);
    if (divider <= 1 || timePoint == 0) {
        return true;
    }

    std::lock_guard lock(mMutex);
    const nsecs_t period = mRateMap[mIdealPeriod].slope;
    const nsecs_t justBeforeTimePoint = timePoint - period / 2;
    const nsecs_t dividedPeriod = mIdealPeriod / divider;
+1 −1
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ public:

    VSyncPredictor::Model getVSyncPredictionModel() const EXCLUDES(mMutex);

    bool isVSyncInPhase(nsecs_t timePoint, int divider) const final EXCLUDES(mMutex);
    bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const final EXCLUDES(mMutex);

    void dump(std::string& result) const final EXCLUDES(mMutex);

Loading