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 <sunitan@ti.com>
This commit is contained in:
Sunita Nadampalli 2011-11-09 18:23:41 -06:00 committed by Jamie Gennis
parent 4464cb95f8
commit a929748ddb
2 changed files with 29 additions and 6 deletions

View File

@ -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;
};
// ----------------------------------------------------------------------------

View File

@ -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;