Loading services/surfaceflinger/DispSync.cpp +39 −33 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ #include <utils/Trace.h> #include <utils/Vector.h> #include <ui/Fence.h> #include <ui/FenceTime.h> #include "DispSync.h" #include "SurfaceFlinger.h" Loading Loading @@ -419,25 +419,13 @@ void DispSync::reset() { resetErrorLocked(); } bool DispSync::addPresentFence(const sp<Fence>& fence) { bool DispSync::addPresentFence(const std::shared_ptr<FenceTime>& fenceTime) { Mutex::Autolock lock(mMutex); mPresentFences[mPresentSampleOffset] = fence; mPresentTimes[mPresentSampleOffset] = 0; mPresentFences[mPresentSampleOffset] = fenceTime; mPresentSampleOffset = (mPresentSampleOffset + 1) % NUM_PRESENT_SAMPLES; mNumResyncSamplesSincePresent = 0; for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) { const sp<Fence>& f(mPresentFences[i]); if (f != NULL) { nsecs_t t = f->getSignalTime(); if (t < INT64_MAX) { mPresentFences[i].clear(); mPresentTimes[i] = t + mPresentTimeOffset; } } } updateErrorLocked(); return !mModelUpdated || mError > kErrorThreshold; Loading Loading @@ -602,8 +590,21 @@ void DispSync::updateErrorLocked() { nsecs_t sqErrSum = 0; for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) { nsecs_t sample = mPresentTimes[i] - mReferenceTime; if (sample > mPhase) { // Only check for the cached value of signal time to avoid unecessary // syscalls. It is the responsibility of the DispSync owner to // call getSignalTime() periodically so the cache is updated when the // fence signals. nsecs_t time = mPresentFences[i]->getCachedSignalTime(); if (time == Fence::SIGNAL_TIME_PENDING || time == Fence::SIGNAL_TIME_INVALID) { continue; } nsecs_t sample = time - mReferenceTime; if (sample <= mPhase) { continue; } nsecs_t sampleErr = (sample - mPhase) % period; if (sampleErr > period / 2) { sampleErr -= period; Loading @@ -611,12 +612,17 @@ void DispSync::updateErrorLocked() { sqErrSum += sampleErr * sampleErr; numErrSamples++; } } if (numErrSamples > 0) { mError = sqErrSum / numErrSamples; mZeroErrSamplesCount = 0; } else { mError = 0; // Use mod ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT to avoid log spam. mZeroErrSamplesCount++; ALOGE_IF( (mZeroErrSamplesCount % ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT) == 0, "No present times for model error."); } if (kTraceDetailedInfo) { Loading @@ -627,9 +633,9 @@ void DispSync::updateErrorLocked() { void DispSync::resetErrorLocked() { mPresentSampleOffset = 0; mError = 0; mZeroErrSamplesCount = 0; for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) { mPresentFences[i].clear(); mPresentTimes[i] = 0; mPresentFences[i] = FenceTime::NO_FENCE; } } Loading Loading @@ -668,19 +674,19 @@ void DispSync::dump(String8& result) const { previous = sampleTime; } result.appendFormat("mPresentFences / mPresentTimes [%d]:\n", result.appendFormat("mPresentFences [%d]:\n", NUM_PRESENT_SAMPLES); nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); previous = 0; previous = Fence::SIGNAL_TIME_INVALID; for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) { size_t idx = (i + mPresentSampleOffset) % NUM_PRESENT_SAMPLES; bool signaled = mPresentFences[idx] == NULL; nsecs_t presentTime = mPresentTimes[idx]; if (!signaled) { nsecs_t presentTime = mPresentFences[idx]->getSignalTime(); if (presentTime == Fence::SIGNAL_TIME_PENDING) { result.appendFormat(" [unsignaled fence]\n"); } else if (presentTime == 0) { result.appendFormat(" 0\n"); } else if (previous == 0) { } else if(presentTime == Fence::SIGNAL_TIME_INVALID) { result.appendFormat(" [invalid fence]\n"); } else if (previous == Fence::SIGNAL_TIME_PENDING || previous == Fence::SIGNAL_TIME_INVALID) { result.appendFormat(" %" PRId64 " (%.3f ms ago)\n", presentTime, (now - presentTime) / 1000000.0); } else { Loading services/surfaceflinger/DispSync.h +15 −5 Original line number Diff line number Diff line Loading @@ -23,10 +23,14 @@ #include <utils/Timers.h> #include <utils/RefBase.h> #include <ui/FenceTime.h> #include <memory> namespace android { class String8; class Fence; class FenceTime; class DispSyncThread; // DispSync maintains a model of the periodic hardware-based vsync events of a Loading Loading @@ -67,7 +71,7 @@ public: // // This method should be called with the retire fence from each HWComposer // set call that affects the display. bool addPresentFence(const sp<Fence>& fence); bool addPresentFence(const std::shared_ptr<FenceTime>& fenceTime); // The beginResync, addResyncSample, and endResync methods are used to re- // synchronize the DispSync's model to the hardware vsync events. The re- Loading Loading @@ -129,6 +133,7 @@ private: enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 6 }; enum { NUM_PRESENT_SAMPLES = 8 }; enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 4 }; enum { ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT = 64 }; const char* const mName; Loading @@ -146,9 +151,14 @@ private: // mError is the computed model error. It is based on the difference // between the estimated vsync event times and those observed in the // mPresentTimes array. // mPresentFences array. nsecs_t mError; // mZeroErrSamplesCount keeps track of how many times in a row there were // zero timestamps available in the mPresentFences array. // Used to sanity check that we are able to calculate the model error. size_t mZeroErrSamplesCount; // Whether we have updated the vsync event model since the last resync. bool mModelUpdated; Loading @@ -162,8 +172,8 @@ private: // These member variables store information about the present fences used // to validate the currently computed model. sp<Fence> mPresentFences[NUM_PRESENT_SAMPLES]; nsecs_t mPresentTimes[NUM_PRESENT_SAMPLES]; std::shared_ptr<FenceTime> mPresentFences[NUM_PRESENT_SAMPLES] {FenceTime::NO_FENCE}; size_t mPresentSampleOffset; int mRefreshSkipCount; Loading services/surfaceflinger/Layer.cpp +10 −4 Original line number Diff line number Diff line Loading @@ -1309,7 +1309,8 @@ bool Layer::headFenceHasSignaled() const { // able to be latched. To avoid this, grab this buffer anyway. return true; } return mQueueItems[0].mFence->getSignalTime() != INT64_MAX; return mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING; #else return true; #endif Loading Loading @@ -2012,9 +2013,6 @@ bool Layer::onPreComposition(nsecs_t refreshStartTime) { bool Layer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence, const std::shared_ptr<FenceTime>& presentFence, const CompositorTiming& compositorTiming) { mAcquireTimeline.updateSignalTimes(); mReleaseTimeline.updateSignalTimes(); // mFrameLatencyNeeded is true when a new frame was latched for the // composition. if (!mFrameLatencyNeeded) Loading Loading @@ -2065,6 +2063,7 @@ void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) { auto releaseFenceTime = std::make_shared<FenceTime>( mSurfaceFlingerConsumer->getPrevFinalReleaseFence()); mReleaseTimeline.updateSignalTimes(); mReleaseTimeline.push(releaseFenceTime); Mutex::Autolock lock(mFrameEventHistoryMutex); Loading Loading @@ -2255,6 +2254,7 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) #ifndef USE_HWC2 auto releaseFenceTime = std::make_shared<FenceTime>( mSurfaceFlingerConsumer->getPrevFinalReleaseFence()); mReleaseTimeline.updateSignalTimes(); mReleaseTimeline.push(releaseFenceTime); if (mPreviousFrameNumber != 0) { mFrameEventHistory.addRelease(mPreviousFrameNumber, Loading Loading @@ -2510,6 +2510,12 @@ void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, FrameEventHistoryDelta *outDelta) { Mutex::Autolock lock(mFrameEventHistoryMutex); if (newTimestamps) { // If there are any unsignaled fences in the aquire timeline at this // point, the previously queued frame hasn't been latched yet. Go ahead // and try to get the signal time here so the syscall is taken out of // the main thread's critical path. mAcquireTimeline.updateSignalTimes(); // Push the new fence after updating since it's likely still pending. mAcquireTimeline.push(newTimestamps->acquireFence); mFrameEventHistory.addQueue(*newTimestamps); } Loading services/surfaceflinger/SurfaceFlinger.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -1553,6 +1553,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) // |mStateLock| not needed as we are on the main thread const sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked()); mGlCompositionDoneTimeline.updateSignalTimes(); std::shared_ptr<FenceTime> glCompositionDoneFenceTime; if (mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) { glCompositionDoneFenceTime = Loading @@ -1561,12 +1562,11 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) } else { glCompositionDoneFenceTime = FenceTime::NO_FENCE; } mGlCompositionDoneTimeline.updateSignalTimes(); mDisplayTimeline.updateSignalTimes(); sp<Fence> presentFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY); auto presentFenceTime = std::make_shared<FenceTime>(presentFence); mDisplayTimeline.push(presentFenceTime); mDisplayTimeline.updateSignalTimes(); nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0); nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod(); Loading @@ -1591,8 +1591,8 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) } }); if (presentFence->isValid()) { if (mPrimaryDispSync.addPresentFence(presentFence)) { if (presentFenceTime->isValid()) { if (mPrimaryDispSync.addPresentFence(presentFenceTime)) { enableHardwareVsync(); } else { disableHardwareVsync(false); Loading services/surfaceflinger/SurfaceFlinger_hwc1.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -1257,6 +1257,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) const HWComposer& hwc = getHwComposer(); const sp<const DisplayDevice> hw(getDefaultDisplayDevice()); mGlCompositionDoneTimeline.updateSignalTimes(); std::shared_ptr<FenceTime> glCompositionDoneFenceTime; if (getHwComposer().hasGlesComposition(hw->getHwcDisplayId())) { glCompositionDoneFenceTime = Loading @@ -1265,12 +1266,11 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) } else { glCompositionDoneFenceTime = FenceTime::NO_FENCE; } mGlCompositionDoneTimeline.updateSignalTimes(); mDisplayTimeline.updateSignalTimes(); sp<Fence> retireFence = mHwc->getDisplayFence(HWC_DISPLAY_PRIMARY); auto retireFenceTime = std::make_shared<FenceTime>(retireFence); mDisplayTimeline.push(retireFenceTime); mDisplayTimeline.updateSignalTimes(); nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0); nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod(); Loading Loading @@ -1298,7 +1298,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) }); if (retireFence->isValid()) { if (mPrimaryDispSync.addPresentFence(retireFence)) { if (mPrimaryDispSync.addPresentFence(retireFenceTime)) { enableHardwareVsync(); } else { disableHardwareVsync(false); Loading Loading
services/surfaceflinger/DispSync.cpp +39 −33 Original line number Diff line number Diff line Loading @@ -30,7 +30,7 @@ #include <utils/Trace.h> #include <utils/Vector.h> #include <ui/Fence.h> #include <ui/FenceTime.h> #include "DispSync.h" #include "SurfaceFlinger.h" Loading Loading @@ -419,25 +419,13 @@ void DispSync::reset() { resetErrorLocked(); } bool DispSync::addPresentFence(const sp<Fence>& fence) { bool DispSync::addPresentFence(const std::shared_ptr<FenceTime>& fenceTime) { Mutex::Autolock lock(mMutex); mPresentFences[mPresentSampleOffset] = fence; mPresentTimes[mPresentSampleOffset] = 0; mPresentFences[mPresentSampleOffset] = fenceTime; mPresentSampleOffset = (mPresentSampleOffset + 1) % NUM_PRESENT_SAMPLES; mNumResyncSamplesSincePresent = 0; for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) { const sp<Fence>& f(mPresentFences[i]); if (f != NULL) { nsecs_t t = f->getSignalTime(); if (t < INT64_MAX) { mPresentFences[i].clear(); mPresentTimes[i] = t + mPresentTimeOffset; } } } updateErrorLocked(); return !mModelUpdated || mError > kErrorThreshold; Loading Loading @@ -602,8 +590,21 @@ void DispSync::updateErrorLocked() { nsecs_t sqErrSum = 0; for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) { nsecs_t sample = mPresentTimes[i] - mReferenceTime; if (sample > mPhase) { // Only check for the cached value of signal time to avoid unecessary // syscalls. It is the responsibility of the DispSync owner to // call getSignalTime() periodically so the cache is updated when the // fence signals. nsecs_t time = mPresentFences[i]->getCachedSignalTime(); if (time == Fence::SIGNAL_TIME_PENDING || time == Fence::SIGNAL_TIME_INVALID) { continue; } nsecs_t sample = time - mReferenceTime; if (sample <= mPhase) { continue; } nsecs_t sampleErr = (sample - mPhase) % period; if (sampleErr > period / 2) { sampleErr -= period; Loading @@ -611,12 +612,17 @@ void DispSync::updateErrorLocked() { sqErrSum += sampleErr * sampleErr; numErrSamples++; } } if (numErrSamples > 0) { mError = sqErrSum / numErrSamples; mZeroErrSamplesCount = 0; } else { mError = 0; // Use mod ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT to avoid log spam. mZeroErrSamplesCount++; ALOGE_IF( (mZeroErrSamplesCount % ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT) == 0, "No present times for model error."); } if (kTraceDetailedInfo) { Loading @@ -627,9 +633,9 @@ void DispSync::updateErrorLocked() { void DispSync::resetErrorLocked() { mPresentSampleOffset = 0; mError = 0; mZeroErrSamplesCount = 0; for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) { mPresentFences[i].clear(); mPresentTimes[i] = 0; mPresentFences[i] = FenceTime::NO_FENCE; } } Loading Loading @@ -668,19 +674,19 @@ void DispSync::dump(String8& result) const { previous = sampleTime; } result.appendFormat("mPresentFences / mPresentTimes [%d]:\n", result.appendFormat("mPresentFences [%d]:\n", NUM_PRESENT_SAMPLES); nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); previous = 0; previous = Fence::SIGNAL_TIME_INVALID; for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) { size_t idx = (i + mPresentSampleOffset) % NUM_PRESENT_SAMPLES; bool signaled = mPresentFences[idx] == NULL; nsecs_t presentTime = mPresentTimes[idx]; if (!signaled) { nsecs_t presentTime = mPresentFences[idx]->getSignalTime(); if (presentTime == Fence::SIGNAL_TIME_PENDING) { result.appendFormat(" [unsignaled fence]\n"); } else if (presentTime == 0) { result.appendFormat(" 0\n"); } else if (previous == 0) { } else if(presentTime == Fence::SIGNAL_TIME_INVALID) { result.appendFormat(" [invalid fence]\n"); } else if (previous == Fence::SIGNAL_TIME_PENDING || previous == Fence::SIGNAL_TIME_INVALID) { result.appendFormat(" %" PRId64 " (%.3f ms ago)\n", presentTime, (now - presentTime) / 1000000.0); } else { Loading
services/surfaceflinger/DispSync.h +15 −5 Original line number Diff line number Diff line Loading @@ -23,10 +23,14 @@ #include <utils/Timers.h> #include <utils/RefBase.h> #include <ui/FenceTime.h> #include <memory> namespace android { class String8; class Fence; class FenceTime; class DispSyncThread; // DispSync maintains a model of the periodic hardware-based vsync events of a Loading Loading @@ -67,7 +71,7 @@ public: // // This method should be called with the retire fence from each HWComposer // set call that affects the display. bool addPresentFence(const sp<Fence>& fence); bool addPresentFence(const std::shared_ptr<FenceTime>& fenceTime); // The beginResync, addResyncSample, and endResync methods are used to re- // synchronize the DispSync's model to the hardware vsync events. The re- Loading Loading @@ -129,6 +133,7 @@ private: enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 6 }; enum { NUM_PRESENT_SAMPLES = 8 }; enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 4 }; enum { ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT = 64 }; const char* const mName; Loading @@ -146,9 +151,14 @@ private: // mError is the computed model error. It is based on the difference // between the estimated vsync event times and those observed in the // mPresentTimes array. // mPresentFences array. nsecs_t mError; // mZeroErrSamplesCount keeps track of how many times in a row there were // zero timestamps available in the mPresentFences array. // Used to sanity check that we are able to calculate the model error. size_t mZeroErrSamplesCount; // Whether we have updated the vsync event model since the last resync. bool mModelUpdated; Loading @@ -162,8 +172,8 @@ private: // These member variables store information about the present fences used // to validate the currently computed model. sp<Fence> mPresentFences[NUM_PRESENT_SAMPLES]; nsecs_t mPresentTimes[NUM_PRESENT_SAMPLES]; std::shared_ptr<FenceTime> mPresentFences[NUM_PRESENT_SAMPLES] {FenceTime::NO_FENCE}; size_t mPresentSampleOffset; int mRefreshSkipCount; Loading
services/surfaceflinger/Layer.cpp +10 −4 Original line number Diff line number Diff line Loading @@ -1309,7 +1309,8 @@ bool Layer::headFenceHasSignaled() const { // able to be latched. To avoid this, grab this buffer anyway. return true; } return mQueueItems[0].mFence->getSignalTime() != INT64_MAX; return mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING; #else return true; #endif Loading Loading @@ -2012,9 +2013,6 @@ bool Layer::onPreComposition(nsecs_t refreshStartTime) { bool Layer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence, const std::shared_ptr<FenceTime>& presentFence, const CompositorTiming& compositorTiming) { mAcquireTimeline.updateSignalTimes(); mReleaseTimeline.updateSignalTimes(); // mFrameLatencyNeeded is true when a new frame was latched for the // composition. if (!mFrameLatencyNeeded) Loading Loading @@ -2065,6 +2063,7 @@ void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) { auto releaseFenceTime = std::make_shared<FenceTime>( mSurfaceFlingerConsumer->getPrevFinalReleaseFence()); mReleaseTimeline.updateSignalTimes(); mReleaseTimeline.push(releaseFenceTime); Mutex::Autolock lock(mFrameEventHistoryMutex); Loading Loading @@ -2255,6 +2254,7 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) #ifndef USE_HWC2 auto releaseFenceTime = std::make_shared<FenceTime>( mSurfaceFlingerConsumer->getPrevFinalReleaseFence()); mReleaseTimeline.updateSignalTimes(); mReleaseTimeline.push(releaseFenceTime); if (mPreviousFrameNumber != 0) { mFrameEventHistory.addRelease(mPreviousFrameNumber, Loading Loading @@ -2510,6 +2510,12 @@ void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, FrameEventHistoryDelta *outDelta) { Mutex::Autolock lock(mFrameEventHistoryMutex); if (newTimestamps) { // If there are any unsignaled fences in the aquire timeline at this // point, the previously queued frame hasn't been latched yet. Go ahead // and try to get the signal time here so the syscall is taken out of // the main thread's critical path. mAcquireTimeline.updateSignalTimes(); // Push the new fence after updating since it's likely still pending. mAcquireTimeline.push(newTimestamps->acquireFence); mFrameEventHistory.addQueue(*newTimestamps); } Loading
services/surfaceflinger/SurfaceFlinger.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -1553,6 +1553,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) // |mStateLock| not needed as we are on the main thread const sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked()); mGlCompositionDoneTimeline.updateSignalTimes(); std::shared_ptr<FenceTime> glCompositionDoneFenceTime; if (mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) { glCompositionDoneFenceTime = Loading @@ -1561,12 +1562,11 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) } else { glCompositionDoneFenceTime = FenceTime::NO_FENCE; } mGlCompositionDoneTimeline.updateSignalTimes(); mDisplayTimeline.updateSignalTimes(); sp<Fence> presentFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY); auto presentFenceTime = std::make_shared<FenceTime>(presentFence); mDisplayTimeline.push(presentFenceTime); mDisplayTimeline.updateSignalTimes(); nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0); nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod(); Loading @@ -1591,8 +1591,8 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) } }); if (presentFence->isValid()) { if (mPrimaryDispSync.addPresentFence(presentFence)) { if (presentFenceTime->isValid()) { if (mPrimaryDispSync.addPresentFence(presentFenceTime)) { enableHardwareVsync(); } else { disableHardwareVsync(false); Loading
services/surfaceflinger/SurfaceFlinger_hwc1.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -1257,6 +1257,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) const HWComposer& hwc = getHwComposer(); const sp<const DisplayDevice> hw(getDefaultDisplayDevice()); mGlCompositionDoneTimeline.updateSignalTimes(); std::shared_ptr<FenceTime> glCompositionDoneFenceTime; if (getHwComposer().hasGlesComposition(hw->getHwcDisplayId())) { glCompositionDoneFenceTime = Loading @@ -1265,12 +1266,11 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) } else { glCompositionDoneFenceTime = FenceTime::NO_FENCE; } mGlCompositionDoneTimeline.updateSignalTimes(); mDisplayTimeline.updateSignalTimes(); sp<Fence> retireFence = mHwc->getDisplayFence(HWC_DISPLAY_PRIMARY); auto retireFenceTime = std::make_shared<FenceTime>(retireFence); mDisplayTimeline.push(retireFenceTime); mDisplayTimeline.updateSignalTimes(); nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0); nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod(); Loading Loading @@ -1298,7 +1298,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) }); if (retireFence->isValid()) { if (mPrimaryDispSync.addPresentFence(retireFence)) { if (mPrimaryDispSync.addPresentFence(retireFenceTime)) { enableHardwareVsync(); } else { disableHardwareVsync(false); Loading