Loading services/surfaceflinger/DispSync.cpp +22 −27 Original line number Diff line number Diff line Loading @@ -53,10 +53,7 @@ class DispSyncThread: public Thread { public: DispSyncThread(): mLowPowerMode(false), mStop(false), mLastVsyncSent(false), mLastBufferFull(false), mPeriod(0), mPhase(0), mWakeupLatency(0) { Loading Loading @@ -140,19 +137,8 @@ public: } if (callbackInvocations.size() > 0) { if (mLowPowerMode) { if (!mLastVsyncSent || !mLastBufferFull) { fireCallbackInvocations(callbackInvocations); mLastVsyncSent = true; } else mLastVsyncSent = false; } else { fireCallbackInvocations(callbackInvocations); } mLastBufferFull = true; } else { mLastBufferFull = false; } } return false; Loading Loading @@ -205,7 +191,6 @@ public: return !mEventListeners.empty(); } bool mLowPowerMode; private: struct EventListener { Loading Loading @@ -278,8 +263,6 @@ private: } bool mStop; bool mLastVsyncSent; bool mLastBufferFull; nsecs_t mPeriod; nsecs_t mPhase; Loading @@ -304,8 +287,10 @@ private: bool mParity; }; DispSync::DispSync() { mThread = new DispSyncThread(); DispSync::DispSync() : mRefreshSkipCount(0), mThread(new DispSyncThread()) { mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); reset(); Loading Loading @@ -404,8 +389,11 @@ status_t DispSync::addEventListener(nsecs_t phase, return mThread->addEventListener(phase, callback); } void DispSync::setLowPowerMode(bool enabled) { mThread->mLowPowerMode = enabled; void DispSync::setRefreshSkipCount(int count) { Mutex::Autolock lock(mMutex); ALOGD("setRefreshSkipCount(%d)", count); mRefreshSkipCount = count; updateModelLocked(); } status_t DispSync::removeEventListener(const sp<Callback>& callback) { Loading Loading @@ -456,6 +444,9 @@ void DispSync::updateModelLocked() { ATRACE_INT64("DispSync:Phase", mPhase); } // Artificially inflate the period if requested. mPeriod += mPeriod * mRefreshSkipCount; mThread->updateModel(mPeriod, mPhase); } } Loading @@ -465,15 +456,19 @@ void DispSync::updateErrorLocked() { return; } // Need to compare present fences against the un-adjusted refresh period, // since they might arrive between two events. nsecs_t period = mPeriod / (1 + mRefreshSkipCount); int numErrSamples = 0; nsecs_t sqErrSum = 0; for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) { nsecs_t sample = mPresentTimes[i]; if (sample > mPhase) { nsecs_t sampleErr = (sample - mPhase) % mPeriod; if (sampleErr > mPeriod / 2) { sampleErr -= mPeriod; nsecs_t sampleErr = (sample - mPhase) % period; if (sampleErr > period / 2) { sampleErr -= period; } sqErrSum += sampleErr * sampleErr; numErrSamples++; Loading Loading @@ -510,8 +505,8 @@ void DispSync::dump(String8& result) const { Mutex::Autolock lock(mMutex); result.appendFormat("present fences are %s\n", kIgnorePresentFences ? "ignored" : "used"); result.appendFormat("mPeriod: %" PRId64 " ns (%.3f fps)\n", mPeriod, 1000000000.0 / mPeriod); result.appendFormat("mPeriod: %" PRId64 " ns (%.3f fps; skipCount=%d)\n", mPeriod, 1000000000.0 / mPeriod, mRefreshSkipCount); result.appendFormat("mPhase: %" PRId64 " ns\n", mPhase); result.appendFormat("mError: %" PRId64 " ns (sqrt=%.1f)\n", mError, sqrt(mError)); Loading services/surfaceflinger/DispSync.h +8 −2 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ public: DispSync(); ~DispSync(); // reset clears the resync samples and error value. void reset(); // addPresentFence adds a fence for use in validating the current vsync Loading Loading @@ -100,8 +101,11 @@ public: // turned on. It should NOT be used after that. void setPeriod(nsecs_t period); // Setting the low power mode reduces the frame rate to half of the default void setLowPowerMode(bool enabled); // setRefreshSkipCount specifies an additional number of refresh // cycles to skip. For example, on a 60Hz display, a skip count of 1 // will result in events happening at 30Hz. Default is zero. The idea // is to sacrifice smoothness for battery life. void setRefreshSkipCount(int count); // addEventListener registers a callback to be called repeatedly at the // given phase offset from the hardware vsync events. The callback is Loading Loading @@ -161,6 +165,8 @@ private: nsecs_t mPresentTimes[NUM_PRESENT_SAMPLES]; size_t mPresentSampleOffset; int mRefreshSkipCount; // mThread is the thread from which all the callbacks are called. sp<DispSyncThread> mThread; Loading services/surfaceflinger/SurfaceFlinger.cpp +2 −5 Original line number Diff line number Diff line Loading @@ -2682,11 +2682,8 @@ status_t SurfaceFlinger::onTransact( // This is an experimental interface // Needs to be shifted to proper binder interface when we productize case 1016: { mPrimaryDispSync.setLowPowerMode(true); return NO_ERROR; } case 1017: { mPrimaryDispSync.setLowPowerMode(false); n = data.readInt32(); mPrimaryDispSync.setRefreshSkipCount(n); return NO_ERROR; } } Loading Loading
services/surfaceflinger/DispSync.cpp +22 −27 Original line number Diff line number Diff line Loading @@ -53,10 +53,7 @@ class DispSyncThread: public Thread { public: DispSyncThread(): mLowPowerMode(false), mStop(false), mLastVsyncSent(false), mLastBufferFull(false), mPeriod(0), mPhase(0), mWakeupLatency(0) { Loading Loading @@ -140,19 +137,8 @@ public: } if (callbackInvocations.size() > 0) { if (mLowPowerMode) { if (!mLastVsyncSent || !mLastBufferFull) { fireCallbackInvocations(callbackInvocations); mLastVsyncSent = true; } else mLastVsyncSent = false; } else { fireCallbackInvocations(callbackInvocations); } mLastBufferFull = true; } else { mLastBufferFull = false; } } return false; Loading Loading @@ -205,7 +191,6 @@ public: return !mEventListeners.empty(); } bool mLowPowerMode; private: struct EventListener { Loading Loading @@ -278,8 +263,6 @@ private: } bool mStop; bool mLastVsyncSent; bool mLastBufferFull; nsecs_t mPeriod; nsecs_t mPhase; Loading @@ -304,8 +287,10 @@ private: bool mParity; }; DispSync::DispSync() { mThread = new DispSyncThread(); DispSync::DispSync() : mRefreshSkipCount(0), mThread(new DispSyncThread()) { mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); reset(); Loading Loading @@ -404,8 +389,11 @@ status_t DispSync::addEventListener(nsecs_t phase, return mThread->addEventListener(phase, callback); } void DispSync::setLowPowerMode(bool enabled) { mThread->mLowPowerMode = enabled; void DispSync::setRefreshSkipCount(int count) { Mutex::Autolock lock(mMutex); ALOGD("setRefreshSkipCount(%d)", count); mRefreshSkipCount = count; updateModelLocked(); } status_t DispSync::removeEventListener(const sp<Callback>& callback) { Loading Loading @@ -456,6 +444,9 @@ void DispSync::updateModelLocked() { ATRACE_INT64("DispSync:Phase", mPhase); } // Artificially inflate the period if requested. mPeriod += mPeriod * mRefreshSkipCount; mThread->updateModel(mPeriod, mPhase); } } Loading @@ -465,15 +456,19 @@ void DispSync::updateErrorLocked() { return; } // Need to compare present fences against the un-adjusted refresh period, // since they might arrive between two events. nsecs_t period = mPeriod / (1 + mRefreshSkipCount); int numErrSamples = 0; nsecs_t sqErrSum = 0; for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) { nsecs_t sample = mPresentTimes[i]; if (sample > mPhase) { nsecs_t sampleErr = (sample - mPhase) % mPeriod; if (sampleErr > mPeriod / 2) { sampleErr -= mPeriod; nsecs_t sampleErr = (sample - mPhase) % period; if (sampleErr > period / 2) { sampleErr -= period; } sqErrSum += sampleErr * sampleErr; numErrSamples++; Loading Loading @@ -510,8 +505,8 @@ void DispSync::dump(String8& result) const { Mutex::Autolock lock(mMutex); result.appendFormat("present fences are %s\n", kIgnorePresentFences ? "ignored" : "used"); result.appendFormat("mPeriod: %" PRId64 " ns (%.3f fps)\n", mPeriod, 1000000000.0 / mPeriod); result.appendFormat("mPeriod: %" PRId64 " ns (%.3f fps; skipCount=%d)\n", mPeriod, 1000000000.0 / mPeriod, mRefreshSkipCount); result.appendFormat("mPhase: %" PRId64 " ns\n", mPhase); result.appendFormat("mError: %" PRId64 " ns (sqrt=%.1f)\n", mError, sqrt(mError)); Loading
services/surfaceflinger/DispSync.h +8 −2 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ public: DispSync(); ~DispSync(); // reset clears the resync samples and error value. void reset(); // addPresentFence adds a fence for use in validating the current vsync Loading Loading @@ -100,8 +101,11 @@ public: // turned on. It should NOT be used after that. void setPeriod(nsecs_t period); // Setting the low power mode reduces the frame rate to half of the default void setLowPowerMode(bool enabled); // setRefreshSkipCount specifies an additional number of refresh // cycles to skip. For example, on a 60Hz display, a skip count of 1 // will result in events happening at 30Hz. Default is zero. The idea // is to sacrifice smoothness for battery life. void setRefreshSkipCount(int count); // addEventListener registers a callback to be called repeatedly at the // given phase offset from the hardware vsync events. The callback is Loading Loading @@ -161,6 +165,8 @@ private: nsecs_t mPresentTimes[NUM_PRESENT_SAMPLES]; size_t mPresentSampleOffset; int mRefreshSkipCount; // mThread is the thread from which all the callbacks are called. sp<DispSyncThread> mThread; Loading
services/surfaceflinger/SurfaceFlinger.cpp +2 −5 Original line number Diff line number Diff line Loading @@ -2682,11 +2682,8 @@ status_t SurfaceFlinger::onTransact( // This is an experimental interface // Needs to be shifted to proper binder interface when we productize case 1016: { mPrimaryDispSync.setLowPowerMode(true); return NO_ERROR; } case 1017: { mPrimaryDispSync.setLowPowerMode(false); n = data.readInt32(); mPrimaryDispSync.setRefreshSkipCount(n); return NO_ERROR; } } Loading