Loading services/surfaceflinger/Scheduler/DispSync.cpp +30 −12 Original line number Diff line number Diff line Loading @@ -210,8 +210,7 @@ public: const nsecs_t baseTime = now - mReferenceTime; const nsecs_t numPeriodsSinceReference = baseTime / mPeriod; const nsecs_t predictedReference = mReferenceTime + numPeriodsSinceReference * mPeriod; const nsecs_t phaseCorrection = mPhase + listener.mPhase; listener.mLastEventTime = predictedReference + phaseCorrection; listener.mLastEventTime = predictedReference + mPhase + listener.mPhase; // If we're very close in time to the predicted last event time, // then we need to back up the last event time so that we can // attempt to fire an event immediately. Loading Loading @@ -279,7 +278,6 @@ public: return NO_ERROR; } } return BAD_VALUE; } Loading Loading @@ -525,21 +523,40 @@ void DispSync::beginResync() { mNumResyncSamples = 0; } bool DispSync::addResyncSample(nsecs_t timestamp) { bool DispSync::addResyncSample(nsecs_t timestamp, bool* periodChanged) { Mutex::Autolock lock(mMutex); ALOGV("[%s] addResyncSample(%" PRId64 ")", mName, ns2us(timestamp)); size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES; *periodChanged = false; const size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES; mResyncSamples[idx] = timestamp; if (mNumResyncSamples == 0) { mPhase = 0; mReferenceTime = timestamp; ALOGV("[%s] First resync sample: mPeriod = %" PRId64 ", mPhase = 0, " "mReferenceTime = %" PRId64, mName, ns2us(mPeriod), ns2us(mReferenceTime)); mThread->updateModel(mPeriod, mPhase, mReferenceTime); mName, ns2us(mPeriod), ns2us(timestamp)); } else if (mPendingPeriod > 0) { // mNumResyncSamples > 0, so priorIdx won't overflow const size_t priorIdx = (mFirstResyncSample + mNumResyncSamples - 1) % MAX_RESYNC_SAMPLES; 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. resetLocked(); mPeriod = mPendingPeriod; mPendingPeriod = 0; if (mTraceDetailedInfo) { ATRACE_INT("DispSync:PendingPeriod", mPendingPeriod); } *periodChanged = true; } } // Always update the reference time with the most recent timestamp. mReferenceTime = timestamp; mThread->updateModel(mPeriod, mPhase, mReferenceTime); if (mNumResyncSamples < MAX_RESYNC_SAMPLES) { mNumResyncSamples++; Loading @@ -562,7 +579,7 @@ bool DispSync::addResyncSample(nsecs_t timestamp) { // Check against kErrorThreshold / 2 to add some hysteresis before having to // resync again bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2); bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2) && mPendingPeriod == 0; ALOGV("[%s] addResyncSample returning %s", mName, modelLocked ? "locked" : "unlocked"); return !modelLocked; } Loading Loading @@ -594,9 +611,10 @@ status_t DispSync::changePhaseOffset(Callback* callback, nsecs_t phase) { void DispSync::setPeriod(nsecs_t period) { Mutex::Autolock lock(mMutex); mPeriod = period; mPhase = 0; mThread->updateModel(mPeriod, mPhase, mReferenceTime); if (mTraceDetailedInfo) { ATRACE_INT("DispSync:PendingPeriod", period); } mPendingPeriod = period; } nsecs_t DispSync::getPeriod() { Loading services/surfaceflinger/Scheduler/DispSync.h +14 −2 Original line number Diff line number Diff line Loading @@ -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) = 0; virtual bool addResyncSample(nsecs_t timestamp, bool* periodChanged) = 0; virtual void endResync() = 0; virtual void setPeriod(nsecs_t period) = 0; virtual nsecs_t getPeriod() = 0; Loading Loading @@ -119,7 +119,13 @@ public: // addPresentFence returns true indicating that the model has drifted away // from the hardware vsync events. void beginResync() override; bool addResyncSample(nsecs_t timestamp) 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 // 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; void endResync() override; // The setPeriod method sets the vsync event model's period to a specific Loading Loading @@ -199,6 +205,12 @@ private: // nanoseconds. nsecs_t mPeriod; // 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 // vsync frequency. nsecs_t mPendingPeriod = 0; // mPhase is the phase offset of the modeled vsync events. It is the // number of nanoseconds from time 0 to the first vsync event. nsecs_t mPhase; Loading services/surfaceflinger/Scheduler/PhaseOffsets.h +2 −2 Original line number Diff line number Diff line Loading @@ -68,8 +68,8 @@ public: void dump(std::string& result) const override; private: Offsets getmDefaultRefreshRateOffsets() { return mDefaultRefreshRateOffsets; } Offsets getmHighRefreshRateOffsets() { return mHighRefreshRateOffsets; } Offsets getDefaultRefreshRateOffsets() { return mDefaultRefreshRateOffsets; } Offsets getHighRefreshRateOffsets() { return mHighRefreshRateOffsets; } std::atomic<RefreshRateConfigs::RefreshRateType> mRefreshRateType = RefreshRateConfigs::RefreshRateType::DEFAULT; Loading services/surfaceflinger/Scheduler/Scheduler.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -249,7 +249,6 @@ void Scheduler::setRefreshSkipCount(int count) { void Scheduler::setVsyncPeriod(const nsecs_t period) { std::lock_guard<std::mutex> lock(mHWVsyncLock); mPrimaryDispSync->reset(); mPrimaryDispSync->setPeriod(period); if (!mPrimaryHWVsyncEnabled) { Loading @@ -259,12 +258,13 @@ void Scheduler::setVsyncPeriod(const nsecs_t period) { } } void Scheduler::addResyncSample(const nsecs_t timestamp) { void Scheduler::addResyncSample(const nsecs_t timestamp, bool* periodChanged) { bool needsHwVsync = false; *periodChanged = false; { // Scope for the lock std::lock_guard<std::mutex> lock(mHWVsyncLock); if (mPrimaryHWVsyncEnabled) { needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp); needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp, periodChanged); } } Loading services/surfaceflinger/Scheduler/Scheduler.h +3 −1 Original line number Diff line number Diff line Loading @@ -139,7 +139,9 @@ public: // Creates a callback for resyncing. ResyncCallback makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod); void setRefreshSkipCount(int count); void addResyncSample(const nsecs_t timestamp); // 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); void addPresentFence(const std::shared_ptr<FenceTime>& fenceTime); void setIgnorePresentFences(bool ignore); nsecs_t expectedPresentTime(); Loading Loading
services/surfaceflinger/Scheduler/DispSync.cpp +30 −12 Original line number Diff line number Diff line Loading @@ -210,8 +210,7 @@ public: const nsecs_t baseTime = now - mReferenceTime; const nsecs_t numPeriodsSinceReference = baseTime / mPeriod; const nsecs_t predictedReference = mReferenceTime + numPeriodsSinceReference * mPeriod; const nsecs_t phaseCorrection = mPhase + listener.mPhase; listener.mLastEventTime = predictedReference + phaseCorrection; listener.mLastEventTime = predictedReference + mPhase + listener.mPhase; // If we're very close in time to the predicted last event time, // then we need to back up the last event time so that we can // attempt to fire an event immediately. Loading Loading @@ -279,7 +278,6 @@ public: return NO_ERROR; } } return BAD_VALUE; } Loading Loading @@ -525,21 +523,40 @@ void DispSync::beginResync() { mNumResyncSamples = 0; } bool DispSync::addResyncSample(nsecs_t timestamp) { bool DispSync::addResyncSample(nsecs_t timestamp, bool* periodChanged) { Mutex::Autolock lock(mMutex); ALOGV("[%s] addResyncSample(%" PRId64 ")", mName, ns2us(timestamp)); size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES; *periodChanged = false; const size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES; mResyncSamples[idx] = timestamp; if (mNumResyncSamples == 0) { mPhase = 0; mReferenceTime = timestamp; ALOGV("[%s] First resync sample: mPeriod = %" PRId64 ", mPhase = 0, " "mReferenceTime = %" PRId64, mName, ns2us(mPeriod), ns2us(mReferenceTime)); mThread->updateModel(mPeriod, mPhase, mReferenceTime); mName, ns2us(mPeriod), ns2us(timestamp)); } else if (mPendingPeriod > 0) { // mNumResyncSamples > 0, so priorIdx won't overflow const size_t priorIdx = (mFirstResyncSample + mNumResyncSamples - 1) % MAX_RESYNC_SAMPLES; 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. resetLocked(); mPeriod = mPendingPeriod; mPendingPeriod = 0; if (mTraceDetailedInfo) { ATRACE_INT("DispSync:PendingPeriod", mPendingPeriod); } *periodChanged = true; } } // Always update the reference time with the most recent timestamp. mReferenceTime = timestamp; mThread->updateModel(mPeriod, mPhase, mReferenceTime); if (mNumResyncSamples < MAX_RESYNC_SAMPLES) { mNumResyncSamples++; Loading @@ -562,7 +579,7 @@ bool DispSync::addResyncSample(nsecs_t timestamp) { // Check against kErrorThreshold / 2 to add some hysteresis before having to // resync again bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2); bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2) && mPendingPeriod == 0; ALOGV("[%s] addResyncSample returning %s", mName, modelLocked ? "locked" : "unlocked"); return !modelLocked; } Loading Loading @@ -594,9 +611,10 @@ status_t DispSync::changePhaseOffset(Callback* callback, nsecs_t phase) { void DispSync::setPeriod(nsecs_t period) { Mutex::Autolock lock(mMutex); mPeriod = period; mPhase = 0; mThread->updateModel(mPeriod, mPhase, mReferenceTime); if (mTraceDetailedInfo) { ATRACE_INT("DispSync:PendingPeriod", period); } mPendingPeriod = period; } nsecs_t DispSync::getPeriod() { Loading
services/surfaceflinger/Scheduler/DispSync.h +14 −2 Original line number Diff line number Diff line Loading @@ -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) = 0; virtual bool addResyncSample(nsecs_t timestamp, bool* periodChanged) = 0; virtual void endResync() = 0; virtual void setPeriod(nsecs_t period) = 0; virtual nsecs_t getPeriod() = 0; Loading Loading @@ -119,7 +119,13 @@ public: // addPresentFence returns true indicating that the model has drifted away // from the hardware vsync events. void beginResync() override; bool addResyncSample(nsecs_t timestamp) 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 // 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; void endResync() override; // The setPeriod method sets the vsync event model's period to a specific Loading Loading @@ -199,6 +205,12 @@ private: // nanoseconds. nsecs_t mPeriod; // 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 // vsync frequency. nsecs_t mPendingPeriod = 0; // mPhase is the phase offset of the modeled vsync events. It is the // number of nanoseconds from time 0 to the first vsync event. nsecs_t mPhase; Loading
services/surfaceflinger/Scheduler/PhaseOffsets.h +2 −2 Original line number Diff line number Diff line Loading @@ -68,8 +68,8 @@ public: void dump(std::string& result) const override; private: Offsets getmDefaultRefreshRateOffsets() { return mDefaultRefreshRateOffsets; } Offsets getmHighRefreshRateOffsets() { return mHighRefreshRateOffsets; } Offsets getDefaultRefreshRateOffsets() { return mDefaultRefreshRateOffsets; } Offsets getHighRefreshRateOffsets() { return mHighRefreshRateOffsets; } std::atomic<RefreshRateConfigs::RefreshRateType> mRefreshRateType = RefreshRateConfigs::RefreshRateType::DEFAULT; Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -249,7 +249,6 @@ void Scheduler::setRefreshSkipCount(int count) { void Scheduler::setVsyncPeriod(const nsecs_t period) { std::lock_guard<std::mutex> lock(mHWVsyncLock); mPrimaryDispSync->reset(); mPrimaryDispSync->setPeriod(period); if (!mPrimaryHWVsyncEnabled) { Loading @@ -259,12 +258,13 @@ void Scheduler::setVsyncPeriod(const nsecs_t period) { } } void Scheduler::addResyncSample(const nsecs_t timestamp) { void Scheduler::addResyncSample(const nsecs_t timestamp, bool* periodChanged) { bool needsHwVsync = false; *periodChanged = false; { // Scope for the lock std::lock_guard<std::mutex> lock(mHWVsyncLock); if (mPrimaryHWVsyncEnabled) { needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp); needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp, periodChanged); } } Loading
services/surfaceflinger/Scheduler/Scheduler.h +3 −1 Original line number Diff line number Diff line Loading @@ -139,7 +139,9 @@ public: // Creates a callback for resyncing. ResyncCallback makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod); void setRefreshSkipCount(int count); void addResyncSample(const nsecs_t timestamp); // 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); void addPresentFence(const std::shared_ptr<FenceTime>& fenceTime); void setIgnorePresentFences(bool ignore); nsecs_t expectedPresentTime(); Loading