diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp index d771e2c2a..c60834ea2 100644 --- a/services/surfaceflinger/DispSync.cpp +++ b/services/surfaceflinger/DispSync.cpp @@ -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: @@ -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); } @@ -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(); @@ -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()); } } @@ -356,14 +348,14 @@ bool DispSync::addPresentFence(const sp& 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() { @@ -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 @@ -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() { @@ -459,7 +451,7 @@ void DispSync::updateModelLocked() { mPhase += mPeriod; } - if (traceDetailedInfo) { + if (kTraceDetailedInfo) { ATRACE_INT64("DispSync:Period", mPeriod); ATRACE_INT64("DispSync:Phase", mPhase); } @@ -494,7 +486,7 @@ void DispSync::updateErrorLocked() { mError = 0; } - if (traceDetailedInfo) { + if (kTraceDetailedInfo) { ATRACE_INT64("DispSync:Error", mError); } } @@ -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("mPhase: %"PRId64" ns\n", mPhase); - result.appendFormat("mError: %"PRId64" ns (sqrt: %.1f)\n", + 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", 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"); @@ -531,9 +526,9 @@ void DispSync::dump(String8& result) const { size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES; nsecs_t sampleTime = mResyncSamples[idx]; if (i == 0) { - result.appendFormat(" %"PRId64"\n", sampleTime); + result.appendFormat(" %" PRId64 "\n", sampleTime); } else { - result.appendFormat(" %"PRId64" (+%"PRId64")\n", + result.appendFormat(" %" PRId64 " (+%" PRId64 ")\n", sampleTime, sampleTime - previous); } previous = sampleTime; @@ -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; @@ -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 diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h index a33ce5d8b..5106bc89d 100644 --- a/services/surfaceflinger/DispSync.h +++ b/services/surfaceflinger/DispSync.h @@ -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; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 59afa66ae..1d7c3c632 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -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 @@ -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() {} @@ -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(this)); @@ -348,7 +343,7 @@ public: ALOGE("error unregistering vsync callback: %s (%d)", strerror(-err), err); } - ATRACE_INT("VsyncOn", 0); + //ATRACE_INT(mVsyncOnLabel.string(), 0); } } @@ -366,7 +361,7 @@ private: if (mTraceVsync) { mValue = (mValue + 1) % 2; - ATRACE_INT("VSYNC", mValue); + ATRACE_INT(mVsyncEventLabel.string(), mValue); } } @@ -379,6 +374,8 @@ private: const nsecs_t mPhaseOffset; const bool mTraceVsync; + const String8 mVsyncOnLabel; + const String8 mVsyncEventLabel; DispSync* mDispSync; sp mCallback; @@ -449,10 +446,10 @@ void SurfaceFlinger::init() { // start the EventThread sp vsyncSrc = new DispSyncSource(&mPrimaryDispSync, - vsyncPhaseOffsetNs, true); + vsyncPhaseOffsetNs, true, "app"); mEventThread = new EventThread(vsyncSrc); sp sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, - sfVsyncPhaseOffsetNs, false); + sfVsyncPhaseOffsetNs, true, "sf"); mSFEventThread = new EventThread(sfVsyncSrc); mEventQueue.setEventThread(mSFEventThread); @@ -858,7 +855,7 @@ void SurfaceFlinger::postComposition() } } - if (runningWithoutSyncFramework) { + if (kIgnorePresentFences) { const sp hw(getDefaultDisplayDevice()); if (hw->isScreenAcquired()) { enableHardwareVsync();