Loading services/surfaceflinger/Scheduler/DispSync.cpp +26 −12 Original line number Diff line number Diff line Loading @@ -115,11 +115,13 @@ public: void lockModel() { Mutex::Autolock lock(mMutex); mModelLocked = true; ATRACE_INT("DispSync:ModelLocked", mModelLocked); } void unlockModel() { Mutex::Autolock lock(mMutex); mModelLocked = false; ATRACE_INT("DispSync:ModelLocked", mModelLocked); } virtual bool threadLoop() { Loading Loading @@ -493,7 +495,6 @@ void DispSync::init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) { ALOGE("Couldn't set SCHED_FIFO for DispSyncThread"); } reset(); beginResync(); if (mTraceDetailedInfo && kEnableZeroPhaseTracer) { Loading Loading @@ -545,17 +546,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) { Loading @@ -569,16 +568,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. Loading Loading @@ -609,6 +612,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; Loading Loading @@ -643,10 +647,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() { Loading Loading @@ -764,6 +775,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; } Loading services/surfaceflinger/Scheduler/DispSync.h +14 −7 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, 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; Loading Loading @@ -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. Loading Loading @@ -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 Loading Loading @@ -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 Loading services/surfaceflinger/Scheduler/Scheduler.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -280,13 +280,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); } } Loading Loading @@ -415,7 +415,7 @@ void Scheduler::resetKernelTimerCallback() { ATRACE_INT("ExpiredKernelIdleTimer", 0); std::lock_guard<std::mutex> lock(mCallbackLock); if (mGetVsyncPeriod) { resyncToHardwareVsync(false, mGetVsyncPeriod()); resyncToHardwareVsync(true, mGetVsyncPeriod()); } } Loading services/surfaceflinger/Scheduler/Scheduler.h +8 −3 Original line number Diff line number Diff line Loading @@ -135,13 +135,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(); Loading services/surfaceflinger/Scheduler/VSyncModulator.h +1 −1 Original line number Diff line number Diff line Loading @@ -116,7 +116,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; } Loading Loading
services/surfaceflinger/Scheduler/DispSync.cpp +26 −12 Original line number Diff line number Diff line Loading @@ -115,11 +115,13 @@ public: void lockModel() { Mutex::Autolock lock(mMutex); mModelLocked = true; ATRACE_INT("DispSync:ModelLocked", mModelLocked); } void unlockModel() { Mutex::Autolock lock(mMutex); mModelLocked = false; ATRACE_INT("DispSync:ModelLocked", mModelLocked); } virtual bool threadLoop() { Loading Loading @@ -493,7 +495,6 @@ void DispSync::init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) { ALOGE("Couldn't set SCHED_FIFO for DispSyncThread"); } reset(); beginResync(); if (mTraceDetailedInfo && kEnableZeroPhaseTracer) { Loading Loading @@ -545,17 +546,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) { Loading @@ -569,16 +568,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. Loading Loading @@ -609,6 +612,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; Loading Loading @@ -643,10 +647,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() { Loading Loading @@ -764,6 +775,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; } Loading
services/surfaceflinger/Scheduler/DispSync.h +14 −7 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, 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; Loading Loading @@ -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. Loading Loading @@ -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 Loading Loading @@ -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 Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -280,13 +280,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); } } Loading Loading @@ -415,7 +415,7 @@ void Scheduler::resetKernelTimerCallback() { ATRACE_INT("ExpiredKernelIdleTimer", 0); std::lock_guard<std::mutex> lock(mCallbackLock); if (mGetVsyncPeriod) { resyncToHardwareVsync(false, mGetVsyncPeriod()); resyncToHardwareVsync(true, mGetVsyncPeriod()); } } Loading
services/surfaceflinger/Scheduler/Scheduler.h +8 −3 Original line number Diff line number Diff line Loading @@ -135,13 +135,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(); Loading
services/surfaceflinger/Scheduler/VSyncModulator.h +1 −1 Original line number Diff line number Diff line Loading @@ -116,7 +116,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; } Loading