summaryrefslogtreecommitdiff
path: root/libs/gui/SurfaceComposerClient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/gui/SurfaceComposerClient.cpp')
-rw-r--r--libs/gui/SurfaceComposerClient.cpp90
1 files changed, 71 insertions, 19 deletions
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index aca59b6d3b..2713be060a 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -214,12 +214,6 @@ void TransactionCompletedListener::setReleaseBufferCallback(const ReleaseCallbac
mReleaseBufferCallbacks[callbackId] = listener;
}
-void TransactionCompletedListener::removeReleaseBufferCallback(
- const ReleaseCallbackId& callbackId) {
- std::scoped_lock<std::mutex> lock(mMutex);
- mReleaseBufferCallbacks.erase(callbackId);
-}
-
void TransactionCompletedListener::addSurfaceStatsListener(void* context, void* cookie,
sp<SurfaceControl> surfaceControl, SurfaceStatsCallback listener) {
std::scoped_lock<std::recursive_mutex> lock(mSurfaceStatsListenerMutex);
@@ -343,7 +337,6 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener
surfaceStats.previousReleaseFence
? surfaceStats.previousReleaseFence
: Fence::NO_FENCE,
- surfaceStats.transformHint,
surfaceStats.currentMaxAcquiredBufferCount);
}
}
@@ -389,7 +382,7 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener
}
void TransactionCompletedListener::onReleaseBuffer(ReleaseCallbackId callbackId,
- sp<Fence> releaseFence, uint32_t transformHint,
+ sp<Fence> releaseFence,
uint32_t currentMaxAcquiredBufferCount) {
ReleaseBufferCallback callback;
{
@@ -401,7 +394,11 @@ void TransactionCompletedListener::onReleaseBuffer(ReleaseCallbackId callbackId,
callbackId.to_string().c_str());
return;
}
- callback(callbackId, releaseFence, transformHint, currentMaxAcquiredBufferCount);
+ std::optional<uint32_t> optionalMaxAcquiredBufferCount =
+ currentMaxAcquiredBufferCount == UINT_MAX
+ ? std::nullopt
+ : std::make_optional<uint32_t>(currentMaxAcquiredBufferCount);
+ callback(callbackId, releaseFence, optionalMaxAcquiredBufferCount);
}
ReleaseBufferCallback TransactionCompletedListener::popReleaseBufferCallbackLocked(
@@ -712,11 +709,34 @@ status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const
return NO_ERROR;
}
+void SurfaceComposerClient::Transaction::releaseBufferIfOverwriting(const layer_state_t& state) {
+ if (!(state.what & layer_state_t::eBufferChanged)) {
+ return;
+ }
+
+ auto listener = state.bufferData.releaseBufferListener;
+ sp<Fence> fence =
+ state.bufferData.acquireFence ? state.bufferData.acquireFence : Fence::NO_FENCE;
+ if (state.bufferData.releaseBufferEndpoint ==
+ IInterface::asBinder(TransactionCompletedListener::getIInstance())) {
+ // if the callback is in process, run on a different thread to avoid any lock contigency
+ // issues in the client.
+ SurfaceComposerClient::getDefault()
+ ->mReleaseCallbackThread.addReleaseCallback(state.bufferData.releaseCallbackId,
+ fence);
+ } else {
+ listener->onReleaseBuffer(state.bufferData.releaseCallbackId, fence, UINT_MAX);
+ }
+}
+
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) {
for (auto const& [handle, composerState] : other.mComposerStates) {
if (mComposerStates.count(handle) == 0) {
mComposerStates[handle] = composerState;
} else {
+ if (composerState.state.what & layer_state_t::eBufferChanged) {
+ releaseBufferIfOverwriting(mComposerStates[handle].state);
+ }
mComposerStates[handle].state.merge(composerState.state);
}
}
@@ -1296,7 +1316,9 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe
mStatus = BAD_INDEX;
return *this;
}
- removeReleaseBufferCallback(s);
+
+ releaseBufferIfOverwriting(*s);
+
BufferData bufferData;
bufferData.buffer = buffer;
if (frameNumber) {
@@ -1321,15 +1343,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe
return *this;
}
-void SurfaceComposerClient::Transaction::removeReleaseBufferCallback(layer_state_t* s) {
- if (!(s->what & layer_state_t::eBufferChanged)) {
- return;
- }
-
- auto listener = TransactionCompletedListener::getInstance();
- listener->removeReleaseBufferCallback(s->bufferData.releaseCallbackId);
-}
-
void SurfaceComposerClient::Transaction::setReleaseBufferCallback(BufferData* bufferData,
const ReleaseCallbackId& id,
ReleaseBufferCallback callback) {
@@ -2210,4 +2223,43 @@ status_t ScreenshotClient::captureLayers(const LayerCaptureArgs& captureArgs,
return s->captureLayers(captureArgs, captureListener);
}
+// ---------------------------------------------------------------------------------
+
+void ReleaseCallbackThread::addReleaseCallback(const ReleaseCallbackId callbackId,
+ sp<Fence> releaseFence) {
+ std::scoped_lock<std::mutex> lock(mMutex);
+ if (!mStarted) {
+ mThread = std::thread(&ReleaseCallbackThread::threadMain, this);
+ mStarted = true;
+ }
+
+ mCallbackInfos.emplace(callbackId, std::move(releaseFence));
+ mReleaseCallbackPending.notify_one();
+}
+
+void ReleaseCallbackThread::threadMain() {
+ const auto listener = TransactionCompletedListener::getInstance();
+ std::queue<std::tuple<const ReleaseCallbackId, const sp<Fence>>> callbackInfos;
+ while (true) {
+ {
+ std::unique_lock<std::mutex> lock(mMutex);
+ callbackInfos = std::move(mCallbackInfos);
+ mCallbackInfos = {};
+ }
+
+ while (!callbackInfos.empty()) {
+ auto [callbackId, releaseFence] = callbackInfos.front();
+ listener->onReleaseBuffer(callbackId, std::move(releaseFence), UINT_MAX);
+ callbackInfos.pop();
+ }
+
+ {
+ std::unique_lock<std::mutex> lock(mMutex);
+ if (mCallbackInfos.size() == 0) {
+ mReleaseCallbackPending.wait(lock);
+ }
+ }
+ }
+}
+
} // namespace android