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