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

Commit 7b6c15f8 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topic "b:140112642:1" into qt-surfaceflinger-dev

* changes:
  SurfaceFlinger: do not force HDR content to default refresh rate
  [SurfaceFlinger] fix permanently enabling early offsets.
  [SurfaceFlinger] Some dispsync fixes for early event firing
  [SurfaceFlinger] add minimum frame count for early gl offsets.
parents 3bf71ab8 baa35b0e
Loading
Loading
Loading
Loading
+45 −17
Original line number Diff line number Diff line
@@ -79,11 +79,7 @@ public:
        Mutex::Autolock lock(mMutex);

        mPhase = phase;
        if (mReferenceTime != referenceTime) {
            for (auto& eventListener : mEventListeners) {
                eventListener.mHasFired = false;
            }
        }
        const bool referenceTimeChanged = mReferenceTime != referenceTime;
        mReferenceTime = referenceTime;
        if (mPeriod != 0 && mPeriod != period && mReferenceTime != 0) {
            // Inflate the reference time to be the most recent predicted
@@ -94,6 +90,13 @@ public:
            mReferenceTime = mReferenceTime + (numOldPeriods)*mPeriod;
        }
        mPeriod = period;
        if (!mModelLocked && referenceTimeChanged) {
            for (auto& eventListener : mEventListeners) {
                eventListener.mHasFired = false;
                eventListener.mLastEventTime =
                        mReferenceTime - mPeriod + mPhase + eventListener.mPhase;
            }
        }
        if (mTraceDetailedInfo) {
            ATRACE_INT64("DispSync:Period", mPeriod);
            ATRACE_INT64("DispSync:Phase", mPhase + mPeriod / 2);
@@ -115,11 +118,20 @@ public:
    void lockModel() {
        Mutex::Autolock lock(mMutex);
        mModelLocked = true;
        ATRACE_INT("DispSync:ModelLocked", mModelLocked);
    }

    void unlockModel() {
        Mutex::Autolock lock(mMutex);
        if (mModelLocked) {
            for (auto& eventListener : mEventListeners) {
                if (eventListener.mLastEventTime > mReferenceTime) {
                    eventListener.mHasFired = true;
                }
            }
        }
        mModelLocked = false;
        ATRACE_INT("DispSync:ModelLocked", mModelLocked);
    }

    virtual bool threadLoop() {
@@ -247,6 +259,10 @@ public:
            listener.mLastCallbackTime = lastCallbackTime;
        }

        if (!mModelLocked && listener.mLastEventTime > mReferenceTime) {
            listener.mHasFired = true;
        }

        mEventListeners.push_back(listener);

        mCond.signal();
@@ -493,7 +509,6 @@ void DispSync::init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) {
        ALOGE("Couldn't set SCHED_FIFO for DispSyncThread");
    }

    reset();
    beginResync();

    if (mTraceDetailedInfo && kEnableZeroPhaseTracer) {
@@ -545,17 +560,15 @@ bool DispSync::addPresentFence(const std::shared_ptr<FenceTime>& fenceTime) {
void DispSync::beginResync() {
    Mutex::Autolock lock(mMutex);
    ALOGV("[%s] beginResync", mName);
    mThread->unlockModel();
    mModelUpdated = false;
    mNumResyncSamples = 0;
    resetLocked();
}

bool DispSync::addResyncSample(nsecs_t timestamp, bool* periodChanged) {
bool DispSync::addResyncSample(nsecs_t timestamp, bool* periodFlushed) {
    Mutex::Autolock lock(mMutex);

    ALOGV("[%s] addResyncSample(%" PRId64 ")", mName, ns2us(timestamp));

    *periodChanged = false;
    *periodFlushed = false;
    const size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
    mResyncSamples[idx] = timestamp;
    if (mNumResyncSamples == 0) {
@@ -569,16 +582,20 @@ bool DispSync::addResyncSample(nsecs_t timestamp, bool* periodChanged) {
        const nsecs_t lastTimestamp = mResyncSamples[priorIdx];

        const nsecs_t observedVsync = std::abs(timestamp - lastTimestamp);
        if (std::abs(observedVsync - mPendingPeriod) < std::abs(observedVsync - mPeriod)) {
            // Observed vsync is closer to the pending period, so reset the
            // model and flush the pending period.
        if (std::abs(observedVsync - mPendingPeriod) <= std::abs(observedVsync - mIntendedPeriod)) {
            // Either the observed vsync is closer to the pending period, (and
            // thus we detected a period change), or the period change will
            // no-op. In either case, reset the model and flush the pending
            // period.
            resetLocked();
            mIntendedPeriod = mPendingPeriod;
            mPeriod = mPendingPeriod;
            mPendingPeriod = 0;
            if (mTraceDetailedInfo) {
                ATRACE_INT("DispSync:PendingPeriod", mPendingPeriod);
                ATRACE_INT("DispSync:IntendedPeriod", mIntendedPeriod);
            }
            *periodChanged = true;
            *periodFlushed = true;
        }
    }
    // Always update the reference time with the most recent timestamp.
@@ -609,6 +626,7 @@ bool DispSync::addResyncSample(nsecs_t timestamp, bool* periodChanged) {
    bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2) && mPendingPeriod == 0;
    ALOGV("[%s] addResyncSample returning %s", mName, modelLocked ? "locked" : "unlocked");
    if (modelLocked) {
        *periodFlushed = true;
        mThread->lockModel();
    }
    return !modelLocked;
@@ -643,10 +661,17 @@ status_t DispSync::changePhaseOffset(Callback* callback, nsecs_t phase) {

void DispSync::setPeriod(nsecs_t period) {
    Mutex::Autolock lock(mMutex);

    const bool pendingPeriodShouldChange =
            period != mIntendedPeriod || (period == mIntendedPeriod && mPendingPeriod != 0);

    if (pendingPeriodShouldChange) {
        mPendingPeriod = period;
    }
    if (mTraceDetailedInfo) {
        ATRACE_INT("DispSync:PendingPeriod", period);
        ATRACE_INT("DispSync:IntendedPeriod", mIntendedPeriod);
        ATRACE_INT("DispSync:PendingPeriod", mPendingPeriod);
    }
    mPendingPeriod = period;
}

nsecs_t DispSync::getPeriod() {
@@ -764,6 +789,9 @@ void DispSync::resetErrorLocked() {
    mPresentSampleOffset = 0;
    mError = 0;
    mZeroErrSamplesCount = 0;
    if (mTraceDetailedInfo) {
        ATRACE_INT64("DispSync:Error", mError);
    }
    for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
        mPresentFences[i] = FenceTime::NO_FENCE;
    }
+14 −7
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ public:
    virtual void reset() = 0;
    virtual bool addPresentFence(const std::shared_ptr<FenceTime>&) = 0;
    virtual void beginResync() = 0;
    virtual bool addResyncSample(nsecs_t timestamp, bool* periodChanged) = 0;
    virtual bool addResyncSample(nsecs_t timestamp, bool* periodFlushed) = 0;
    virtual void endResync() = 0;
    virtual void setPeriod(nsecs_t period) = 0;
    virtual nsecs_t getPeriod() = 0;
@@ -120,17 +120,19 @@ public:
    // from the hardware vsync events.
    void beginResync() override;
    // Adds a vsync sample to the dispsync model. The timestamp is the time
    // of the vsync event that fired. periodChanged will return true if the
    // of the vsync event that fired. periodFlushed will return true if the
    // vsync period was detected to have changed to mPendingPeriod.
    //
    // This method will return true if more vsync samples are needed to lock
    // down the DispSync model, and false otherwise.
    bool addResyncSample(nsecs_t timestamp, bool* periodChanged) override;
    // periodFlushed will be set to true if mPendingPeriod is flushed to
    // mIntendedPeriod, and false otherwise.
    bool addResyncSample(nsecs_t timestamp, bool* periodFlushed) override;
    void endResync() override;

    // The setPeriod method sets the vsync event model's period to a specific
    // value. This should be used to prime the model when a display is first
    // turned on.  It should NOT be used after that.
    // turned on, or when a refresh rate change is requested.
    void setPeriod(nsecs_t period) override;

    // The getPeriod method returns the current vsync period.
@@ -205,6 +207,11 @@ private:
    // nanoseconds.
    nsecs_t mPeriod;

    // mIntendedPeriod is the intended period of the modeled vsync events in
    // nanoseconds. Under ideal conditions this should be similar if not the
    // same as mPeriod, plus or minus an observed error.
    nsecs_t mIntendedPeriod = 0;

    // mPendingPeriod is the proposed period change in nanoseconds.
    // If mPendingPeriod differs from mPeriod and is nonzero, it will
    // be flushed to mPeriod when we detect that the hardware switched
@@ -236,8 +243,8 @@ private:
    // process to store information about the hardware vsync event times used
    // to compute the model.
    nsecs_t mResyncSamples[MAX_RESYNC_SAMPLES] = {0};
    size_t mFirstResyncSample;
    size_t mNumResyncSamples;
    size_t mFirstResyncSample = 0;
    size_t mNumResyncSamples = 0;
    int mNumResyncSamplesSincePresent;

    // These member variables store information about the present fences used
+4 −4
Original line number Diff line number Diff line
@@ -283,13 +283,13 @@ void Scheduler::setVsyncPeriod(const nsecs_t period) {
    }
}

void Scheduler::addResyncSample(const nsecs_t timestamp, bool* periodChanged) {
void Scheduler::addResyncSample(const nsecs_t timestamp, bool* periodFlushed) {
    bool needsHwVsync = false;
    *periodChanged = false;
    *periodFlushed = false;
    { // Scope for the lock
        std::lock_guard<std::mutex> lock(mHWVsyncLock);
        if (mPrimaryHWVsyncEnabled) {
            needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp, periodChanged);
            needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp, periodFlushed);
        }
    }

@@ -418,7 +418,7 @@ void Scheduler::resetKernelTimerCallback() {
    ATRACE_INT("ExpiredKernelIdleTimer", 0);
    std::lock_guard<std::mutex> lock(mCallbackLock);
    if (mGetVsyncPeriod) {
        resyncToHardwareVsync(false, mGetVsyncPeriod());
        resyncToHardwareVsync(true, mGetVsyncPeriod());
    }
}

+9 −4
Original line number Diff line number Diff line
@@ -136,13 +136,18 @@ public:

    void enableHardwareVsync();
    void disableHardwareVsync(bool makeUnavailable);
    // Resyncs the scheduler to hardware vsync.
    // If makeAvailable is true, then hardware vsync will be turned on.
    // Otherwise, if hardware vsync is not already enabled then this method will
    // no-op.
    // The period is the vsync period from the current display configuration.
    void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
    // Creates a callback for resyncing.
    ResyncCallback makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod);
    void setRefreshSkipCount(int count);
    // Passes a vsync sample to DispSync. periodChange will be true if DipSync
    // detected that the vsync period changed, and false otherwise.
    void addResyncSample(const nsecs_t timestamp, bool* periodChanged);
    // Passes a vsync sample to DispSync. periodFlushed will be true if
    // DispSync detected that the vsync period changed, and false otherwise.
    void addResyncSample(const nsecs_t timestamp, bool* periodFlushed);
    void addPresentFence(const std::shared_ptr<FenceTime>& fenceTime);
    void setIgnorePresentFences(bool ignore);
    nsecs_t expectedPresentTime();
@@ -294,7 +299,7 @@ private:
    const scheduler::RefreshRateConfigs& mRefreshRateConfigs;

    // Global config to force HDR content to work on DEFAULT refreshRate
    static constexpr bool mForceHDRContentToDefaultRefreshRate = true;
    static constexpr bool mForceHDRContentToDefaultRefreshRate = false;
};

} // namespace android
+14 −5
Original line number Diff line number Diff line
@@ -35,6 +35,11 @@ private:
    // sending new transactions.
    const int MIN_EARLY_FRAME_COUNT_TRANSACTION = 2;

    // Number of frames we'll keep the early gl phase offsets once they are activated.
    // This acts as a low-pass filter to avoid scenarios where we rapidly
    // switch in and out of gl composition.
    const int MIN_EARLY_GL_FRAME_COUNT_TRANSACTION = 2;

public:
    struct Offsets {
        nsecs_t sf;
@@ -116,7 +121,7 @@ public:

    // Called when we detect from vsync signals that the refresh rate changed.
    // This way we can move out of early offsets if no longer necessary.
    void onRefreshRateChangeDetected() {
    void onRefreshRateChangeCompleted() {
        if (!mRefreshRateChangePending) {
            return;
        }
@@ -130,10 +135,14 @@ public:
            mRemainingEarlyFrameCount--;
            updateOffsetsNeeded = true;
        }
        if (usedRenderEngine != mLastFrameUsedRenderEngine) {
            mLastFrameUsedRenderEngine = usedRenderEngine;
        if (usedRenderEngine) {
            mRemainingRenderEngineUsageCount = MIN_EARLY_GL_FRAME_COUNT_TRANSACTION;
            updateOffsetsNeeded = true;
        } else if (mRemainingRenderEngineUsageCount > 0) {
            mRemainingRenderEngineUsageCount--;
            updateOffsetsNeeded = true;
        }

        if (updateOffsetsNeeded) {
            updateOffsets();
        }
@@ -145,7 +154,7 @@ public:
        if (mTransactionStart == Scheduler::TransactionStart::EARLY ||
            mRemainingEarlyFrameCount > 0 || mRefreshRateChangePending) {
            return mEarlyOffsets;
        } else if (mLastFrameUsedRenderEngine) {
        } else if (mRemainingRenderEngineUsageCount > 0) {
            return mEarlyGlOffsets;
        } else {
            return mLateOffsets;
@@ -195,9 +204,9 @@ private:

    std::atomic<Scheduler::TransactionStart> mTransactionStart =
            Scheduler::TransactionStart::NORMAL;
    std::atomic<bool> mLastFrameUsedRenderEngine = false;
    std::atomic<bool> mRefreshRateChangePending = false;
    std::atomic<int> mRemainingEarlyFrameCount = 0;
    std::atomic<int> mRemainingRenderEngineUsageCount = 0;
};

} // namespace android
Loading