Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8e637485 authored by Jim Shargo's avatar Jim Shargo Committed by Android (Google) Code Review
Browse files

Merge "bufferqueues: Move the gl fence wait from dequeue to releaseBuffer" into main

parents 11c42854 9084218d
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -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>
@@ -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);
@@ -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();

+3 −1
Original line number Diff line number Diff line
@@ -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;
+12 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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
@@ -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);
@@ -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,
@@ -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;
+17 −11
Original line number Diff line number Diff line
@@ -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) {
@@ -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;

@@ -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,