diff options
| -rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 2307fbf56b..605c2e8848 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -430,6 +430,19 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel } status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const { + // If we write the Transaction to a parcel, we want to ensure the Buffers are cached + // before crossing the IPC boundary. Otherwise the receiving party will cache the buffers + // but is unlikely to use them again as they are owned by the other process. + // You may be asking yourself, is this const cast safe? Const cast is safe up + // until the point where you try and write to an object that was originally const at which + // point we enter undefined behavior. In this case we are safe though, because there are + // two possibilities: + // 1. The SurfaceComposerClient::Transaction was originally non-const. Safe. + // 2. It was originall const! In this case not only was it useless, but it by definition + // contains no composer states and so cacheBuffers will not perform any writes. + + const_cast<SurfaceComposerClient::Transaction*>(this)->cacheBuffers(); + parcel->writeUint32(mForceSynchronous); parcel->writeUint32(mTransactionNestCount); parcel->writeBool(mAnimation); @@ -507,7 +520,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr mInputWindowCommands.merge(other.mInputWindowCommands); - mContainsBuffer = other.mContainsBuffer; + mContainsBuffer |= other.mContainsBuffer; mEarlyWakeup = mEarlyWakeup || other.mEarlyWakeup; other.clear(); return *this; @@ -547,6 +560,11 @@ void SurfaceComposerClient::Transaction::cacheBuffers() { layer_state_t* s = getLayerState(handle); if (!(s->what & layer_state_t::eBufferChanged)) { continue; + } else if (s->what & layer_state_t::eCachedBufferChanged) { + // If eBufferChanged and eCachedBufferChanged are both trued then that means + // we already cached the buffer in a previous call to cacheBuffers, perhaps + // from writeToParcel on a Transaction that was merged in to this one. + continue; } // Don't try to cache a null buffer. Sending null buffers is cheap so we shouldn't waste |