OSDN Git Service

Allow global transactions to nest.
authorJeff Brown <jeffbrown@google.com>
Fri, 31 Aug 2012 09:18:38 +0000 (02:18 -0700)
committerJeff Brown <jeffbrown@google.com>
Fri, 2 Nov 2012 21:02:52 +0000 (14:02 -0700)
This change fixes a number of small glitches that can occur when
multiple components in the same process are updating surfaces.
One would expect that updates to disjoint sets of surfaces would
not collide but this is not the case.  The first component to
close the global transaction causes all pending updates to
be applied, including those that another component might not
have finished setting up if it also had an open transaction
at the same time.

Change-Id: I99345958581abbe0e1e325a5bcba37e8941a313a

libs/gui/SurfaceComposerClient.cpp

index 80dd6ee..746057b 100644 (file)
@@ -115,13 +115,15 @@ class Composer : public Singleton<Composer>
     SortedVector<ComposerState> mComposerStates;
     SortedVector<DisplayState > mDisplayStates;
     uint32_t                    mForceSynchronous;
+    uint32_t                    mTransactionNestCount;
     bool                        mAnimation;
 
     Composer() : Singleton<Composer>(),
-        mForceSynchronous(0),
+        mForceSynchronous(0), mTransactionNestCount(0),
         mAnimation(false)
     { }
 
+    void openGlobalTransactionImpl();
     void closeGlobalTransactionImpl(bool synchronous);
     void setAnimationTransactionImpl();
 
@@ -166,6 +168,10 @@ public:
         Composer::getInstance().setAnimationTransactionImpl();
     }
 
+    static void openGlobalTransaction() {
+        Composer::getInstance().openGlobalTransactionImpl();
+    }
+
     static void closeGlobalTransaction(bool synchronous) {
         Composer::getInstance().closeGlobalTransactionImpl(synchronous);
     }
@@ -184,6 +190,13 @@ sp<IBinder> Composer::getBuiltInDisplay(int32_t id) {
     return ComposerService::getComposerService()->getBuiltInDisplay(id);
 }
 
+void Composer::openGlobalTransactionImpl() {
+    { // scope for the lock
+        Mutex::Autolock _l(mLock);
+        mTransactionNestCount += 1;
+    }
+}
+
 void Composer::closeGlobalTransactionImpl(bool synchronous) {
     sp<ISurfaceComposer> sm(ComposerService::getComposerService());
 
@@ -193,13 +206,21 @@ void Composer::closeGlobalTransactionImpl(bool synchronous) {
 
     { // scope for the lock
         Mutex::Autolock _l(mLock);
+        mForceSynchronous |= synchronous;
+        if (!mTransactionNestCount) {
+            ALOGW("At least one call to closeGlobalTransaction() was not matched by a prior "
+                    "call to openGlobalTransaction().");
+        } else if (--mTransactionNestCount) {
+            return;
+        }
+
         transaction = mComposerStates;
         mComposerStates.clear();
 
         displayTransaction = mDisplayStates;
         mDisplayStates.clear();
 
-        if (synchronous || mForceSynchronous) {
+        if (mForceSynchronous) {
             flags |= ISurfaceComposer::eSynchronous;
         }
         if (mAnimation) {
@@ -483,7 +504,7 @@ inline Composer& SurfaceComposerClient::getComposer() {
 // ----------------------------------------------------------------------------
 
 void SurfaceComposerClient::openGlobalTransaction() {
-    // Currently a no-op
+    Composer::openGlobalTransaction();
 }
 
 void SurfaceComposerClient::closeGlobalTransaction(bool synchronous) {