From 1efe099a51e2231bd938a6afcf66e6584deec0f2 Mon Sep 17 00:00:00 2001 From: Jamie Gennis Date: Thu, 4 Oct 2012 18:34:01 -0700 Subject: [PATCH] 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 --- libs/gui/BufferQueue.cpp | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index d40847674..590946a85 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -385,18 +385,8 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp& outFence, (uint32_t(buffer->format) != format) || ((uint32_t(buffer->usage) & usage) != usage)) { - status_t error; - sp 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].mGraphicBuffer = graphicBuffer; + mSlots[buf].mGraphicBuffer = NULL; mSlots[buf].mRequestBufferCalled = false; mSlots[buf].mEglFence = EGL_NO_SYNC_KHR; mSlots[buf].mFence.clear(); @@ -412,6 +402,30 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp& outFence, mSlots[buf].mFence.clear(); } // end lock scope + if (returnFlags & ISurfaceTexture::BUFFER_NEEDS_REALLOCATION) { + status_t error; + sp 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) { EGLint result = eglClientWaitSyncKHR(dpy, eglFence, 0, 1000000000); // If something goes wrong, log the error, but return the buffer without