libgui: move fence handling into ConsumerBase

This change moves some common fence handling code into the base class for
BufferQueue consumer classes.  It also makes the ConsumerBase class initialize
a buffer slot's fence with the acquire fence every time a buffer is acquired.

Change-Id: I0bd88bc269e919653b659bfb3ebfb04dd61692a0
This commit is contained in:
Jamie Gennis 2012-09-05 20:09:05 -07:00
parent 331841b96b
commit b272541546
7 changed files with 50 additions and 27 deletions

View File

@ -152,7 +152,14 @@ protected:
// it is overridden the derived class's implementation must call
// ConsumerBase::acquireBufferLocked.
virtual status_t releaseBufferLocked(int buf, EGLDisplay display,
EGLSyncKHR eglFence, const sp<Fence>& fence);
EGLSyncKHR eglFence);
// addReleaseFence adds the sync points associated with a fence to the set
// of sync points that must be reached before the buffer in the given slot
// may be used after the slot has been released. This should be called by
// derived classes each time some asynchronous work is kicked off that
// references the buffer.
status_t addReleaseFence(int slot, const sp<Fence>& fence);
// Slot contains the information and object references that
// ConsumerBase maintains about a BufferQueue buffer slot.

View File

@ -220,7 +220,7 @@ protected:
// releaseBufferLocked overrides the ConsumerBase method to update the
// mEglSlots array in addition to the ConsumerBase.
virtual status_t releaseBufferLocked(int buf, EGLDisplay display,
EGLSyncKHR eglFence, const sp<Fence>& fence);
EGLSyncKHR eglFence);
static bool isExternalFormat(uint32_t format);

View File

@ -82,8 +82,10 @@ status_t BufferItemConsumer::releaseBuffer(const BufferItem &item,
Mutex::Autolock _l(mMutex);
err = addReleaseFence(item.mBuf, releaseFence);
err = releaseBufferLocked(item.mBuf, EGL_NO_DISPLAY,
EGL_NO_SYNC_KHR, releaseFence);
EGL_NO_SYNC_KHR);
if (err != OK) {
BI_LOGE("Failed to release buffer: %s (%d)",
strerror(-err), err);

View File

@ -185,15 +185,40 @@ status_t ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *item) {
mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;
}
mSlots[item->mBuf].mFence = item->mFence;
CB_LOGV("acquireBufferLocked: -> slot=%d", item->mBuf);
return OK;
}
status_t ConsumerBase::addReleaseFence(int slot, const sp<Fence>& fence) {
CB_LOGV("addReleaseFence: slot=%d", slot);
if (!mSlots[slot].mFence.get()) {
mSlots[slot].mFence = fence;
} else {
sp<Fence> mergedFence = Fence::merge(
String8("ConsumerBase merged release"),
mSlots[slot].mFence, fence);
if (!mergedFence.get()) {
CB_LOGE("failed to merge release fences");
// synchronization is broken, the best we can do is hope fences
// signal in order so the new fence will act like a union
mSlots[slot].mFence = fence;
return BAD_VALUE;
}
mSlots[slot].mFence = mergedFence;
}
return OK;
}
status_t ConsumerBase::releaseBufferLocked(int slot, EGLDisplay display,
EGLSyncKHR eglFence, const sp<Fence>& fence) {
EGLSyncKHR eglFence) {
CB_LOGV("releaseBufferLocked: slot=%d", slot);
status_t err = mBufferQueue->releaseBuffer(slot, display, eglFence, fence);
status_t err = mBufferQueue->releaseBuffer(slot, display, eglFence,
mSlots[slot].mFence);
if (err == BufferQueue::STALE_BUFFER_SLOT) {
freeBufferLocked(slot);
}

View File

@ -134,7 +134,7 @@ status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) {
CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, slotIndex);
return err;
}
releaseBufferLocked(slotIndex, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
releaseBufferLocked(slotIndex, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
mCurrentLockedBuffers--;

View File

@ -172,9 +172,9 @@ status_t SurfaceTexture::acquireBufferLocked(BufferQueue::BufferItem *item) {
}
status_t SurfaceTexture::releaseBufferLocked(int buf, EGLDisplay display,
EGLSyncKHR eglFence, const sp<Fence>& fence) {
EGLSyncKHR eglFence) {
status_t err = ConsumerBase::releaseBufferLocked(buf, mEglDisplay,
eglFence, fence);
eglFence);
mEglSlots[mCurrentTexture].mEglFence = EGL_NO_SYNC_KHR;
@ -229,7 +229,7 @@ status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
// not accept this buffer. this is used by SurfaceFlinger to
// reject buffers which have the wrong size
if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) {
releaseBufferLocked(buf, dpy, EGL_NO_SYNC_KHR, item.mFence);
releaseBufferLocked(buf, dpy, EGL_NO_SYNC_KHR);
glBindTexture(mTexTarget, mTexName);
return NO_ERROR;
}
@ -256,7 +256,7 @@ status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
if (err != NO_ERROR) {
// Release the buffer we just acquired. It's not safe to
// release the old buffer, so instead we just drop the new frame.
releaseBufferLocked(buf, dpy, EGL_NO_SYNC_KHR, item.mFence);
releaseBufferLocked(buf, dpy, EGL_NO_SYNC_KHR);
return err;
}
@ -268,8 +268,7 @@ status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
// release old buffer
if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
status_t status = releaseBufferLocked(mCurrentTexture, dpy,
mEglSlots[mCurrentTexture].mEglFence,
mSlots[mCurrentTexture].mFence);
mEglSlots[mCurrentTexture].mEglFence);
if (status != NO_ERROR && status != BufferQueue::STALE_BUFFER_SLOT) {
ST_LOGE("updateTexImage: failed to release buffer: %s (%d)",
strerror(-status), status);
@ -304,20 +303,10 @@ void SurfaceTexture::setReleaseFence(int fenceFd) {
sp<Fence> fence(new Fence(fenceFd));
if (fenceFd == -1 || mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT)
return;
if (!mSlots[mCurrentTexture].mFence.get()) {
mSlots[mCurrentTexture].mFence = fence;
} else {
sp<Fence> mergedFence = Fence::merge(
String8("SurfaceTexture merged release"),
mSlots[mCurrentTexture].mFence, fence);
if (!mergedFence.get()) {
ST_LOGE("failed to merge release fences");
// synchronization is broken, the best we can do is hope fences
// signal in order so the new fence will act like a union
mSlots[mCurrentTexture].mFence = fence;
return;
}
mSlots[mCurrentTexture].mFence = mergedFence;
status_t err = addReleaseFence(mCurrentTexture, fence);
if (err != OK) {
ST_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
strerror(-err), err);
}
}

View File

@ -125,7 +125,7 @@ status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>* buffer) {
item.mBuf != mCurrentBufferSlot) {
// Release the previous buffer.
err = releaseBufferLocked(mCurrentBufferSlot, EGL_NO_DISPLAY,
EGL_NO_SYNC_KHR, Fence::NO_FENCE);
EGL_NO_SYNC_KHR);
if (err != NO_ERROR && err != BufferQueue::STALE_BUFFER_SLOT) {
ALOGE("error releasing buffer: %s (%d)", strerror(-err), err);
return err;