Loading services/surfaceflinger/DispSync.cpp +37 −35 Original line number Diff line number Diff line Loading @@ -37,25 +37,17 @@ namespace android { // Setting this to true enables verbose tracing that can be used to debug // vsync event model or phase issues. static const bool traceDetailedInfo = false; static const bool kTraceDetailedInfo = false; // This is the threshold used to determine when hardware vsync events are // needed to re-synchronize the software vsync model with the hardware. The // error metric used is the mean of the squared difference between each // present time and the nearest software-predicted vsync. static const nsecs_t errorThreshold = 160000000000; // This works around the lack of support for the sync framework on some // devices. #ifdef RUNNING_WITHOUT_SYNC_FRAMEWORK static const bool runningWithoutSyncFramework = true; #else static const bool runningWithoutSyncFramework = false; #endif static const nsecs_t kErrorThreshold = 160000000000; // 400 usec squared // This is the offset from the present fence timestamps to the corresponding // vsync event. static const int64_t presentTimeOffset = PRESENT_TIME_OFFSET_FROM_VSYNC_NS; static const int64_t kPresentTimeOffset = PRESENT_TIME_OFFSET_FROM_VSYNC_NS; class DispSyncThread: public Thread { public: Loading Loading @@ -138,7 +130,7 @@ public: // Don't correct by more than 500 us mWakeupLatency = 500000; } if (traceDetailedInfo) { if (kTraceDetailedInfo) { ATRACE_INT64("DispSync:WakeupLat", now - nextEventTime); ATRACE_INT64("DispSync:AvgWakeupLat", mWakeupLatency); } Loading Loading @@ -207,8 +199,7 @@ public: return BAD_VALUE; } // This method is only here to handle the runningWithoutSyncFramework // case. // This method is only here to handle the kIgnorePresentFences case. bool hasAnyEventListeners() { Mutex::Autolock lock(mMutex); return !mEventListeners.empty(); Loading Loading @@ -320,12 +311,13 @@ DispSync::DispSync() { reset(); beginResync(); if (traceDetailedInfo) { // If runningWithoutSyncFramework is true then the ZeroPhaseTracer if (kTraceDetailedInfo) { // If we're not getting present fences then the ZeroPhaseTracer // would prevent HW vsync event from ever being turned off. // Furthermore the zero-phase tracing is not needed because any time // there is an event registered we will turn on the HW vsync events. if (!runningWithoutSyncFramework) { // Even if we're just ignoring the fences, the zero-phase tracing is // not needed because any time there is an event registered we will // turn on the HW vsync events. if (!kIgnorePresentFences) { addEventListener(0, new ZeroPhaseTracer()); } } Loading Loading @@ -356,14 +348,14 @@ bool DispSync::addPresentFence(const sp<Fence>& fence) { nsecs_t t = f->getSignalTime(); if (t < INT64_MAX) { mPresentFences[i].clear(); mPresentTimes[i] = t + presentTimeOffset; mPresentTimes[i] = t + kPresentTimeOffset; } } } updateErrorLocked(); return mPeriod == 0 || mError > errorThreshold; return mPeriod == 0 || mError > kErrorThreshold; } void DispSync::beginResync() { Loading @@ -390,7 +382,7 @@ bool DispSync::addResyncSample(nsecs_t timestamp) { resetErrorLocked(); } if (runningWithoutSyncFramework) { if (kIgnorePresentFences) { // If we don't have the sync framework we will never have // addPresentFence called. This means we have no way to know whether // or not we're synchronized with the HW vsyncs, so we just request Loading @@ -399,7 +391,7 @@ bool DispSync::addResyncSample(nsecs_t timestamp) { return mThread->hasAnyEventListeners(); } return mPeriod == 0 || mError > errorThreshold; return mPeriod == 0 || mError > kErrorThreshold; } void DispSync::endResync() { Loading Loading @@ -459,7 +451,7 @@ void DispSync::updateModelLocked() { mPhase += mPeriod; } if (traceDetailedInfo) { if (kTraceDetailedInfo) { ATRACE_INT64("DispSync:Period", mPeriod); ATRACE_INT64("DispSync:Phase", mPhase); } Loading Loading @@ -494,7 +486,7 @@ void DispSync::updateErrorLocked() { mError = 0; } if (traceDetailedInfo) { if (kTraceDetailedInfo) { ATRACE_INT64("DispSync:Error", mError); } } Loading @@ -516,13 +508,16 @@ nsecs_t DispSync::computeNextRefresh(int periodOffset) const { void DispSync::dump(String8& result) const { Mutex::Autolock lock(mMutex); result.appendFormat("mPeriod: %"PRId64" ns\n", mPeriod); result.appendFormat("present fences are %s\n", kIgnorePresentFences ? "ignored" : "used"); result.appendFormat("mPeriod: %" PRId64 " ns (%.3f fps)\n", mPeriod, 1000000000.0 / mPeriod); result.appendFormat("mPhase: %" PRId64 " ns\n", mPhase); result.appendFormat("mError: %"PRId64" ns (sqrt: %.1f)\n", result.appendFormat("mError: %" PRId64 " ns (sqrt=%.1f)\n", mError, sqrt(mError)); result.appendFormat("mNumResyncSamplesSincePresent: %d (max %d)\n", result.appendFormat("mNumResyncSamplesSincePresent: %d (limit %d)\n", mNumResyncSamplesSincePresent, MAX_RESYNC_SAMPLES_WITHOUT_PRESENT); result.appendFormat("mNumResyncSamples: %d (max %d)\n", result.appendFormat("mNumResyncSamples: %zd (max %d)\n", mNumResyncSamples, MAX_RESYNC_SAMPLES); result.appendFormat("mResyncSamples:\n"); Loading @@ -541,6 +536,7 @@ void DispSync::dump(String8& result) const { result.appendFormat("mPresentFences / mPresentTimes [%d]:\n", NUM_PRESENT_SAMPLES); nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); previous = 0; for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) { size_t idx = (i + mPresentSampleOffset) % NUM_PRESENT_SAMPLES; Loading @@ -548,15 +544,21 @@ void DispSync::dump(String8& result) const { nsecs_t presentTime = mPresentTimes[idx]; if (!signaled) { result.appendFormat(" [unsignaled fence]\n"); } else if (presentTime == 0) { result.appendFormat(" 0\n"); } else if (previous == 0) { result.appendFormat(" %"PRId64"\n", presentTime); result.appendFormat(" %" PRId64 " (%.3f ms ago)\n", presentTime, (now - presentTime) / 1000000.0); } else { result.appendFormat(" %"PRId64" (+%"PRId64" / %.3f)\n", result.appendFormat(" %" PRId64 " (+%" PRId64 " / %.3f) (%.3f ms ago)\n", presentTime, presentTime - previous, (presentTime - previous) / (double) mPeriod); (presentTime - previous) / (double) mPeriod, (now - presentTime) / 1000000.0); } previous = presentTime; } result.appendFormat("current monotonic time: %" PRId64 "\n", now); } } // namespace android services/surfaceflinger/DispSync.h +12 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,18 @@ namespace android { // Ignore present (retire) fences if the device doesn't have support for the // sync framework, or if all phase offsets are zero. The latter is useful // because it allows us to avoid resync bursts on devices that don't need // phase-offset VSYNC events. #if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK) || \ (VSYNC_EVENT_PHASE_OFFSET_NS == 0 && SF_VSYNC_EVENT_PHASE_OFFSET_NS == 0) static const bool kIgnorePresentFences = true; #else static const bool kIgnorePresentFences = false; #endif class String8; class Fence; class DispSyncThread; Loading services/surfaceflinger/SurfaceFlinger.cpp +12 −15 Original line number Diff line number Diff line Loading @@ -88,14 +88,6 @@ EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint na namespace android { // This works around the lack of support for the sync framework on some // devices. #ifdef RUNNING_WITHOUT_SYNC_FRAMEWORK static const bool runningWithoutSyncFramework = true; #else static const bool runningWithoutSyncFramework = false; #endif // This is the phase offset in nanoseconds of the software vsync event // relative to the vsync event reported by HWComposer. The software vsync // event is when SurfaceFlinger and Choreographer-based applications run each Loading Loading @@ -322,10 +314,13 @@ void SurfaceFlinger::deleteTextureAsync(uint32_t texture) { class DispSyncSource : public VSyncSource, private DispSync::Callback { public: DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync) : DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync, const char* label) : mValue(0), mPhaseOffset(phaseOffset), mTraceVsync(traceVsync), mVsyncOnLabel(String8::format("VsyncOn-%s", label)), mVsyncEventLabel(String8::format("VSYNC-%s", label)), mDispSync(dispSync) {} virtual ~DispSyncSource() {} Loading @@ -340,7 +335,7 @@ public: ALOGE("error registering vsync callback: %s (%d)", strerror(-err), err); } ATRACE_INT("VsyncOn", 1); //ATRACE_INT(mVsyncOnLabel.string(), 1); } else { status_t err = mDispSync->removeEventListener( static_cast<DispSync::Callback*>(this)); Loading @@ -348,7 +343,7 @@ public: ALOGE("error unregistering vsync callback: %s (%d)", strerror(-err), err); } ATRACE_INT("VsyncOn", 0); //ATRACE_INT(mVsyncOnLabel.string(), 0); } } Loading @@ -366,7 +361,7 @@ private: if (mTraceVsync) { mValue = (mValue + 1) % 2; ATRACE_INT("VSYNC", mValue); ATRACE_INT(mVsyncEventLabel.string(), mValue); } } Loading @@ -379,6 +374,8 @@ private: const nsecs_t mPhaseOffset; const bool mTraceVsync; const String8 mVsyncOnLabel; const String8 mVsyncEventLabel; DispSync* mDispSync; sp<VSyncSource::Callback> mCallback; Loading Loading @@ -449,10 +446,10 @@ void SurfaceFlinger::init() { // start the EventThread sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true); vsyncPhaseOffsetNs, true, "app"); mEventThread = new EventThread(vsyncSrc); sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, false); sfVsyncPhaseOffsetNs, true, "sf"); mSFEventThread = new EventThread(sfVsyncSrc); mEventQueue.setEventThread(mSFEventThread); Loading Loading @@ -858,7 +855,7 @@ void SurfaceFlinger::postComposition() } } if (runningWithoutSyncFramework) { if (kIgnorePresentFences) { const sp<const DisplayDevice> hw(getDefaultDisplayDevice()); if (hw->isScreenAcquired()) { enableHardwareVsync(); Loading Loading
services/surfaceflinger/DispSync.cpp +37 −35 Original line number Diff line number Diff line Loading @@ -37,25 +37,17 @@ namespace android { // Setting this to true enables verbose tracing that can be used to debug // vsync event model or phase issues. static const bool traceDetailedInfo = false; static const bool kTraceDetailedInfo = false; // This is the threshold used to determine when hardware vsync events are // needed to re-synchronize the software vsync model with the hardware. The // error metric used is the mean of the squared difference between each // present time and the nearest software-predicted vsync. static const nsecs_t errorThreshold = 160000000000; // This works around the lack of support for the sync framework on some // devices. #ifdef RUNNING_WITHOUT_SYNC_FRAMEWORK static const bool runningWithoutSyncFramework = true; #else static const bool runningWithoutSyncFramework = false; #endif static const nsecs_t kErrorThreshold = 160000000000; // 400 usec squared // This is the offset from the present fence timestamps to the corresponding // vsync event. static const int64_t presentTimeOffset = PRESENT_TIME_OFFSET_FROM_VSYNC_NS; static const int64_t kPresentTimeOffset = PRESENT_TIME_OFFSET_FROM_VSYNC_NS; class DispSyncThread: public Thread { public: Loading Loading @@ -138,7 +130,7 @@ public: // Don't correct by more than 500 us mWakeupLatency = 500000; } if (traceDetailedInfo) { if (kTraceDetailedInfo) { ATRACE_INT64("DispSync:WakeupLat", now - nextEventTime); ATRACE_INT64("DispSync:AvgWakeupLat", mWakeupLatency); } Loading Loading @@ -207,8 +199,7 @@ public: return BAD_VALUE; } // This method is only here to handle the runningWithoutSyncFramework // case. // This method is only here to handle the kIgnorePresentFences case. bool hasAnyEventListeners() { Mutex::Autolock lock(mMutex); return !mEventListeners.empty(); Loading Loading @@ -320,12 +311,13 @@ DispSync::DispSync() { reset(); beginResync(); if (traceDetailedInfo) { // If runningWithoutSyncFramework is true then the ZeroPhaseTracer if (kTraceDetailedInfo) { // If we're not getting present fences then the ZeroPhaseTracer // would prevent HW vsync event from ever being turned off. // Furthermore the zero-phase tracing is not needed because any time // there is an event registered we will turn on the HW vsync events. if (!runningWithoutSyncFramework) { // Even if we're just ignoring the fences, the zero-phase tracing is // not needed because any time there is an event registered we will // turn on the HW vsync events. if (!kIgnorePresentFences) { addEventListener(0, new ZeroPhaseTracer()); } } Loading Loading @@ -356,14 +348,14 @@ bool DispSync::addPresentFence(const sp<Fence>& fence) { nsecs_t t = f->getSignalTime(); if (t < INT64_MAX) { mPresentFences[i].clear(); mPresentTimes[i] = t + presentTimeOffset; mPresentTimes[i] = t + kPresentTimeOffset; } } } updateErrorLocked(); return mPeriod == 0 || mError > errorThreshold; return mPeriod == 0 || mError > kErrorThreshold; } void DispSync::beginResync() { Loading @@ -390,7 +382,7 @@ bool DispSync::addResyncSample(nsecs_t timestamp) { resetErrorLocked(); } if (runningWithoutSyncFramework) { if (kIgnorePresentFences) { // If we don't have the sync framework we will never have // addPresentFence called. This means we have no way to know whether // or not we're synchronized with the HW vsyncs, so we just request Loading @@ -399,7 +391,7 @@ bool DispSync::addResyncSample(nsecs_t timestamp) { return mThread->hasAnyEventListeners(); } return mPeriod == 0 || mError > errorThreshold; return mPeriod == 0 || mError > kErrorThreshold; } void DispSync::endResync() { Loading Loading @@ -459,7 +451,7 @@ void DispSync::updateModelLocked() { mPhase += mPeriod; } if (traceDetailedInfo) { if (kTraceDetailedInfo) { ATRACE_INT64("DispSync:Period", mPeriod); ATRACE_INT64("DispSync:Phase", mPhase); } Loading Loading @@ -494,7 +486,7 @@ void DispSync::updateErrorLocked() { mError = 0; } if (traceDetailedInfo) { if (kTraceDetailedInfo) { ATRACE_INT64("DispSync:Error", mError); } } Loading @@ -516,13 +508,16 @@ nsecs_t DispSync::computeNextRefresh(int periodOffset) const { void DispSync::dump(String8& result) const { Mutex::Autolock lock(mMutex); result.appendFormat("mPeriod: %"PRId64" ns\n", mPeriod); result.appendFormat("present fences are %s\n", kIgnorePresentFences ? "ignored" : "used"); result.appendFormat("mPeriod: %" PRId64 " ns (%.3f fps)\n", mPeriod, 1000000000.0 / mPeriod); result.appendFormat("mPhase: %" PRId64 " ns\n", mPhase); result.appendFormat("mError: %"PRId64" ns (sqrt: %.1f)\n", result.appendFormat("mError: %" PRId64 " ns (sqrt=%.1f)\n", mError, sqrt(mError)); result.appendFormat("mNumResyncSamplesSincePresent: %d (max %d)\n", result.appendFormat("mNumResyncSamplesSincePresent: %d (limit %d)\n", mNumResyncSamplesSincePresent, MAX_RESYNC_SAMPLES_WITHOUT_PRESENT); result.appendFormat("mNumResyncSamples: %d (max %d)\n", result.appendFormat("mNumResyncSamples: %zd (max %d)\n", mNumResyncSamples, MAX_RESYNC_SAMPLES); result.appendFormat("mResyncSamples:\n"); Loading @@ -541,6 +536,7 @@ void DispSync::dump(String8& result) const { result.appendFormat("mPresentFences / mPresentTimes [%d]:\n", NUM_PRESENT_SAMPLES); nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); previous = 0; for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) { size_t idx = (i + mPresentSampleOffset) % NUM_PRESENT_SAMPLES; Loading @@ -548,15 +544,21 @@ void DispSync::dump(String8& result) const { nsecs_t presentTime = mPresentTimes[idx]; if (!signaled) { result.appendFormat(" [unsignaled fence]\n"); } else if (presentTime == 0) { result.appendFormat(" 0\n"); } else if (previous == 0) { result.appendFormat(" %"PRId64"\n", presentTime); result.appendFormat(" %" PRId64 " (%.3f ms ago)\n", presentTime, (now - presentTime) / 1000000.0); } else { result.appendFormat(" %"PRId64" (+%"PRId64" / %.3f)\n", result.appendFormat(" %" PRId64 " (+%" PRId64 " / %.3f) (%.3f ms ago)\n", presentTime, presentTime - previous, (presentTime - previous) / (double) mPeriod); (presentTime - previous) / (double) mPeriod, (now - presentTime) / 1000000.0); } previous = presentTime; } result.appendFormat("current monotonic time: %" PRId64 "\n", now); } } // namespace android
services/surfaceflinger/DispSync.h +12 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,18 @@ namespace android { // Ignore present (retire) fences if the device doesn't have support for the // sync framework, or if all phase offsets are zero. The latter is useful // because it allows us to avoid resync bursts on devices that don't need // phase-offset VSYNC events. #if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK) || \ (VSYNC_EVENT_PHASE_OFFSET_NS == 0 && SF_VSYNC_EVENT_PHASE_OFFSET_NS == 0) static const bool kIgnorePresentFences = true; #else static const bool kIgnorePresentFences = false; #endif class String8; class Fence; class DispSyncThread; Loading
services/surfaceflinger/SurfaceFlinger.cpp +12 −15 Original line number Diff line number Diff line Loading @@ -88,14 +88,6 @@ EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint na namespace android { // This works around the lack of support for the sync framework on some // devices. #ifdef RUNNING_WITHOUT_SYNC_FRAMEWORK static const bool runningWithoutSyncFramework = true; #else static const bool runningWithoutSyncFramework = false; #endif // This is the phase offset in nanoseconds of the software vsync event // relative to the vsync event reported by HWComposer. The software vsync // event is when SurfaceFlinger and Choreographer-based applications run each Loading Loading @@ -322,10 +314,13 @@ void SurfaceFlinger::deleteTextureAsync(uint32_t texture) { class DispSyncSource : public VSyncSource, private DispSync::Callback { public: DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync) : DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync, const char* label) : mValue(0), mPhaseOffset(phaseOffset), mTraceVsync(traceVsync), mVsyncOnLabel(String8::format("VsyncOn-%s", label)), mVsyncEventLabel(String8::format("VSYNC-%s", label)), mDispSync(dispSync) {} virtual ~DispSyncSource() {} Loading @@ -340,7 +335,7 @@ public: ALOGE("error registering vsync callback: %s (%d)", strerror(-err), err); } ATRACE_INT("VsyncOn", 1); //ATRACE_INT(mVsyncOnLabel.string(), 1); } else { status_t err = mDispSync->removeEventListener( static_cast<DispSync::Callback*>(this)); Loading @@ -348,7 +343,7 @@ public: ALOGE("error unregistering vsync callback: %s (%d)", strerror(-err), err); } ATRACE_INT("VsyncOn", 0); //ATRACE_INT(mVsyncOnLabel.string(), 0); } } Loading @@ -366,7 +361,7 @@ private: if (mTraceVsync) { mValue = (mValue + 1) % 2; ATRACE_INT("VSYNC", mValue); ATRACE_INT(mVsyncEventLabel.string(), mValue); } } Loading @@ -379,6 +374,8 @@ private: const nsecs_t mPhaseOffset; const bool mTraceVsync; const String8 mVsyncOnLabel; const String8 mVsyncEventLabel; DispSync* mDispSync; sp<VSyncSource::Callback> mCallback; Loading Loading @@ -449,10 +446,10 @@ void SurfaceFlinger::init() { // start the EventThread sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true); vsyncPhaseOffsetNs, true, "app"); mEventThread = new EventThread(vsyncSrc); sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, false); sfVsyncPhaseOffsetNs, true, "sf"); mSFEventThread = new EventThread(sfVsyncSrc); mEventQueue.setEventThread(mSFEventThread); Loading Loading @@ -858,7 +855,7 @@ void SurfaceFlinger::postComposition() } } if (runningWithoutSyncFramework) { if (kIgnorePresentFences) { const sp<const DisplayDevice> hw(getDefaultDisplayDevice()); if (hw->isScreenAcquired()) { enableHardwareVsync(); Loading