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

Commit a277b7a4 authored by Jesse Hall's avatar Jesse Hall Committed by Android (Google) Code Review
Browse files

Merge "Transfer HWC release fences to BufferQueue"

parents 37815d16 ef19414b
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <gui/IGraphicBufferAlloc.h>
#include <gui/ISurfaceTexture.h>

#include <ui/Fence.h>
#include <ui/GraphicBuffer.h>

#include <utils/String8.h>
@@ -218,7 +219,8 @@ public:
    //
    // Note that the dependencies on EGL will be removed once we switch to using
    // the Android HW Sync HAL.
    status_t releaseBuffer(int buf, EGLDisplay display, EGLSyncKHR fence);
    status_t releaseBuffer(int buf, EGLDisplay display, EGLSyncKHR fence,
            const sp<Fence>& releaseFence = Fence::NO_FENCE);

    // consumerConnect connects a consumer to the BufferQueue.  Only one
    // consumer may be connected, and when that consumer disconnects the
@@ -378,6 +380,10 @@ private:
        // on a compile-time option) set to a new sync object in updateTexImage.
        EGLSyncKHR mFence;

        // mReleaseFence is a fence which must signal before the contents of
        // the buffer associated with this buffer slot may be overwritten.
        sp<Fence> mReleaseFence;

        // Indicates whether this buffer has been seen by a consumer yet
        bool mAcquireCalled;

+15 −0
Original line number Diff line number Diff line
@@ -91,6 +91,14 @@ public:
    // target texture belongs is bound to the calling thread.
    status_t updateTexImage();

    // setReleaseFence stores a fence file descriptor that will signal when the
    // current buffer is no longer being read. This fence will be returned to
    // the producer when the current buffer is released by updateTexImage().
    // Multiple fences can be set for a given buffer; they will be merged into
    // a single union fence. The SurfaceTexture will close the file descriptor
    // when finished with it.
    void setReleaseFence(int fenceFd);

    // setBufferCountServer set the buffer count. If the client has requested
    // a buffer count using setBufferCount, the server-buffer count will
    // take effect once the client sets the count back to zero.
@@ -349,6 +357,13 @@ private:
        // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
        // on a compile-time option) set to a new sync object in updateTexImage.
        EGLSyncKHR mFence;

        // mReleaseFence is a fence which will signal when the buffer
        // associated with this buffer slot is no longer being used by the
        // consumer and can be overwritten. The buffer can be dequeued before
        // the fence signals; the producer is responsible for delaying writes
        // until it signals.
        sp<Fence> mReleaseFence;
    };

    // mEglDisplay is the EGLDisplay with which this SurfaceTexture is currently
+1 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ class Fence
    : public LightRefBase<Fence>, public Flattenable
{
public:
    static const sp<Fence> NO_FENCE;

    // Construct a new Fence object with an invalid file descriptor.  This
    // should be done when the Fence object will be set up by unflattening
+5 −4
Original line number Diff line number Diff line
@@ -25,14 +25,15 @@ LOCAL_SRC_FILES:= \
	CpuConsumer.cpp

LOCAL_SHARED_LIBRARIES := \
	libcutils \
	libutils \
	libbinder \
	libcutils \
	libEGL \
	libGLESv2 \
	libhardware \
	libhardware_legacy \
	libsync \
	libui \
	libEGL \
	libGLESv2 \
	libutils \


LOCAL_MODULE:= libgui
+17 −4
Original line number Diff line number Diff line
@@ -307,6 +307,7 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
    status_t returnFlags(OK);
    EGLDisplay dpy = EGL_NO_DISPLAY;
    EGLSyncKHR fence = EGL_NO_SYNC_KHR;
    sp<Fence> releaseFence;

    { // Scope for the lock
        Mutex::Autolock lock(mMutex);
@@ -318,7 +319,6 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
        usage |= mConsumerUsageBits;

        int found = -1;
        int foundSync = -1;
        int dequeuedCount = 0;
        bool tryAgain = true;
        while (tryAgain) {
@@ -369,7 +369,6 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,

            // look for a free buffer to give to the client
            found = INVALID_BUFFER_SLOT;
            foundSync = INVALID_BUFFER_SLOT;
            dequeuedCount = 0;
            for (int i = 0; i < mBufferCount; i++) {
                const int state = mSlots[i].mBufferState;
@@ -393,7 +392,6 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
                        bool isOlder = mSlots[i].mFrameNumber <
                                mSlots[found].mFrameNumber;
                        if (found < 0 || isOlder) {
                            foundSync = i;
                            found = i;
                        }
                    }
@@ -484,6 +482,7 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
            mSlots[buf].mGraphicBuffer = graphicBuffer;
            mSlots[buf].mRequestBufferCalled = false;
            mSlots[buf].mFence = EGL_NO_SYNC_KHR;
            mSlots[buf].mReleaseFence.clear();
            mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;

            returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
@@ -491,7 +490,9 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,

        dpy = mSlots[buf].mEglDisplay;
        fence = mSlots[buf].mFence;
        releaseFence = mSlots[buf].mReleaseFence;
        mSlots[buf].mFence = EGL_NO_SYNC_KHR;
        mSlots[buf].mReleaseFence.clear();
    }  // end lock scope

    if (fence != EGL_NO_SYNC_KHR) {
@@ -507,6 +508,16 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
        eglDestroySyncKHR(dpy, fence);
    }

    if (releaseFence.get()) {
        int err = releaseFence->wait(1000);
        if (err == -ETIME) {
            ALOGE("dequeueBuffer: timeout waiting for release fence");
        } else if (err != NO_ERROR) {
            ALOGE("dequeueBuffer: error waiting for sync fence: %d", err);
        }
        releaseFence.clear();
    }

    ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
            mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);

@@ -846,6 +857,7 @@ void BufferQueue::freeBufferLocked(int i) {
        eglDestroySyncKHR(mSlots[i].mEglDisplay, mSlots[i].mFence);
        mSlots[i].mFence = EGL_NO_SYNC_KHR;
    }
    mSlots[i].mReleaseFence.clear();
}

void BufferQueue::freeAllBuffersLocked() {
@@ -896,7 +908,7 @@ status_t BufferQueue::acquireBuffer(BufferItem *buffer) {
}

status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display,
        EGLSyncKHR fence) {
        EGLSyncKHR fence, const sp<Fence>& releaseFence) {
    ATRACE_CALL();
    ATRACE_BUFFER_INDEX(buf);

@@ -908,6 +920,7 @@ status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display,

    mSlots[buf].mEglDisplay = display;
    mSlots[buf].mFence = fence;
    mSlots[buf].mReleaseFence = releaseFence;

    // The buffer can now only be released if its in the acquired state
    if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
Loading