diff options
author | Mathias Agopian <mathias@google.com> | 2012-04-10 21:04:02 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2012-04-11 15:31:40 -0700 |
commit | 22ffb117b0c2a906bd04aef9738a52223cdd1dce (patch) | |
tree | 5d5b8915428be715ec6db9ace523f78668f4f50e /services | |
parent | b60314a12f3336b27d73920805ab07cbc498d857 (diff) | |
download | frameworks_native-22ffb117b0c2a906bd04aef9738a52223cdd1dce.zip frameworks_native-22ffb117b0c2a906bd04aef9738a52223cdd1dce.tar.gz frameworks_native-22ffb117b0c2a906bd04aef9738a52223cdd1dce.tar.bz2 |
make sure to disable VSYNC while screen is off
Change-Id: If1894c43b0a39a2851e1280a35ae77bccd6d9abd
Diffstat (limited to 'services')
-rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.cpp | 3 | ||||
-rw-r--r-- | services/surfaceflinger/EventThread.cpp | 56 | ||||
-rw-r--r-- | services/surfaceflinger/EventThread.h | 12 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 8 |
4 files changed, 57 insertions, 22 deletions
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 6ae03c9..b87e191 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -205,6 +205,9 @@ status_t HWComposer::commit() const { status_t HWComposer::release() const { if (mHwc) { + if (mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) { + mHwc->methods->eventControl(mHwc, HWC_EVENT_VSYNC, 0); + } int err = mHwc->set(mHwc, NULL, NULL, NULL); return (status_t)err; } diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index 5813eef..d86c280 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -41,6 +41,7 @@ EventThread::EventThread(const sp<SurfaceFlinger>& flinger) mHw(flinger->graphicPlane(0).editDisplayHardware()), mLastVSyncTimestamp(0), mVSyncTimestamp(0), + mUseSoftwareVSync(false), mDeliveredEvents(0), mDebugVsyncEnabled(false) { @@ -55,16 +56,6 @@ sp<EventThread::Connection> EventThread::createEventConnection() const { return new Connection(const_cast<EventThread*>(this)); } -nsecs_t EventThread::getLastVSyncTimestamp() const { - Mutex::Autolock _l(mLock); - return mLastVSyncTimestamp; -} - -nsecs_t EventThread::getVSyncPeriod() const { - return mHw.getRefreshPeriod(); - -} - status_t EventThread::registerDisplayEventConnection( const sp<EventThread::Connection>& connection) { Mutex::Autolock _l(mLock); @@ -108,6 +99,24 @@ void EventThread::requestNextVsync( } } +void EventThread::onScreenReleased() { + Mutex::Autolock _l(mLock); + // wait for an eventual pending vsync to be serviced + if (!mUseSoftwareVSync) { + while (mVSyncTimestamp) { + mCondition.wait(mLock); + } + } + // disable reliance on h/w vsync + mUseSoftwareVSync = true; +} + +void EventThread::onScreenAcquired() { + Mutex::Autolock _l(mLock); + mUseSoftwareVSync = false; +} + + void EventThread::onVSyncReceived(int, nsecs_t timestamp) { Mutex::Autolock _l(mLock); mVSyncTimestamp = timestamp; @@ -121,7 +130,6 @@ bool EventThread::threadLoop() { Vector< wp<EventThread::Connection> > displayEventConnections; do { - Mutex::Autolock _l(mLock); do { // latch VSYNC event if any @@ -145,7 +153,7 @@ bool EventThread::threadLoop() { if (!waitForNextVsync) { // we received a VSYNC but we have no clients // don't report it, and disable VSYNC events - disableVSync(); + disableVSyncLocked(); } else { // report VSYNC event break; @@ -157,12 +165,21 @@ bool EventThread::threadLoop() { // disable VSYNC events then. if (waitForNextVsync) { // enable - enableVSync(); + enableVSyncLocked(); } } // wait for something to happen - mCondition.wait(mLock); + if (mUseSoftwareVSync == true) { + // h/w vsync cannot be used (screen is off), so we use + // a timeout instead. it doesn't matter how imprecise this + // is, we just need to make sure to serve the clients + if (mCondition.waitRelative(mLock, ms2ns(16)) == TIMED_OUT) { + mVSyncTimestamp = systemTime(SYSTEM_TIME_MONOTONIC); + } + } else { + mCondition.wait(mLock); + } } while(true); // process vsync event @@ -233,12 +250,15 @@ bool EventThread::threadLoop() { return true; } -void EventThread::enableVSync() { - mHw.getHwComposer().eventControl(HWComposer::EVENT_VSYNC, true); +void EventThread::enableVSyncLocked() { + if (!mUseSoftwareVSync) { + // never enable h/w VSYNC when screen is off + mHw.getHwComposer().eventControl(HWComposer::EVENT_VSYNC, true); + } mDebugVsyncEnabled = true; } -void EventThread::disableVSync() { +void EventThread::disableVSyncLocked() { mHw.getHwComposer().eventControl(HWComposer::EVENT_VSYNC, false); mDebugVsyncEnabled = false; } @@ -252,6 +272,8 @@ void EventThread::dump(String8& result, char* buffer, size_t SIZE) const { Mutex::Autolock _l(mLock); result.appendFormat("VSYNC state: %s\n", mDebugVsyncEnabled?"enabled":"disabled"); + result.appendFormat(" soft-vsync: %s\n", + mUseSoftwareVSync?"enabled":"disabled"); result.appendFormat(" numListeners=%u,\n events-delivered: %u\n", mDisplayEventConnections.size(), mDeliveredEvents); for (size_t i=0 ; i<mDisplayEventConnections.size() ; i++) { diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h index 2e237dd..b42cab6 100644 --- a/services/surfaceflinger/EventThread.h +++ b/services/surfaceflinger/EventThread.h @@ -72,8 +72,11 @@ public: void setVsyncRate(uint32_t count, const sp<Connection>& connection); void requestNextVsync(const sp<Connection>& connection); - nsecs_t getLastVSyncTimestamp() const; - nsecs_t getVSyncPeriod() const; + // called before the screen is turned off from main thread + void onScreenReleased(); + + // called after the screen is turned on from main thread + void onScreenAcquired(); void dump(String8& result, char* buffer, size_t SIZE) const; @@ -84,8 +87,8 @@ private: virtual void onVSyncReceived(int, nsecs_t timestamp); void removeDisplayEventConnection(const wp<Connection>& connection); - void enableVSync(); - void disableVSync(); + void enableVSyncLocked(); + void disableVSyncLocked(); // constants sp<SurfaceFlinger> mFlinger; @@ -98,6 +101,7 @@ private: SortedVector< wp<Connection> > mDisplayEventConnections; nsecs_t mLastVSyncTimestamp; nsecs_t mVSyncTimestamp; + bool mUseSoftwareVSync; // main thread only size_t mDeliveredEvents; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f891b29..ce6c4a0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1467,16 +1467,18 @@ uint32_t SurfaceFlinger::setClientStateLocked( void SurfaceFlinger::onScreenAcquired() { const DisplayHardware& hw(graphicPlane(0).displayHardware()); hw.acquireScreen(); + mEventThread->onScreenAcquired(); // this is a temporary work-around, eventually this should be called // by the power-manager SurfaceFlinger::turnElectronBeamOn(mElectronBeamAnimationMode); mDirtyRegion.set(hw.bounds()); - // from this point on, SF will priocess updates again + // from this point on, SF will process updates again } void SurfaceFlinger::onScreenReleased() { const DisplayHardware& hw(graphicPlane(0).displayHardware()); if (hw.isScreenAcquired()) { + mEventThread->onScreenReleased(); mDirtyRegion.set(hw.bounds()); hw.releaseScreen(); // from this point on, SF will stop drawing @@ -1883,6 +1885,8 @@ status_t SurfaceFlinger::renderScreenToTexture(DisplayID dpy, status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy, GLuint* textureName, GLfloat* uOut, GLfloat* vOut) { + ATRACE_CALL(); + if (!GLExtensions::getInstance().haveFramebufferObject()) return INVALID_OPERATION; @@ -2263,6 +2267,8 @@ status_t SurfaceFlinger::electronBeamOnAnimationImplLocked() status_t SurfaceFlinger::turnElectronBeamOffImplLocked(int32_t mode) { + ATRACE_CALL(); + DisplayHardware& hw(graphicPlane(0).editDisplayHardware()); if (!hw.canDraw()) { // we're already off |