Loading libs/gui/BufferQueueConsumer.cpp +27 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,10 @@ #define VALIDATE_CONSISTENCY() #endif #define EGL_EGLEXT_PROTOTYPES #include <EGL/egl.h> #include <EGL/eglext.h> #include <gui/BufferItem.h> #include <gui/BufferQueueConsumer.h> #include <gui/BufferQueueCore.h> Loading Loading @@ -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<IProducerListener> listener; { // Autolock scope std::lock_guard<std::mutex> lock(mCore->mMutex); Loading @@ -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(); Loading libs/gui/BufferQueueCore.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -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; Loading libs/gui/BufferQueueProducer.cpp +12 −0 Original line number Diff line number Diff line Loading @@ -451,8 +451,10 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* 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<IConsumerListener> listener; Loading Loading @@ -569,8 +571,10 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* 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; Loading @@ -595,14 +599,18 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* 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 Loading Loading @@ -691,6 +699,7 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* 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); Loading @@ -705,6 +714,7 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou } eglDestroySyncKHR(eglDisplay, eglFence); } #endif BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x", *outSlot, Loading Loading @@ -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; Loading libs/gui/include/gui/BufferSlot.h +17 −11 Original line number Diff line number Diff line Loading @@ -174,14 +174,17 @@ struct BufferState { }; struct BufferSlot { BufferSlot() : 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) { Loading @@ -191,9 +194,10 @@ struct BufferSlot { // if no buffer has been allocated. sp<GraphicBuffer> 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; Loading @@ -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, Loading Loading
libs/gui/BufferQueueConsumer.cpp +27 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,10 @@ #define VALIDATE_CONSISTENCY() #endif #define EGL_EGLEXT_PROTOTYPES #include <EGL/egl.h> #include <EGL/eglext.h> #include <gui/BufferItem.h> #include <gui/BufferQueueConsumer.h> #include <gui/BufferQueueCore.h> Loading Loading @@ -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<IProducerListener> listener; { // Autolock scope std::lock_guard<std::mutex> lock(mCore->mMutex); Loading @@ -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(); Loading
libs/gui/BufferQueueCore.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
libs/gui/BufferQueueProducer.cpp +12 −0 Original line number Diff line number Diff line Loading @@ -451,8 +451,10 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* 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<IConsumerListener> listener; Loading Loading @@ -569,8 +571,10 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* 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; Loading @@ -595,14 +599,18 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* 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 Loading Loading @@ -691,6 +699,7 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* 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); Loading @@ -705,6 +714,7 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou } eglDestroySyncKHR(eglDisplay, eglFence); } #endif BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x", *outSlot, Loading Loading @@ -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; Loading
libs/gui/include/gui/BufferSlot.h +17 −11 Original line number Diff line number Diff line Loading @@ -174,14 +174,17 @@ struct BufferState { }; struct BufferSlot { BufferSlot() : 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) { Loading @@ -191,9 +194,10 @@ struct BufferSlot { // if no buffer has been allocated. sp<GraphicBuffer> 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; Loading @@ -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, Loading