diff options
-rw-r--r-- | include/gui/ISurfaceComposer.h | 1 | ||||
-rw-r--r-- | include/gui/SurfaceComposerClient.h | 5 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 23 | ||||
-rw-r--r-- | services/surfaceflinger/LayerScreenshot.cpp | 3 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 95 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 11 |
6 files changed, 96 insertions, 42 deletions
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index 5d2d8d7..002aafc 100644 --- a/include/gui/ISurfaceComposer.h +++ b/include/gui/ISurfaceComposer.h @@ -46,6 +46,7 @@ public: // flags for setTransactionState() enum { eSynchronous = 0x01, + eAnimation = 0x02, }; enum { diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h index 581ec8d..21d16a9 100644 --- a/include/gui/SurfaceComposerClient.h +++ b/include/gui/SurfaceComposerClient.h @@ -101,10 +101,13 @@ public: //! Open a composer transaction on all active SurfaceComposerClients. static void openGlobalTransaction(); - + //! Close a composer transaction on all active SurfaceComposerClients. static void closeGlobalTransaction(bool synchronous = false); + //! Flag the currently open transaction as an animation transaction. + static void setAnimationTransaction(); + status_t hide(SurfaceID id); status_t show(SurfaceID id); status_t setFlags(SurfaceID id, uint32_t flags, uint32_t mask); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 3efd086..8586ed2 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -115,12 +115,15 @@ class Composer : public Singleton<Composer> SortedVector<ComposerState> mComposerStates; SortedVector<DisplayState > mDisplayStates; uint32_t mForceSynchronous; + bool mAnimation; Composer() : Singleton<Composer>(), - mForceSynchronous(0) + mForceSynchronous(0), + mAnimation(false) { } void closeGlobalTransactionImpl(bool synchronous); + void setAnimationTransactionImpl(); layer_state_t* getLayerStateLocked( const sp<SurfaceComposerClient>& client, SurfaceID id); @@ -159,6 +162,10 @@ public: const Rect& layerStackRect, const Rect& displayRect); + static void setAnimationTransaction() { + Composer::getInstance().setAnimationTransactionImpl(); + } + static void closeGlobalTransaction(bool synchronous) { Composer::getInstance().closeGlobalTransactionImpl(synchronous); } @@ -194,12 +201,22 @@ void Composer::closeGlobalTransactionImpl(bool synchronous) { if (synchronous || mForceSynchronous) { flags |= ISurfaceComposer::eSynchronous; } + if (mAnimation) { + flags |= ISurfaceComposer::eAnimation; + } + mForceSynchronous = false; + mAnimation = false; } sm->setTransactionState(transaction, displayTransaction, flags); } +void Composer::setAnimationTransactionImpl() { + Mutex::Autolock _l(mLock); + mAnimation = true; +} + layer_state_t* Composer::getLayerStateLocked( const sp<SurfaceComposerClient>& client, SurfaceID id) { @@ -471,6 +488,10 @@ void SurfaceComposerClient::closeGlobalTransaction(bool synchronous) { Composer::closeGlobalTransaction(synchronous); } +void SurfaceComposerClient::setAnimationTransaction() { + Composer::setAnimationTransaction(); +} + // ---------------------------------------------------------------------------- status_t SurfaceComposerClient::setCrop(SurfaceID id, const Rect& crop) { diff --git a/services/surfaceflinger/LayerScreenshot.cpp b/services/surfaceflinger/LayerScreenshot.cpp index 1aa8c09..0fd744f 100644 --- a/services/surfaceflinger/LayerScreenshot.cpp +++ b/services/surfaceflinger/LayerScreenshot.cpp @@ -122,13 +122,14 @@ void LayerScreenshot::onDraw(const sp<const DisplayDevice>& hw, const Region& cl } else { glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glColor4f(alpha, alpha, alpha, alpha); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } LayerMesh mesh; computeGeometry(hw, &mesh); + glColor4f(alpha, alpha, alpha, alpha); + glDisable(GL_TEXTURE_EXTERNAL_OES); glEnable(GL_TEXTURE_2D); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 492d1cf..13b2c6b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -86,7 +86,8 @@ const String16 sDump("android.permission.DUMP"); SurfaceFlinger::SurfaceFlinger() : BnSurfaceComposer(), Thread(false), mTransactionFlags(0), - mTransationPending(false), + mTransactionPending(false), + mAnimTransactionPending(false), mLayersRemoved(false), mRepaintEverything(0), mBootTime(systemTime()), @@ -506,7 +507,7 @@ status_t SurfaceFlinger::readyToRun() // or when a texture is (asynchronously) destroyed, and for that // we need a valid surface, so it's convenient to use the main display // for that. - sp<const DisplayDevice> hw = getDefaultDisplayDevice(); + sp<const DisplayDevice> hw(getDefaultDisplayDevice()); // initialize OpenGL ES DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext); @@ -1125,7 +1126,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // Call makeCurrent() on the primary display so we can // be sure that nothing associated with this display // is current. - const sp<const DisplayDevice>& hw(getDefaultDisplayDevice()); + const sp<const DisplayDevice> hw(getDefaultDisplayDevice()); DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext); mDisplays.removeItem(draw.keyAt(i)); getHwComposer().disconnectDisplay(draw[i].type); @@ -1149,7 +1150,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) continue; } - const sp<DisplayDevice>& disp(getDisplayDevice(display)); + const sp<DisplayDevice> disp(getDisplayDevice(display)); if (disp != NULL) { if (state.layerStack != draw[i].layerStack) { disp->setLayerStack(state.layerStack); @@ -1264,7 +1265,8 @@ void SurfaceFlinger::commitTransaction() } mDrawingState = mCurrentState; - mTransationPending = false; + mTransactionPending = false; + mAnimTransactionPending = false; mTransactionCV.broadcast(); } @@ -1665,6 +1667,21 @@ void SurfaceFlinger::setTransactionState( Mutex::Autolock _l(mStateLock); uint32_t transactionFlags = 0; + if (flags & eAnimation) { + // For window updates that are part of an animation we must wait for + // previous animation "frames" to be handled. + while (mAnimTransactionPending) { + status_t err = mTransactionCV.waitRelative(mStateLock, 500 * 1000); + if (CC_UNLIKELY(err != NO_ERROR)) { + // just in case something goes wrong in SF, return to the + // caller after a few hundred microseconds. + ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!"); + mAnimTransactionPending = false; + break; + } + } + } + size_t count = displays.size(); for (size_t i=0 ; i<count ; i++) { const DisplayState& s(displays[i]); @@ -1685,15 +1702,18 @@ void SurfaceFlinger::setTransactionState( // if this is a synchronous transaction, wait for it to take effect // before returning. if (flags & eSynchronous) { - mTransationPending = true; + mTransactionPending = true; + } + if (flags & eAnimation) { + mAnimTransactionPending = true; } - while (mTransationPending) { + while (mTransactionPending) { status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5)); if (CC_UNLIKELY(err != NO_ERROR)) { // just in case something goes wrong in SF, return to the // called after a few seconds. - ALOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!"); - mTransationPending = false; + ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!"); + mTransactionPending = false; break; } } @@ -2023,48 +2043,48 @@ void SurfaceFlinger::onScreenReleased(const sp<const DisplayDevice>& hw) { void SurfaceFlinger::unblank(const sp<IBinder>& display) { class MessageScreenAcquired : public MessageBase { - SurfaceFlinger* mFlinger; - const sp<DisplayDevice>& mHw; + SurfaceFlinger& mFlinger; + sp<IBinder> mDisplay; public: - MessageScreenAcquired(SurfaceFlinger* flinger, - const sp<DisplayDevice>& hw) : mFlinger(flinger), mHw(hw) { } + MessageScreenAcquired(SurfaceFlinger& flinger, + const sp<IBinder>& disp) : mFlinger(flinger), mDisplay(disp) { } virtual bool handler() { - mFlinger->onScreenAcquired(mHw); + const sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay)); + if (hw == NULL) { + ALOGE("Attempt to unblank null display %p", mDisplay.get()); + } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) { + ALOGW("Attempt to unblank virtual display"); + } else { + mFlinger.onScreenAcquired(hw); + } return true; } }; - const sp<DisplayDevice>& hw = getDisplayDevice(display); - if (hw == NULL) { - ALOGE("Attempt to unblank null display %p", display.get()); - } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) { - ALOGW("Attempt to unblank virtual display"); - } else { - sp<MessageBase> msg = new MessageScreenAcquired(this, hw); - postMessageSync(msg); - } + sp<MessageBase> msg = new MessageScreenAcquired(*this, display); + postMessageSync(msg); } void SurfaceFlinger::blank(const sp<IBinder>& display) { class MessageScreenReleased : public MessageBase { - SurfaceFlinger* mFlinger; - const sp<DisplayDevice>& mHw; + SurfaceFlinger& mFlinger; + sp<IBinder> mDisplay; public: - MessageScreenReleased(SurfaceFlinger* flinger, - const sp<DisplayDevice>& hw) : mFlinger(flinger), mHw(hw) { } + MessageScreenReleased(SurfaceFlinger& flinger, + const sp<IBinder>& disp) : mFlinger(flinger), mDisplay(disp) { } virtual bool handler() { - mFlinger->onScreenReleased(mHw); + const sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay)); + if (hw == NULL) { + ALOGE("Attempt to blank null display %p", mDisplay.get()); + } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) { + ALOGW("Attempt to blank virtual display"); + } else { + mFlinger.onScreenReleased(hw); + } return true; } }; - const sp<DisplayDevice>& hw = getDisplayDevice(display); - if (hw == NULL) { - ALOGE("Attempt to blank null display %p", display.get()); - } else if (hw->getDisplayType() >= DisplayDevice::NUM_DISPLAY_TYPES) { - ALOGW("Attempt to blank virtual display"); - } else { - sp<MessageBase> msg = new MessageScreenReleased(this, hw); - postMessageSync(msg); - } + sp<MessageBase> msg = new MessageScreenReleased(*this, display); + postMessageSync(msg); } // --------------------------------------------------------------------------- @@ -2339,6 +2359,7 @@ void SurfaceFlinger::dumpAllLocked( const Vector< sp<LayerBase> >& SurfaceFlinger::getLayerSortedByZForHwcDisplay(int disp) { + // Note: mStateLock is held here return getDisplayDevice( getBuiltInDisplay(disp) )->getVisibleLayersSortedByZ(); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 6d36719..de97167 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -327,10 +327,13 @@ private: // called when starting, or restarting after system_server death void initializeDisplays(); + // NOTE: can only be called from the main thread or with mStateLock held sp<const DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) const { return mDisplays.valueFor(dpy); } - const sp<DisplayDevice>& getDisplayDevice(const wp<IBinder>& dpy) { + + // NOTE: can only be called from the main thread or with mStateLock held + sp<DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) { return mDisplays.valueFor(dpy); } @@ -398,7 +401,8 @@ private: volatile int32_t mTransactionFlags; Condition mTransactionCV; SortedVector<sp<LayerBase> > mLayerPurgatory; - bool mTransationPending; + bool mTransactionPending; + bool mAnimTransactionPending; Vector<sp<LayerBase> > mLayersPendingRemoval; // protected by mStateLock (but we could use another lock) @@ -424,6 +428,9 @@ private: State mDrawingState; bool mVisibleRegionsDirty; bool mHwWorkListDirty; + + // this may only be written from the main thread with mStateLock held + // it may be read from other threads with mStateLock held DefaultKeyedVector< wp<IBinder>, sp<DisplayDevice> > mDisplays; // don't use a lock for these, we don't care |