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

Commit 02d5ed9b authored by Kevin DuBois's avatar Kevin DuBois
Browse files

SF: VSR: VSyncTracker can reorients itself

When an incoming timestamp doesnt make sense, VSyncPredictor
will now report this out to VSyncReactor (VSR), which will
turn on HWVsync accordingly. DispSync would turn this on as a normal
course of operations, VSyncReactor only turns this on as an error
handling condition (where DispSync could recover better, more info see
linked bugs)

Bug: 147891587
Bug: 147734678
Bug: 144707443
Test: 3 new unit
Test: uibench run with VSR on

Change-Id: Ia554b3262875e01de5cd8e30af99616ff23d2d27
parent 75df83e9
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -71,12 +71,12 @@ nsecs_t VSyncPredictor::currentPeriod() const {
    return std::get<0>(mRateMap.find(mIdealPeriod)->second);
}

void VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) {
bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) {
    std::lock_guard<std::mutex> lk(mMutex);

    if (!validate(timestamp)) {
        ALOGV("timestamp was too far off the last known timestamp");
        return;
        return false;
    }

    if (timestamps.size() != kHistorySize) {
@@ -89,7 +89,7 @@ void VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) {

    if (timestamps.size() < kMinimumSamplesForPrediction) {
        mRateMap[mIdealPeriod] = {mIdealPeriod, 0};
        return;
        return true;
    }

    // This is a 'simple linear regression' calculation of Y over X, with Y being the
@@ -143,7 +143,7 @@ void VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) {

    if (CC_UNLIKELY(bottom == 0)) {
        it->second = {mIdealPeriod, 0};
        return;
        return false;
    }

    nsecs_t const anticipatedPeriod = top / bottom * kScalingFactor;
@@ -156,6 +156,7 @@ void VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) {

    ALOGV("model update ts: %" PRId64 " slope: %" PRId64 " intercept: %" PRId64, timestamp,
          anticipatedPeriod, intercept);
    return true;
}

nsecs_t VSyncPredictor::nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const {
+1 −1
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ public:
                   uint32_t outlierTolerancePercent);
    ~VSyncPredictor();

    void addVsyncTimestamp(nsecs_t timestamp) final;
    bool addVsyncTimestamp(nsecs_t timestamp) final;
    nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const final;
    nsecs_t currentPeriod() const final;
    void resetModel() final;
+43 −16
Original line number Diff line number Diff line
@@ -130,10 +130,11 @@ bool VSyncReactor::addPresentFence(const std::shared_ptr<FenceTime>& fence) {
    }

    std::lock_guard<std::mutex> lk(mMutex);
    if (mIgnorePresentFences) {
    if (mExternalIgnoreFences || mInternalIgnoreFences) {
        return true;
    }

    bool timestampAccepted = true;
    for (auto it = mUnfiredFences.begin(); it != mUnfiredFences.end();) {
        auto const time = (*it)->getCachedSignalTime();
        if (time == Fence::SIGNAL_TIME_PENDING) {
@@ -141,7 +142,8 @@ bool VSyncReactor::addPresentFence(const std::shared_ptr<FenceTime>& fence) {
        } else if (time == Fence::SIGNAL_TIME_INVALID) {
            it = mUnfiredFences.erase(it);
        } else {
            mTracker->addVsyncTimestamp(time);
            timestampAccepted &= mTracker->addVsyncTimestamp(time);

            it = mUnfiredFences.erase(it);
        }
    }
@@ -152,7 +154,13 @@ bool VSyncReactor::addPresentFence(const std::shared_ptr<FenceTime>& fence) {
        }
        mUnfiredFences.push_back(fence);
    } else {
        mTracker->addVsyncTimestamp(signalTime);
        timestampAccepted &= mTracker->addVsyncTimestamp(signalTime);
    }

    if (!timestampAccepted) {
        mMoreSamplesNeeded = true;
        setIgnorePresentFencesInternal(true);
        mPeriodConfirmationInProgress = true;
    }

    return mMoreSamplesNeeded;
@@ -160,8 +168,17 @@ bool VSyncReactor::addPresentFence(const std::shared_ptr<FenceTime>& fence) {

void VSyncReactor::setIgnorePresentFences(bool ignoration) {
    std::lock_guard<std::mutex> lk(mMutex);
    mIgnorePresentFences = ignoration;
    if (mIgnorePresentFences == true) {
    mExternalIgnoreFences = ignoration;
    updateIgnorePresentFencesInternal();
}

void VSyncReactor::setIgnorePresentFencesInternal(bool ignoration) {
    mInternalIgnoreFences = ignoration;
    updateIgnorePresentFencesInternal();
}

void VSyncReactor::updateIgnorePresentFencesInternal() {
    if (mExternalIgnoreFences || mInternalIgnoreFences) {
        mUnfiredFences.clear();
    }
}
@@ -177,14 +194,18 @@ nsecs_t VSyncReactor::expectedPresentTime() {
}

void VSyncReactor::startPeriodTransition(nsecs_t newPeriod) {
    mPeriodConfirmationInProgress = true;
    mPeriodTransitioningTo = newPeriod;
    mMoreSamplesNeeded = true;
    setIgnorePresentFencesInternal(true);
}

void VSyncReactor::endPeriodTransition() {
    setIgnorePresentFencesInternal(false);
    mMoreSamplesNeeded = false;
    mPeriodTransitioningTo.reset();
    mPeriodConfirmationInProgress = false;
    mLastHwVsync.reset();
    mMoreSamplesNeeded = false;
}

void VSyncReactor::setPeriod(nsecs_t period) {
@@ -208,27 +229,33 @@ void VSyncReactor::beginResync() {

void VSyncReactor::endResync() {}

bool VSyncReactor::periodChangeDetected(nsecs_t vsync_timestamp) {
    if (!mLastHwVsync || !mPeriodTransitioningTo) {
bool VSyncReactor::periodConfirmed(nsecs_t vsync_timestamp) {
    if (!mLastHwVsync || !mPeriodConfirmationInProgress) {
        return false;
    }
    auto const period = mPeriodTransitioningTo ? *mPeriodTransitioningTo : getPeriod();

    static constexpr int allowancePercent = 10;
    static constexpr std::ratio<allowancePercent, 100> allowancePercentRatio;
    auto const allowance = period * allowancePercentRatio.num / allowancePercentRatio.den;
    auto const distance = vsync_timestamp - *mLastHwVsync;
    return std::abs(distance - *mPeriodTransitioningTo) < std::abs(distance - getPeriod());
    return std::abs(distance - period) < allowance;
}

bool VSyncReactor::addResyncSample(nsecs_t timestamp, bool* periodFlushed) {
    assert(periodFlushed);

    std::lock_guard<std::mutex> lk(mMutex);
    if (periodChangeDetected(timestamp)) {
    if (periodConfirmed(timestamp)) {
        if (mPeriodTransitioningTo) {
            mTracker->setPeriod(*mPeriodTransitioningTo);
            for (auto& entry : mCallbacks) {
                entry.second->setPeriod(*mPeriodTransitioningTo);
            }

        endPeriodTransition();
            *periodFlushed = true;
    } else if (mPeriodTransitioningTo) {
        }
        endPeriodTransition();
    } else if (mPeriodConfirmationInProgress) {
        mLastHwVsync = timestamp;
        mMoreSamplesNeeded = true;
        *periodFlushed = false;
+6 −2
Original line number Diff line number Diff line
@@ -61,9 +61,11 @@ public:
    void reset() final;

private:
    void setIgnorePresentFencesInternal(bool ignoration) REQUIRES(mMutex);
    void updateIgnorePresentFencesInternal() REQUIRES(mMutex);
    void startPeriodTransition(nsecs_t newPeriod) REQUIRES(mMutex);
    void endPeriodTransition() REQUIRES(mMutex);
    bool periodChangeDetected(nsecs_t vsync_timestamp) REQUIRES(mMutex);
    bool periodConfirmed(nsecs_t vsync_timestamp) REQUIRES(mMutex);

    std::unique_ptr<Clock> const mClock;
    std::unique_ptr<VSyncTracker> const mTracker;
@@ -71,10 +73,12 @@ private:
    size_t const mPendingLimit;

    std::mutex mMutex;
    bool mIgnorePresentFences GUARDED_BY(mMutex) = false;
    bool mInternalIgnoreFences GUARDED_BY(mMutex) = false;
    bool mExternalIgnoreFences GUARDED_BY(mMutex) = false;
    std::vector<std::shared_ptr<FenceTime>> mUnfiredFences GUARDED_BY(mMutex);

    bool mMoreSamplesNeeded GUARDED_BY(mMutex) = false;
    bool mPeriodConfirmationInProgress GUARDED_BY(mMutex) = false;
    std::optional<nsecs_t> mPeriodTransitioningTo GUARDED_BY(mMutex);
    std::optional<nsecs_t> mLastHwVsync GUARDED_BY(mMutex);

+3 −1
Original line number Diff line number Diff line
@@ -33,8 +33,10 @@ public:
     * to the model.
     *
     * \param [in] timestamp    The timestamp when the vsync signal was.
     * \return                  True if the timestamp was consistent with the internal model,
     *                          False otherwise
     */
    virtual void addVsyncTimestamp(nsecs_t timestamp) = 0;
    virtual bool addVsyncTimestamp(nsecs_t timestamp) = 0;

    /*
     * Access the next anticipated vsync time such that the anticipated time >= timePoint.
Loading