From a929748ddb67cbece3337c7fda7877fdeb973aa4 Mon Sep 17 00:00:00 2001 From: Sunita Nadampalli Date: Wed, 9 Nov 2011 18:23:41 -0600 Subject: [PATCH] SurfaceTexture: Fix to return the oldest of free buffers to Client on Dequeue call Surface Texture dequeue logic is modified to return the oldest of the free buffers to Client on dequeue call. Currently dequeue method is returning the first buffer index which is free. The parsing is done in ascending order of the buffer slot indices. This leads to returning the buffer which has been just queued to composer, and hence display, and this defeats the purpose of having minimum dequeue count as 2 in asynchrnouse mode. This is fixed by checking all the free slots and returning the oldest buffer. Change-Id: Ibbac10593c3994c278c601af0480b171635ecdd4 Signed-off-by: Sunita Nadampalli --- include/gui/SurfaceTexture.h | 13 ++++++++++++- libs/gui/SurfaceTexture.cpp | 22 +++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h index d7dd4d6cb..27d863de5 100644 --- a/include/gui/SurfaceTexture.h +++ b/include/gui/SurfaceTexture.h @@ -271,7 +271,8 @@ private: mRequestBufferCalled(false), mTransform(0), mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), - mTimestamp(0) { + mTimestamp(0), + mFrameNumber(0) { mCrop.makeInvalid(); } @@ -340,6 +341,10 @@ private: // mTimestamp is the current timestamp for this buffer slot. This gets // to set by queueBuffer each time this slot is queued. int64_t mTimestamp; + + // mFrameNumber is the number of the queued frame for this slot. + uint64_t mFrameNumber; + }; // mSlots is the array of buffer slots that must be mirrored on the client @@ -476,6 +481,12 @@ private: // around a GL driver limitation on the number of FBO attachments, which the // browser's tile cache exceeds. const GLenum mTexTarget; + + // mFrameCounter is the free running counter, incremented for every buffer queued + // with the surface Texture. + uint64_t mFrameCounter; + + }; // ---------------------------------------------------------------------------- diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 6f842067c..3c0d4756f 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -112,7 +112,8 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode, mAllowSynchronousMode(allowSynchronousMode), mConnectedApi(NO_CONNECTED_API), mAbandoned(false), - mTexTarget(texTarget) { + mTexTarget(texTarget), + mFrameCounter(0) { // Choose a name using the PID and a process-unique ID. mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); @@ -260,7 +261,8 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, status_t returnFlags(OK); - int found, foundSync; + int found = -1; + int foundSync = -1; int dequeuedCount = 0; bool tryAgain = true; while (tryAgain) { @@ -333,9 +335,14 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, } } else { if (state == BufferSlot::FREE) { - foundSync = i; - found = i; - break; + /** For Asynchronous mode, we need to return the oldest of free buffers + * There is only one instance when the Framecounter overflows, this logic + * might return the earlier buffer to client. Which is a negligible impact + **/ + if (found < 0 || mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) { + foundSync = i; + found = i; + } } } } @@ -527,6 +534,9 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp, mSlots[buf].mTransform = mNextTransform; mSlots[buf].mScalingMode = mNextScalingMode; mSlots[buf].mTimestamp = timestamp; + mFrameCounter++; + mSlots[buf].mFrameNumber = mFrameCounter; + mDequeueCondition.signal(); *outWidth = mDefaultWidth; @@ -560,6 +570,7 @@ void SurfaceTexture::cancelBuffer(int buf) { return; } mSlots[buf].mBufferState = BufferSlot::FREE; + mSlots[buf].mFrameNumber = 0; mDequeueCondition.signal(); } @@ -893,6 +904,7 @@ void SurfaceTexture::setFrameAvailableListener( void SurfaceTexture::freeBufferLocked(int i) { mSlots[i].mGraphicBuffer = 0; mSlots[i].mBufferState = BufferSlot::FREE; + mSlots[i].mFrameNumber = 0; if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage); mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;