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

Commit 29b5762e authored by Mathias Agopian's avatar Mathias Agopian
Browse files

don't return the current buffer from dequeueBuffer

we were not reseting mCurrentTexture in some situations
which in turn caused dequeueBuffers() return a
"FREE" buffer that was also current.
Very often it was harmless, but it created a race with
updateTexImage() which could cause the following
queueBuffers() to fail.

Bug: 5156325
Change-Id: If15a31dc869117543d220d6e5562c57116cbabdb
parent 3902be62
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -275,7 +275,7 @@ private:
        enum BufferState {
            // FREE indicates that the buffer is not currently being used and
            // will not be used in the future until it gets dequeued and
            // subseqently queued by the client.
            // subsequently queued by the client.
            FREE = 0,

            // DEQUEUED indicates that the buffer has been dequeued by the
+23 −4
Original line number Diff line number Diff line
@@ -36,6 +36,10 @@
#include <utils/Log.h>
#include <utils/String8.h>


#define ALLOW_DEQUEUE_CURRENT_BUFFER    false


namespace android {

// Transform matrices
@@ -294,13 +298,26 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
            if (state == BufferSlot::DEQUEUED) {
                dequeuedCount++;
            }
            if (state == BufferSlot::FREE /*|| i == mCurrentTexture*/) {

            // if buffer is FREE it CANNOT be current
            LOGW_IF((state == BufferSlot::FREE) && (mCurrentTexture==i),
                    "dequeueBuffer: buffer %d is both FREE and current!", i);

            if (ALLOW_DEQUEUE_CURRENT_BUFFER) {
                if (state == BufferSlot::FREE || i == mCurrentTexture) {
                    foundSync = i;
                    if (i != mCurrentTexture) {
                        found = i;
                        break;
                    }
                }
            } else {
                if (state == BufferSlot::FREE) {
                    foundSync = i;
                    found = i;
                    break;
                }
            }
        }

        // clients are not allowed to dequeue more than one buffer
@@ -325,7 +342,7 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
        }

        // we're in synchronous mode and didn't find a buffer, we need to wait
        // for for some buffers to be consumed
        // for some buffers to be consumed
        tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
        if (tryAgain) {
            mDequeueCondition.wait(mMutex);
@@ -846,6 +863,7 @@ void SurfaceTexture::freeBufferLocked(int i) {
void SurfaceTexture::freeAllBuffersLocked() {
    LOGW_IF(!mQueue.isEmpty(),
            "freeAllBuffersLocked called but mQueue is not empty");
    mCurrentTexture = INVALID_BUFFER_SLOT;
    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
        freeBufferLocked(i);
    }
@@ -859,6 +877,7 @@ void SurfaceTexture::freeAllBuffersExceptHeadLocked() {
        Fifo::iterator front(mQueue.begin());
        head = *front;
    }
    mCurrentTexture = INVALID_BUFFER_SLOT;
    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
        if (i != head) {
            freeBufferLocked(i);