From 2d5e230292c27d59f4c096bc742a0a19abf811c1 Mon Sep 17 00:00:00 2001 From: Jamie Gennis Date: Mon, 15 Oct 2012 18:24:43 -0700 Subject: [PATCH] SurfaceFlinger: add animation transactions This change adds a transaction flag for WindowManager to indicate that a transaction is being used to animate windows around the screen. SurfaceFlinger will not allow more than one of these transactions to be outstanding at a time to prevent the animation "frames" from being dropped. Bug: 7353840 Change-Id: I6488a6e0e1ed13d27356d2203c9dc766dc6b1759 --- include/gui/ISurfaceComposer.h | 1 + include/gui/SurfaceComposerClient.h | 5 +++- libs/gui/SurfaceComposerClient.cpp | 23 +++++++++++++++- services/surfaceflinger/SurfaceFlinger.cpp | 32 ++++++++++++++++++---- services/surfaceflinger/SurfaceFlinger.h | 3 +- 5 files changed, 55 insertions(+), 9 deletions(-) diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index 5d2d8d705..002aafc52 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 581ec8d47..21d16a947 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 3efd086bd..8586ed218 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -115,12 +115,15 @@ class Composer : public Singleton SortedVector mComposerStates; SortedVector mDisplayStates; uint32_t mForceSynchronous; + bool mAnimation; Composer() : Singleton(), - mForceSynchronous(0) + mForceSynchronous(0), + mAnimation(false) { } void closeGlobalTransactionImpl(bool synchronous); + void setAnimationTransactionImpl(); layer_state_t* getLayerStateLocked( const sp& 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& 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/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 492d1cf10..e21e2bfc3 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()), @@ -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 > mLayerPurgatory; - bool mTransationPending; + bool mTransactionPending; + bool mAnimTransactionPending; Vector > mLayersPendingRemoval; // protected by mStateLock (but we could use another lock)