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:
parent
331841b96b
commit
b272541546
@ -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.
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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--;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user