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

Commit 1efe099a authored by Jamie Gennis's avatar Jamie Gennis
Browse files

BufferQueue: alloc without holding the lock

This change makes BufferQueue::dequeueBuffer release its mutex before
allocating new buffers.  This should alleviate lock contention in
SurfaceFlinger where SF's main thread can get blocked waiting for an allocation
operation to complete.

Bug: 7335075
Change-Id: I1b000539cc616a695afab2e9c68507db69e57b13
parent f0c89b28
Loading
Loading
Loading
Loading
+25 −11
Original line number Original line Diff line number Diff line
@@ -385,18 +385,8 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence,
            (uint32_t(buffer->format) != format) ||
            (uint32_t(buffer->format) != format) ||
            ((uint32_t(buffer->usage) & usage) != usage))
            ((uint32_t(buffer->usage) & usage) != usage))
        {
        {
            status_t error;
            sp<GraphicBuffer> graphicBuffer(
                    mGraphicBufferAlloc->createGraphicBuffer(
                            w, h, format, usage, &error));
            if (graphicBuffer == 0) {
                ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
                        "failed");
                return error;
            }

            mSlots[buf].mAcquireCalled = false;
            mSlots[buf].mAcquireCalled = false;
            mSlots[buf].mGraphicBuffer = graphicBuffer;
            mSlots[buf].mGraphicBuffer = NULL;
            mSlots[buf].mRequestBufferCalled = false;
            mSlots[buf].mRequestBufferCalled = false;
            mSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
            mSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
            mSlots[buf].mFence.clear();
            mSlots[buf].mFence.clear();
@@ -412,6 +402,30 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence,
        mSlots[buf].mFence.clear();
        mSlots[buf].mFence.clear();
    }  // end lock scope
    }  // end lock scope


    if (returnFlags & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) {
        status_t error;
        sp<GraphicBuffer> graphicBuffer(
                mGraphicBufferAlloc->createGraphicBuffer(
                        w, h, format, usage, &error));
        if (graphicBuffer == 0) {
            ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
                    "failed");
            return error;
        }

        { // Scope for the lock
            Mutex::Autolock lock(mMutex);

            if (mAbandoned) {
                ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
                return NO_INIT;
            }

            mSlots[*outBuf].mGraphicBuffer = graphicBuffer;
        }
    }


    if (eglFence != EGL_NO_SYNC_KHR) {
    if (eglFence != EGL_NO_SYNC_KHR) {
        EGLint result = eglClientWaitSyncKHR(dpy, eglFence, 0, 1000000000);
        EGLint result = eglClientWaitSyncKHR(dpy, eglFence, 0, 1000000000);
        // If something goes wrong, log the error, but return the buffer without
        // If something goes wrong, log the error, but return the buffer without