make sure BufferQueue releases newly acquired buffers on failures

this prevents SurfaceTexture producer to hang in dequeueBuffer()
when something goes wrong in the consumer.
only the consumer gets an error and the current frame is kept
instead of the new one. the producer is unaware of the problem.

Bug: 6476587
Change-Id: Ie6db5526632aabc3e60229b93dfe29c19491ade4
This commit is contained in:
Mathias Agopian 2012-05-18 16:50:58 -07:00
parent f899e4113a
commit 7e477bfe11

View File

@ -235,17 +235,19 @@ status_t SurfaceTexture::updateTexImage() {
if (image == EGL_NO_IMAGE_KHR) { if (image == EGL_NO_IMAGE_KHR) {
if (mEGLSlots[buf].mGraphicBuffer == NULL) { if (mEGLSlots[buf].mGraphicBuffer == NULL) {
ST_LOGE("updateTexImage: buffer at slot %d is null", buf); ST_LOGE("updateTexImage: buffer at slot %d is null", buf);
return BAD_VALUE; err = BAD_VALUE;
} } else {
image = createImage(dpy, mEGLSlots[buf].mGraphicBuffer); image = createImage(dpy, mEGLSlots[buf].mGraphicBuffer);
mEGLSlots[buf].mEglImage = image; mEGLSlots[buf].mEglImage = image;
if (image == EGL_NO_IMAGE_KHR) { if (image == EGL_NO_IMAGE_KHR) {
// NOTE: if dpy was invalid, createImage() is guaranteed to // NOTE: if dpy was invalid, createImage() is guaranteed to
// fail. so we'd end up here. // fail. so we'd end up here.
return UNKNOWN_ERROR; err = UNKNOWN_ERROR;
}
} }
} }
if (err == NO_ERROR) {
GLint error; GLint error;
while ((error = glGetError()) != GL_NO_ERROR) { while ((error = glGetError()) != GL_NO_ERROR) {
ST_LOGW("updateTexImage: clearing GL error: %#04x", error); ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
@ -260,11 +262,12 @@ status_t SurfaceTexture::updateTexImage() {
err = UNKNOWN_ERROR; err = UNKNOWN_ERROR;
} }
if (err == OK) { if (err == NO_ERROR) {
err = syncForReleaseLocked(dpy); err = syncForReleaseLocked(dpy);
} }
}
if (err != OK) { if (err != NO_ERROR) {
// Release the buffer we just acquired. It's not safe to // Release the buffer we just acquired. It's not safe to
// release the old buffer, so instead we just drop the new frame. // release the old buffer, so instead we just drop the new frame.
mBufferQueue->releaseBuffer(buf, dpy, mEGLSlots[buf].mFence); mBufferQueue->releaseBuffer(buf, dpy, mEGLSlots[buf].mFence);
@ -279,12 +282,13 @@ status_t SurfaceTexture::updateTexImage() {
// release old buffer // release old buffer
if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
status_t status = mBufferQueue->releaseBuffer(mCurrentTexture, dpy, mEGLSlots[mCurrentTexture].mFence); status_t status = mBufferQueue->releaseBuffer(mCurrentTexture, dpy,
mEGLSlots[mCurrentTexture].mFence);
mEGLSlots[mCurrentTexture].mFence = EGL_NO_SYNC_KHR; mEGLSlots[mCurrentTexture].mFence = EGL_NO_SYNC_KHR;
if (status == BufferQueue::STALE_BUFFER_SLOT) { if (status == BufferQueue::STALE_BUFFER_SLOT) {
freeBufferLocked(mCurrentTexture); freeBufferLocked(mCurrentTexture);
} else if (status != OK) { } else if (status != NO_ERROR) {
ST_LOGE("updateTexImage: released invalid buffer"); ST_LOGE("updateTexImage: released invalid buffer");
err = status; err = status;
} }