From 078d7366d28232ea0ef7d614f9526ab33de49b9b Mon Sep 17 00:00:00 2001 From: Patrick Williams Date: Tue, 27 Aug 2024 10:20:39 -0500 Subject: Block on BufferReleaseChannel when out of buffers Bug: 294133380 Flag: com.android.graphics.libgui.flags.buffer_release_channel Test: BLASTBufferQueueTest Change-Id: I4ffec81ffb9c26546cc50176f3c44ffe6eb90b75 --- libs/gui/BufferQueueConsumer.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'libs/gui/BufferQueueConsumer.cpp') diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp index 69d25be006..d0607bfab8 100644 --- a/libs/gui/BufferQueueConsumer.cpp +++ b/libs/gui/BufferQueueConsumer.cpp @@ -297,7 +297,11 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, // We might have freed a slot while dropping old buffers, or the producer // may be blocked waiting for the number of buffers in the queue to // decrease. +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL) + mCore->notifyBufferReleased(); +#else mCore->mDequeueCondition.notify_all(); +#endif ATRACE_INT(mCore->mConsumerName.c_str(), static_cast(mCore->mQueue.size())); #ifndef NO_BINDER @@ -350,7 +354,12 @@ status_t BufferQueueConsumer::detachBuffer(int slot) { mCore->mActiveBuffers.erase(slot); mCore->mFreeSlots.insert(slot); mCore->clearBufferSlotLocked(slot); +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL) + mCore->notifyBufferReleased(); +#else mCore->mDequeueCondition.notify_all(); +#endif + VALIDATE_CONSISTENCY(); } @@ -520,7 +529,12 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, } BQ_LOGV("releaseBuffer: releasing slot %d", slot); +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL) + mCore->notifyBufferReleased(); +#else mCore->mDequeueCondition.notify_all(); +#endif + VALIDATE_CONSISTENCY(); } // Autolock scope @@ -574,7 +588,11 @@ status_t BufferQueueConsumer::disconnect() { mCore->mQueue.clear(); mCore->freeAllBuffersLocked(); mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT; +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL) + mCore->notifyBufferReleased(); +#else mCore->mDequeueCondition.notify_all(); +#endif return NO_ERROR; } -- cgit v1.2.3-59-g8ed1b From 9084218d1255891135976b3cf9c3f0f3afb9143a Mon Sep 17 00:00:00 2001 From: Jim Shargo Date: Thu, 14 Nov 2024 00:49:27 +0000 Subject: bufferqueues: Move the gl fence wait from dequeue to releaseBuffer Bug: 339705065 Flag: com.android.graphics.libgui.flags.bq_gl_fence_cleanup Test: old tests Change-Id: I429118e2f23691c8858100343f40b8cc156133ea --- libs/gui/BufferQueueConsumer.cpp | 27 +++++++++++++++++++++++++++ libs/gui/BufferQueueCore.cpp | 4 +++- libs/gui/BufferQueueProducer.cpp | 12 ++++++++++++ libs/gui/include/gui/BufferSlot.h | 28 +++++++++++++++++----------- 4 files changed, 59 insertions(+), 12 deletions(-) (limited to 'libs/gui/BufferQueueConsumer.cpp') diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp index d0607bfab8..9855b5bca4 100644 --- a/libs/gui/BufferQueueConsumer.cpp +++ b/libs/gui/BufferQueueConsumer.cpp @@ -28,6 +28,10 @@ #define VALIDATE_CONSISTENCY() #endif +#define EGL_EGLEXT_PROTOTYPES +#include +#include + #include #include #include @@ -486,6 +490,27 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, return BAD_VALUE; } +#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP) + if (eglFence != EGL_NO_SYNC_KHR) { + // Most platforms will be using native fences, so it's unlikely that we'll ever have to + // process an eglFence. Ideally we can remove this code eventually. In the mean time, do our + // best to wait for it so the buffer stays valid, otherwise return an error to the caller. + // + // EGL_SYNC_FLUSH_COMMANDS_BIT_KHR so that we don't wait forever on a fence that hasn't + // shown up on the GPU yet. + EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, + 1000000000); + if (result == EGL_FALSE) { + BQ_LOGE("releaseBuffer: error %#x waiting for fence", eglGetError()); + return UNKNOWN_ERROR; + } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { + BQ_LOGE("releaseBuffer: timeout waiting for fence"); + return UNKNOWN_ERROR; + } + eglDestroySyncKHR(eglDisplay, eglFence); + } +#endif + sp listener; { // Autolock scope std::lock_guard lock(mCore->mMutex); @@ -507,8 +532,10 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, return BAD_VALUE; } +#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP) mSlots[slot].mEglDisplay = eglDisplay; mSlots[slot].mEglFence = eglFence; +#endif mSlots[slot].mFence = releaseFence; mSlots[slot].mBufferState.release(); diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp index d52cf700cd..5a093995b4 100644 --- a/libs/gui/BufferQueueCore.cpp +++ b/libs/gui/BufferQueueCore.cpp @@ -262,14 +262,16 @@ void BufferQueueCore::clearBufferSlotLocked(int slot) { mSlots[slot].mFrameNumber = 0; mSlots[slot].mAcquireCalled = false; mSlots[slot].mNeedsReallocation = true; + mSlots[slot].mFence = Fence::NO_FENCE; +#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP) // Destroy fence as BufferQueue now takes ownership if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) { eglDestroySyncKHR(mSlots[slot].mEglDisplay, mSlots[slot].mEglFence); mSlots[slot].mEglFence = EGL_NO_SYNC_KHR; } - mSlots[slot].mFence = Fence::NO_FENCE; mSlots[slot].mEglDisplay = EGL_NO_DISPLAY; +#endif if (mLastQueuedSlot == slot) { mLastQueuedSlot = INVALID_BUFFER_SLOT; diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 39209f9745..2e7cef0847 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -451,8 +451,10 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp* ou } status_t returnFlags = NO_ERROR; +#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP) EGLDisplay eglDisplay = EGL_NO_DISPLAY; EGLSyncKHR eglFence = EGL_NO_SYNC_KHR; +#endif bool attachedByConsumer = false; sp listener; @@ -569,8 +571,10 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp* ou mSlots[found].mAcquireCalled = false; mSlots[found].mGraphicBuffer = nullptr; mSlots[found].mRequestBufferCalled = false; +#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP) mSlots[found].mEglDisplay = EGL_NO_DISPLAY; mSlots[found].mEglFence = EGL_NO_SYNC_KHR; +#endif mSlots[found].mFence = Fence::NO_FENCE; mCore->mBufferAge = 0; mCore->mIsAllocating = true; @@ -595,14 +599,18 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp* ou found, buffer->width, buffer->height, buffer->format); } +#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP) eglDisplay = mSlots[found].mEglDisplay; eglFence = mSlots[found].mEglFence; +#endif // Don't return a fence in shared buffer mode, except for the first // frame. *outFence = (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == found) ? Fence::NO_FENCE : mSlots[found].mFence; +#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP) mSlots[found].mEglFence = EGL_NO_SYNC_KHR; +#endif mSlots[found].mFence = Fence::NO_FENCE; // If shared buffer mode has just been enabled, cache the slot of the @@ -691,6 +699,7 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp* ou returnFlags |= BUFFER_NEEDS_REALLOCATION; } +#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP) if (eglFence != EGL_NO_SYNC_KHR) { EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0, 1000000000); @@ -705,6 +714,7 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp* ou } eglDestroySyncKHR(eglDisplay, eglFence); } +#endif BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x", *outSlot, @@ -908,7 +918,9 @@ status_t BufferQueueProducer::attachBuffer(int* outSlot, mSlots[*outSlot].mGraphicBuffer = buffer; mSlots[*outSlot].mBufferState.attachProducer(); +#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP) mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR; +#endif mSlots[*outSlot].mFence = Fence::NO_FENCE; mSlots[*outSlot].mRequestBufferCalled = true; mSlots[*outSlot].mAcquireCalled = false; diff --git a/libs/gui/include/gui/BufferSlot.h b/libs/gui/include/gui/BufferSlot.h index 5b32710135..e83d2e33f2 100644 --- a/libs/gui/include/gui/BufferSlot.h +++ b/libs/gui/include/gui/BufferSlot.h @@ -174,26 +174,30 @@ struct BufferState { }; struct BufferSlot { - BufferSlot() - : mGraphicBuffer(nullptr), - mEglDisplay(EGL_NO_DISPLAY), - mBufferState(), - mRequestBufferCalled(false), - mFrameNumber(0), - mEglFence(EGL_NO_SYNC_KHR), - mFence(Fence::NO_FENCE), - mAcquireCalled(false), - mNeedsReallocation(false) { + : mGraphicBuffer(nullptr), +#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP) + mEglDisplay(EGL_NO_DISPLAY), +#endif + mBufferState(), + mRequestBufferCalled(false), + mFrameNumber(0), +#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP) + mEglFence(EGL_NO_SYNC_KHR), +#endif + mFence(Fence::NO_FENCE), + mAcquireCalled(false), + mNeedsReallocation(false) { } // mGraphicBuffer points to the buffer allocated for this slot or is NULL // if no buffer has been allocated. sp mGraphicBuffer; +#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP) // mEglDisplay is the EGLDisplay used to create EGLSyncKHR objects. EGLDisplay mEglDisplay; - +#endif // mBufferState is the current state of this buffer slot. BufferState mBufferState; @@ -207,12 +211,14 @@ struct BufferSlot { // may be released before their release fence is signaled). uint64_t mFrameNumber; +#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP) // mEglFence is the EGL sync object that must signal before the buffer // associated with this buffer slot may be dequeued. It is initialized // to EGL_NO_SYNC_KHR when the buffer is created and may be set to a // new sync object in releaseBuffer. (This is deprecated in favor of // mFence, below.) EGLSyncKHR mEglFence; +#endif // mFence is a fence which will signal when work initiated by the // previous owner of the buffer is finished. When the buffer is FREE, -- cgit v1.2.3-59-g8ed1b