diff options
| -rw-r--r-- | libs/gui/ISurfaceComposer.cpp | 12 | ||||
| -rw-r--r-- | libs/gui/LayerState.cpp | 4 | ||||
| -rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 162 | ||||
| -rw-r--r-- | libs/gui/include/gui/ISurfaceComposer.h | 4 | ||||
| -rw-r--r-- | libs/gui/include/gui/LayerState.h | 9 | ||||
| -rw-r--r-- | libs/gui/include/gui/SurfaceComposerClient.h | 10 | ||||
| -rw-r--r-- | libs/gui/tests/Surface_test.cpp | 3 | ||||
| -rw-r--r-- | libs/ui/GraphicBuffer.cpp | 7 | ||||
| -rw-r--r-- | libs/ui/include/ui/GraphicBuffer.h | 20 | ||||
| -rw-r--r-- | services/surfaceflinger/BufferStateLayerCache.cpp | 39 | ||||
| -rw-r--r-- | services/surfaceflinger/BufferStateLayerCache.h | 8 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 49 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 11 |
13 files changed, 218 insertions, 120 deletions
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 247dc8d9d2..bc63d315e0 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -68,7 +68,8 @@ public: const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, const InputWindowCommands& commands, - int64_t desiredPresentTime) { + int64_t desiredPresentTime, + const cached_buffer_t& uncacheBuffer) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -86,6 +87,8 @@ public: data.writeStrongBinder(applyToken); commands.write(data); data.writeInt64(desiredPresentTime); + data.writeStrongBinder(uncacheBuffer.token); + data.writeUint64(uncacheBuffer.cacheId); remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply); } @@ -970,8 +973,13 @@ status_t BnSurfaceComposer::onTransact( inputWindowCommands.read(data); int64_t desiredPresentTime = data.readInt64(); + + cached_buffer_t uncachedBuffer; + uncachedBuffer.token = data.readStrongBinder(); + uncachedBuffer.cacheId = data.readUint64(); + setTransactionState(state, displays, stateFlags, applyToken, inputWindowCommands, - desiredPresentTime); + desiredPresentTime, uncachedBuffer); return NO_ERROR; } case BOOT_FINISHED: { diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 84ba64494f..f6ca9e8f0b 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -95,7 +95,7 @@ status_t layer_state_t::write(Parcel& output) const } output.writeStrongBinder(cachedBuffer.token); - output.writeInt32(cachedBuffer.bufferId); + output.writeUint64(cachedBuffer.cacheId); output.writeParcelable(metadata); output.writeFloat(bgColorAlpha); @@ -173,7 +173,7 @@ status_t layer_state_t::read(const Parcel& input) } cachedBuffer.token = input.readStrongBinder(); - cachedBuffer.bufferId = input.readInt32(); + cachedBuffer.cacheId = input.readUint64(); input.readParcelable(&metadata); bgColorAlpha = input.readFloat(); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index b0e827536d..39cd62fa10 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -233,6 +233,8 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener // --------------------------------------------------------------------------- +void bufferCacheCallback(void* /*context*/, uint64_t graphicBufferId); + class BufferCache : public Singleton<BufferCache> { public: BufferCache() : token(new BBinder()) {} @@ -241,77 +243,57 @@ public: return IInterface::asBinder(TransactionCompletedListener::getIInstance()); } - int32_t getId(const sp<GraphicBuffer>& buffer) { + status_t getCacheId(const sp<GraphicBuffer>& buffer, uint64_t* cacheId) { std::lock_guard<std::mutex> lock(mMutex); - auto itr = mBuffers.find(buffer); + auto itr = mBuffers.find(buffer->getId()); if (itr == mBuffers.end()) { - return -1; + return BAD_VALUE; } - itr->second.counter = getCounter(); - return itr->second.id; + itr->second = getCounter(); + *cacheId = buffer->getId(); + return NO_ERROR; } - int32_t cache(const sp<GraphicBuffer>& buffer) { + uint64_t cache(const sp<GraphicBuffer>& buffer) { std::lock_guard<std::mutex> lock(mMutex); - int32_t bufferId = getNextAvailableId(); + if (mBuffers.size() >= BUFFER_CACHE_MAX_SIZE) { + evictLeastRecentlyUsedBuffer(); + } + + buffer->addDeathCallback(bufferCacheCallback, nullptr); - mBuffers[buffer].id = bufferId; - mBuffers[buffer].counter = getCounter(); - return bufferId; + mBuffers[buffer->getId()] = getCounter(); + return buffer->getId(); } -private: - int32_t evictDestroyedBuffer() REQUIRES(mMutex) { - auto itr = mBuffers.begin(); - while (itr != mBuffers.end()) { - auto& buffer = itr->first; - if (buffer == nullptr || buffer.promote() == nullptr) { - int32_t bufferId = itr->second.id; - mBuffers.erase(itr); - return bufferId; - } - itr++; - } - return -1; + void uncache(uint64_t cacheId) { + std::lock_guard<std::mutex> lock(mMutex); + uncacheLocked(cacheId); } - int32_t evictLeastRecentlyUsedBuffer() REQUIRES(mMutex) { - if (mBuffers.size() < 0) { - return -1; - } + void uncacheLocked(uint64_t cacheId) REQUIRES(mMutex) { + mBuffers.erase(cacheId); + SurfaceComposerClient::doUncacheBufferTransaction(cacheId); + } + +private: + void evictLeastRecentlyUsedBuffer() REQUIRES(mMutex) { auto itr = mBuffers.begin(); - uint64_t minCounter = itr->second.counter; + uint64_t minCounter = itr->second; auto minBuffer = itr; itr++; while (itr != mBuffers.end()) { - uint64_t counter = itr->second.counter; + uint64_t counter = itr->second; if (counter < minCounter) { minCounter = counter; minBuffer = itr; } itr++; } - int32_t minBufferId = minBuffer->second.id; - mBuffers.erase(minBuffer); - return minBufferId; - } - - int32_t getNextAvailableId() REQUIRES(mMutex) { - static int32_t id = 0; - if (id + 1 < BUFFER_CACHE_MAX_SIZE) { - return id++; - } - - // There are no more valid cache ids. To set additional buffers, evict existing buffers - // and reuse their cache ids. - int32_t bufferId = evictDestroyedBuffer(); - if (bufferId > 0) { - return bufferId; - } - return evictLeastRecentlyUsedBuffer(); + uncacheLocked(minBuffer->first); } uint64_t getCounter() REQUIRES(mMutex) { @@ -319,18 +301,8 @@ private: return counter++; } - struct Metadata { - // The cache id of a buffer that can be set to ISurfaceComposer. When ISurfaceComposer - // recieves this id, it can retrieve the buffer from its cache. Caching GraphicBuffers - // is important because sending them across processes is expensive. - int32_t id = 0; - // When a buffer is set, a counter is incremented and stored in the cache's metadata. - // When an buffer must be evicted, the entry with the lowest counter value is chosen. - uint64_t counter = 0; - }; - std::mutex mMutex; - std::map<wp<GraphicBuffer>, Metadata> mBuffers GUARDED_BY(mMutex); + std::map<uint64_t /*Cache id*/, uint64_t /*counter*/> mBuffers GUARDED_BY(mMutex); // Used by ISurfaceComposer to identify which process is sending the cached buffer. sp<IBinder> token; @@ -338,6 +310,11 @@ private: ANDROID_SINGLETON_STATIC_INSTANCE(BufferCache); +void bufferCacheCallback(void* /*context*/, uint64_t graphicBufferId) { + // GraphicBuffer id's are used as the cache ids. + BufferCache::getInstance().uncache(graphicBufferId); +} + // --------------------------------------------------------------------------- SurfaceComposerClient::Transaction::Transaction(const Transaction& other) @@ -385,6 +362,9 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr mInputWindowCommands.merge(other.mInputWindowCommands); other.mInputWindowCommands.clear(); + mContainsBuffer = other.mContainsBuffer; + other.mContainsBuffer = false; + return *this; } @@ -401,7 +381,50 @@ void SurfaceComposerClient::doDropReferenceTransaction(const sp<IBinder>& handle s.state.parentHandleForChild = nullptr; composerStates.add(s); - sf->setTransactionState(composerStates, displayStates, 0, nullptr, {}, -1); + sf->setTransactionState(composerStates, displayStates, 0, nullptr, {}, -1, {}); +} + +void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { + sp<ISurfaceComposer> sf(ComposerService::getComposerService()); + + cached_buffer_t uncacheBuffer; + uncacheBuffer.token = BufferCache::getInstance().getToken(); + uncacheBuffer.cacheId = cacheId; + + sf->setTransactionState({}, {}, 0, nullptr, {}, -1, uncacheBuffer); +} + +void SurfaceComposerClient::Transaction::cacheBuffers() { + if (!mContainsBuffer) { + return; + } + + size_t count = 0; + for (auto& [sc, cs] : mComposerStates) { + layer_state_t* s = getLayerState(sc); + if (!(s->what & layer_state_t::eBufferChanged)) { + continue; + } + + uint64_t cacheId = 0; + status_t ret = BufferCache::getInstance().getCacheId(s->buffer, &cacheId); + if (ret == NO_ERROR) { + s->what &= ~static_cast<uint32_t>(layer_state_t::eBufferChanged); + s->buffer = nullptr; + } else { + cacheId = BufferCache::getInstance().cache(s->buffer); + } + s->what |= layer_state_t::eCachedBufferChanged; + s->cachedBuffer.token = BufferCache::getInstance().getToken(); + s->cachedBuffer.cacheId = cacheId; + + // If we have more buffers than the size of the cache, we should stop caching so we don't + // evict other buffers in this transaction + count++; + if (count >= BUFFER_CACHE_MAX_SIZE) { + break; + } + } } status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { @@ -437,6 +460,8 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { } mListenerCallbacks.clear(); + cacheBuffers(); + Vector<ComposerState> composerStates; Vector<DisplayState> displayStates; uint32_t flags = 0; @@ -468,7 +493,8 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); sf->setTransactionState(composerStates, displayStates, flags, applyToken, mInputWindowCommands, - mDesiredPresentTime); + mDesiredPresentTime, + {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/); mInputWindowCommands.clear(); mStatus = NO_ERROR; return NO_ERROR; @@ -882,20 +908,12 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe mStatus = BAD_INDEX; return *this; } - - int32_t bufferId = BufferCache::getInstance().getId(buffer); - if (bufferId < 0) { - bufferId = BufferCache::getInstance().cache(buffer); - - s->what |= layer_state_t::eBufferChanged; - s->buffer = buffer; - } - - s->what |= layer_state_t::eCachedBufferChanged; - s->cachedBuffer.token = BufferCache::getInstance().getToken(); - s->cachedBuffer.bufferId = bufferId; + s->what |= layer_state_t::eBufferChanged; + s->buffer = buffer; registerSurfaceControlForCallback(sc); + + mContainsBuffer = true; return *this; } diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 8f54fee22f..0ef5b39641 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -40,6 +40,7 @@ namespace android { // ---------------------------------------------------------------------------- +struct cached_buffer_t; struct ComposerState; struct DisplayState; struct DisplayInfo; @@ -131,7 +132,8 @@ public: const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, const InputWindowCommands& inputWindowCommands, - int64_t desiredPresentTime) = 0; + int64_t desiredPresentTime, + const cached_buffer_t& uncacheBuffer) = 0; /* signal that we're done booting. * Requires ACCESS_SURFACE_FLINGER permission diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 35e795c30b..77bf8f1dc5 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -41,6 +41,11 @@ namespace android { class Parcel; class ISurfaceComposerClient; +struct cached_buffer_t { + sp<IBinder> token = nullptr; + uint64_t cacheId; +}; + /* * Used to communicate layer information between SurfaceFlinger and its clients. */ @@ -133,10 +138,6 @@ struct layer_state_t { float dtdy{0}; float dsdy{0}; }; - struct cached_buffer_t { - sp<IBinder> token = nullptr; - int32_t bufferId = -1; - }; sp<IBinder> surface; uint64_t what; float x; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 39d6d13682..593a5e7d81 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -165,6 +165,12 @@ public: static void doDropReferenceTransaction(const sp<IBinder>& handle, const sp<ISurfaceComposerClient>& client); + /** + * Uncaches a buffer in ISurfaceComposer. It must be uncached via a transaction so that it is + * in order with other transactions that use buffers. + */ + static void doUncacheBufferTransaction(uint64_t cacheId); + // Queries whether a given display is wide color display. static status_t isWideColorDisplay(const sp<IBinder>& display, bool* outIsWideColorDisplay); @@ -279,6 +285,9 @@ public: bool mAnimation = false; bool mEarlyWakeup = false; + // Indicates that the Transaction contains a buffer that should be cached + bool mContainsBuffer = false; + // mDesiredPresentTime is the time in nanoseconds that the client would like the transaction // to be presented. When it is not possible to present at exactly that time, it will be // presented after the time has passed. @@ -297,6 +306,7 @@ public: layer_state_t* getLayerState(const sp<SurfaceControl>& sc); DisplayState& getDisplayState(const sp<IBinder>& token); + void cacheBuffers(); void registerSurfaceControlForCallback(const sp<SurfaceControl>& sc); public: diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 06fe86c0cf..94b669dde4 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -560,7 +560,8 @@ public: const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/, const sp<IBinder>& /*applyToken*/, const InputWindowCommands& /*inputWindowCommands*/, - int64_t /*desiredPresentTime*/) override {} + int64_t /*desiredPresentTime*/, + const cached_buffer_t& /*cachedBuffer*/) override {} void bootFinished() override {} bool authenticateSurfaceTexture( diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index e1c325e319..40df260fda 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -133,6 +133,9 @@ GraphicBuffer::~GraphicBuffer() if (handle) { free_handle(); } + for (auto& [callback, context] : mDeathCallbacks) { + callback(context, mId); + } } void GraphicBuffer::free_handle() @@ -553,6 +556,10 @@ status_t GraphicBuffer::unflatten(void const*& buffer, size_t& size, int const*& return NO_ERROR; } +void GraphicBuffer::addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context) { + mDeathCallbacks.emplace_back(deathCallback, context); +} + #ifndef LIBUI_IN_VNDK status_t GraphicBuffer::flattenBufferHubBuffer(void*& buffer, size_t& size, int*& fds, size_t& count) const { diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h index cb4ee2a096..c137860aee 100644 --- a/libs/ui/include/ui/GraphicBuffer.h +++ b/libs/ui/include/ui/GraphicBuffer.h @@ -21,6 +21,8 @@ #include <sys/types.h> #include <string> +#include <utility> +#include <vector> #include <android/hardware_buffer.h> #include <ui/ANativeObjectBase.h> @@ -42,6 +44,8 @@ class BufferHubBuffer; class GraphicBufferMapper; +using GraphicBufferDeathCallback = std::function<void(void* /*context*/, uint64_t bufferId)>; + // =========================================================================== // GraphicBuffer // =========================================================================== @@ -219,6 +223,8 @@ public: return mBufferMapper.getMapperVersion(); } + void addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context); + #ifndef LIBUI_IN_VNDK // Returns whether this GraphicBuffer is backed by BufferHubBuffer. bool isBufferHubBuffer() const; @@ -280,6 +286,20 @@ private: // IGBP::setGenerationNumber), attempts to attach the buffer will fail. uint32_t mGenerationNumber; + // Send a callback when a GraphicBuffer dies. + // + // This is used for BufferStateLayer caching. GraphicBuffers are refcounted per process. When + // A GraphicBuffer doesn't have any more sp<> in a process, it is destroyed. This causes + // problems when trying to implicitcly cache across process boundaries. Ideally, both sides + // of the cache would hold onto wp<> references. When an app dropped its sp<>, the GraphicBuffer + // would be destroyed. Unfortunately, when SurfaceFlinger has only a wp<> reference to the + // GraphicBuffer, it immediately goes out of scope in the SurfaceFlinger process. SurfaceFlinger + // must hold onto a sp<> to the buffer. When the GraphicBuffer goes out of scope in the app's + // process, the client side cache will get this callback. It erases the buffer from its cache + // and informs SurfaceFlinger that it should drop its strong pointer reference to the buffer. + std::vector<std::pair<GraphicBufferDeathCallback, void* /*mDeathCallbackContext*/>> + mDeathCallbacks; + #ifndef LIBUI_IN_VNDK // Flatten this GraphicBuffer object if backed by BufferHubBuffer. status_t flattenBufferHubBuffer(void*& buffer, size_t& size, int*& fds, size_t& count) const; diff --git a/services/surfaceflinger/BufferStateLayerCache.cpp b/services/surfaceflinger/BufferStateLayerCache.cpp index cb02d16007..51ca45c53a 100644 --- a/services/surfaceflinger/BufferStateLayerCache.cpp +++ b/services/surfaceflinger/BufferStateLayerCache.cpp @@ -23,21 +23,14 @@ #include "BufferStateLayerCache.h" -#define VALID_CACHE_ID(id) ((id) >= 0 || (id) < (BUFFER_CACHE_MAX_SIZE)) - namespace android { ANDROID_SINGLETON_STATIC_INSTANCE(BufferStateLayerCache); BufferStateLayerCache::BufferStateLayerCache() : mDeathRecipient(new CacheDeathRecipient) {} -void BufferStateLayerCache::add(sp<IBinder> processToken, int32_t id, +void BufferStateLayerCache::add(const sp<IBinder>& processToken, uint64_t id, const sp<GraphicBuffer>& buffer) { - if (!VALID_CACHE_ID(id)) { - ALOGE("failed to cache buffer: invalid buffer id"); - return; - } - if (!processToken) { ALOGE("failed to cache buffer: invalid process token"); return; @@ -61,15 +54,33 @@ void BufferStateLayerCache::add(sp<IBinder> processToken, int32_t id, } auto& processBuffers = mBuffers[processToken]; + + if (processBuffers.size() > BUFFER_CACHE_MAX_SIZE) { + ALOGE("failed to cache buffer: cache is full"); + return; + } + processBuffers[id] = buffer; } -sp<GraphicBuffer> BufferStateLayerCache::get(sp<IBinder> processToken, int32_t id) { - if (!VALID_CACHE_ID(id)) { - ALOGE("failed to get buffer: invalid buffer id"); - return nullptr; +void BufferStateLayerCache::erase(const sp<IBinder>& processToken, uint64_t id) { + if (!processToken) { + ALOGE("failed to uncache buffer: invalid process token"); + return; + } + + std::lock_guard lock(mMutex); + + if (mBuffers.find(processToken) == mBuffers.end()) { + ALOGE("failed to uncache buffer: process token not found"); + return; } + auto& processBuffers = mBuffers[processToken]; + processBuffers.erase(id); +} + +sp<GraphicBuffer> BufferStateLayerCache::get(const sp<IBinder>& processToken, uint64_t id) { if (!processToken) { ALOGE("failed to cache buffer: invalid process token"); return nullptr; @@ -82,8 +93,8 @@ sp<GraphicBuffer> BufferStateLayerCache::get(sp<IBinder> processToken, int32_t i return nullptr; } - if (id >= itr->second.size()) { - ALOGE("failed to get buffer: id outside the bounds of the cache"); + if (itr->second.find(id) == itr->second.end()) { + ALOGE("failed to get buffer: buffer not found"); return nullptr; } diff --git a/services/surfaceflinger/BufferStateLayerCache.h b/services/surfaceflinger/BufferStateLayerCache.h index ede3feb1c8..415c09cf96 100644 --- a/services/surfaceflinger/BufferStateLayerCache.h +++ b/services/surfaceflinger/BufferStateLayerCache.h @@ -34,14 +34,16 @@ class BufferStateLayerCache : public Singleton<BufferStateLayerCache> { public: BufferStateLayerCache(); - void add(sp<IBinder> processToken, int32_t id, const sp<GraphicBuffer>& buffer); - sp<GraphicBuffer> get(sp<IBinder> processToken, int32_t id); + void add(const sp<IBinder>& processToken, uint64_t id, const sp<GraphicBuffer>& buffer); + void erase(const sp<IBinder>& processToken, uint64_t id); + + sp<GraphicBuffer> get(const sp<IBinder>& processToken, uint64_t id); void removeProcess(const wp<IBinder>& processToken); private: std::mutex mMutex; - std::map<wp<IBinder> /*caching process*/, std::array<sp<GraphicBuffer>, BUFFER_CACHE_MAX_SIZE>> + std::map<wp<IBinder> /*caching process*/, std::map<uint64_t /*Cache id*/, sp<GraphicBuffer>>> mBuffers GUARDED_BY(mMutex); class CacheDeathRecipient : public IBinder::DeathRecipient { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f6251b8a4b..ad4a76929e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3508,13 +3508,15 @@ bool SurfaceFlinger::flushTransactionQueues() { auto& [applyToken, transactionQueue] = *it; while (!transactionQueue.empty()) { - const auto& [states, displays, flags, desiredPresentTime, postTime, privileged] = - transactionQueue.front(); + const auto& + [states, displays, flags, desiredPresentTime, uncacheBuffer, postTime, + privileged] = transactionQueue.front(); if (!transactionIsReadyToBeApplied(desiredPresentTime, states)) { break; } applyTransactionState(states, displays, flags, mPendingInputWindowCommands, - desiredPresentTime, postTime, privileged, /*isMainThread*/ true); + desiredPresentTime, uncacheBuffer, postTime, privileged, + /*isMainThread*/ true); transactionQueue.pop(); } @@ -3571,7 +3573,8 @@ void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& states, const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, const InputWindowCommands& inputWindowCommands, - int64_t desiredPresentTime) { + int64_t desiredPresentTime, + const cached_buffer_t& uncacheBuffer) { ATRACE_CALL(); const int64_t postTime = systemTime(); @@ -3588,20 +3591,22 @@ void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& states, if (mTransactionQueues.find(applyToken) != mTransactionQueues.end() || !transactionIsReadyToBeApplied(desiredPresentTime, states)) { mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime, - postTime, privileged); + uncacheBuffer, postTime, privileged); setTransactionFlags(eTransactionNeeded); return; } applyTransactionState(states, displays, flags, inputWindowCommands, desiredPresentTime, - postTime, privileged); + uncacheBuffer, postTime, privileged); } void SurfaceFlinger::applyTransactionState(const Vector<ComposerState>& states, const Vector<DisplayState>& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, - const int64_t desiredPresentTime, const int64_t postTime, - bool privileged, bool isMainThread) { + const int64_t desiredPresentTime, + const cached_buffer_t& uncacheBuffer, + const int64_t postTime, bool privileged, + bool isMainThread) { uint32_t transactionFlags = 0; if (flags & eAnimation) { @@ -3636,6 +3641,10 @@ void SurfaceFlinger::applyTransactionState(const Vector<ComposerState>& states, transactionFlags |= addInputWindowCommands(inputWindowCommands); + if (uncacheBuffer.token) { + BufferStateLayerCache::getInstance().erase(uncacheBuffer.token, uncacheBuffer.cacheId); + } + // If a synchronous transaction is explicitly requested without any changes, force a transaction // anyway. This can be used as a flush mechanism for previous async transactions. // Empty animation transaction can be used to simulate back-pressure, so also force a @@ -3977,16 +3986,20 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState callbackHandles.emplace_back(new CallbackHandle(listener, callbackIds, s.surface)); } } - - if (what & layer_state_t::eBufferChanged) { - // Add the new buffer to the cache. This should always come before eCachedBufferChanged. - BufferStateLayerCache::getInstance().add(s.cachedBuffer.token, s.cachedBuffer.bufferId, + bool bufferChanged = what & layer_state_t::eBufferChanged; + bool cacheIdChanged = what & layer_state_t::eCachedBufferChanged; + sp<GraphicBuffer> buffer; + if (bufferChanged && cacheIdChanged) { + BufferStateLayerCache::getInstance().add(s.cachedBuffer.token, s.cachedBuffer.cacheId, s.buffer); - } - if (what & layer_state_t::eCachedBufferChanged) { - sp<GraphicBuffer> buffer = - BufferStateLayerCache::getInstance().get(s.cachedBuffer.token, - s.cachedBuffer.bufferId); + buffer = s.buffer; + } else if (cacheIdChanged) { + buffer = BufferStateLayerCache::getInstance().get(s.cachedBuffer.token, + s.cachedBuffer.cacheId); + } else if (bufferChanged) { + buffer = s.buffer; + } + if (buffer) { if (layer->setBuffer(buffer)) { flags |= eTraversalNeeded; layer->setPostTime(postTime); @@ -4230,7 +4243,7 @@ void SurfaceFlinger::onInitializeDisplays() { d.width = 0; d.height = 0; displays.add(d); - setTransactionState(state, displays, 0, nullptr, mPendingInputWindowCommands, -1); + setTransactionState(state, displays, 0, nullptr, mPendingInputWindowCommands, -1, {}); setPowerModeInternal(display, HWC_POWER_MODE_NORMAL); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 3bf7c213c0..26d0cd1412 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -431,7 +431,8 @@ private: const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken, const InputWindowCommands& inputWindowCommands, - int64_t desiredPresentTime) override; + int64_t desiredPresentTime, + const cached_buffer_t& uncacheBuffer) override; void bootFinished() override; bool authenticateSurfaceTexture( const sp<IGraphicBufferProducer>& bufferProducer) const override; @@ -577,7 +578,8 @@ private: void applyTransactionState(const Vector<ComposerState>& state, const Vector<DisplayState>& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, - const int64_t desiredPresentTime, const int64_t postTime, + const int64_t desiredPresentTime, + const cached_buffer_t& uncacheBuffer, const int64_t postTime, bool privileged, bool isMainThread = false) REQUIRES(mStateLock); bool flushTransactionQueues(); uint32_t getTransactionFlags(uint32_t flags); @@ -1059,11 +1061,13 @@ private: struct TransactionState { TransactionState(const Vector<ComposerState>& composerStates, const Vector<DisplayState>& displayStates, uint32_t transactionFlags, - int64_t desiredPresentTime, int64_t postTime, bool privileged) + int64_t desiredPresentTime, const cached_buffer_t& uncacheBuffer, + int64_t postTime, bool privileged) : states(composerStates), displays(displayStates), flags(transactionFlags), desiredPresentTime(desiredPresentTime), + buffer(uncacheBuffer), postTime(postTime), privileged(privileged) {} @@ -1071,6 +1075,7 @@ private: Vector<DisplayState> displays; uint32_t flags; const int64_t desiredPresentTime; + cached_buffer_t buffer; const int64_t postTime; bool privileged; }; |