Pass fences from BufferQueue to SurfaceTextureClient

ISurfaceTexture::dequeueBuffer now returns the buffer's fence for the
client to wait on. For BufferQueue, this means passing it through
Binder so it can be returned to the SurfaceTextureClient. Now
SurfaceTextureClient is responsible for waiting on the fence in
dequeueBuffer instead of BufferQueue: one step closer to the goal.

Change-Id: I677ae758bcd23acee2d784b8cec11b32cccc196d
This commit is contained in:
Jesse Hall 2012-06-14 15:26:33 -07:00
parent ef19414bd8
commit f785754009
5 changed files with 45 additions and 23 deletions

View File

@ -116,12 +116,18 @@ public:
// pointed to by the buf argument and a status of OK is returned. If no // pointed to by the buf argument and a status of OK is returned. If no
// slot is available then a status of -EBUSY is returned and buf is // slot is available then a status of -EBUSY is returned and buf is
// unmodified. // unmodified.
//
// The fence parameter will be updated to hold the fence associated with
// the buffer. The contents of the buffer must not be overwritten until the
// fence signals. If the fence is NULL, the buffer may be written
// immediately.
//
// The width and height parameters must be no greater than the minimum of // The width and height parameters must be no greater than the minimum of
// GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv). // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
// An error due to invalid dimensions might not be reported until // An error due to invalid dimensions might not be reported until
// updateTexImage() is called. // updateTexImage() is called.
virtual status_t dequeueBuffer(int *buf, uint32_t width, uint32_t height, virtual status_t dequeueBuffer(int *buf, sp<Fence>& fence,
uint32_t format, uint32_t usage); uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
// queueBuffer returns a filled buffer to the BufferQueue. In addition, a // queueBuffer returns a filled buffer to the BufferQueue. In addition, a
// timestamp must be provided for the buffer. The timestamp is in // timestamp must be provided for the buffer. The timestamp is in
@ -220,7 +226,7 @@ public:
// Note that the dependencies on EGL will be removed once we switch to using // Note that the dependencies on EGL will be removed once we switch to using
// the Android HW Sync HAL. // the Android HW Sync HAL.
status_t releaseBuffer(int buf, EGLDisplay display, EGLSyncKHR fence, status_t releaseBuffer(int buf, EGLDisplay display, EGLSyncKHR fence,
const sp<Fence>& releaseFence = Fence::NO_FENCE); const sp<Fence>& releaseFence);
// consumerConnect connects a consumer to the BufferQueue. Only one // consumerConnect connects a consumer to the BufferQueue. Only one
// consumer may be connected, and when that consumer disconnects the // consumer may be connected, and when that consumer disconnects the

View File

@ -25,6 +25,7 @@
#include <binder/IInterface.h> #include <binder/IInterface.h>
#include <ui/Fence.h>
#include <ui/GraphicBuffer.h> #include <ui/GraphicBuffer.h>
#include <ui/Rect.h> #include <ui/Rect.h>
@ -67,8 +68,13 @@ protected:
// in the contents of its associated buffer contents and call queueBuffer. // in the contents of its associated buffer contents and call queueBuffer.
// If dequeueBuffer return BUFFER_NEEDS_REALLOCATION, the client is // If dequeueBuffer return BUFFER_NEEDS_REALLOCATION, the client is
// expected to call requestBuffer immediately. // expected to call requestBuffer immediately.
virtual status_t dequeueBuffer(int *slot, uint32_t w, uint32_t h, //
uint32_t format, uint32_t usage) = 0; // The fence parameter will be updated to hold the fence associated with
// the buffer. The contents of the buffer must not be overwritten until the
// fence signals. If the fence is NULL, the buffer may be written
// immediately.
virtual status_t dequeueBuffer(int *slot, sp<Fence>& fence,
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0;
// queueBuffer indicates that the client has finished filling in the // queueBuffer indicates that the client has finished filling in the
// contents of the buffer associated with slot and transfers ownership of // contents of the buffer associated with slot and transfers ownership of

View File

@ -294,8 +294,8 @@ status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
return NO_ERROR; return NO_ERROR;
} }
status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence,
uint32_t format, uint32_t usage) { uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
ATRACE_CALL(); ATRACE_CALL();
ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage); ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
@ -307,7 +307,6 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
status_t returnFlags(OK); status_t returnFlags(OK);
EGLDisplay dpy = EGL_NO_DISPLAY; EGLDisplay dpy = EGL_NO_DISPLAY;
EGLSyncKHR fence = EGL_NO_SYNC_KHR; EGLSyncKHR fence = EGL_NO_SYNC_KHR;
sp<Fence> releaseFence;
{ // Scope for the lock { // Scope for the lock
Mutex::Autolock lock(mMutex); Mutex::Autolock lock(mMutex);
@ -490,7 +489,7 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
dpy = mSlots[buf].mEglDisplay; dpy = mSlots[buf].mEglDisplay;
fence = mSlots[buf].mFence; fence = mSlots[buf].mFence;
releaseFence = mSlots[buf].mReleaseFence; outFence = mSlots[buf].mReleaseFence;
mSlots[buf].mFence = EGL_NO_SYNC_KHR; mSlots[buf].mFence = EGL_NO_SYNC_KHR;
mSlots[buf].mReleaseFence.clear(); mSlots[buf].mReleaseFence.clear();
} // end lock scope } // end lock scope
@ -508,16 +507,6 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
eglDestroySyncKHR(dpy, fence); eglDestroySyncKHR(dpy, fence);
} }
if (releaseFence.get()) {
int err = releaseFence->wait(1000);
if (err == -ETIME) {
ALOGE("dequeueBuffer: timeout waiting for release fence");
} else if (err != NO_ERROR) {
ALOGE("dequeueBuffer: error waiting for sync fence: %d", err);
}
releaseFence.clear();
}
ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf, ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
mSlots[*outBuf].mGraphicBuffer->handle, returnFlags); mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);

View File

@ -81,8 +81,8 @@ public:
return result; return result;
} }
virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h, virtual status_t dequeueBuffer(int *buf, sp<Fence>& fence,
uint32_t format, uint32_t usage) { uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
Parcel data, reply; Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(w); data.writeInt32(w);
@ -94,6 +94,12 @@ public:
return result; return result;
} }
*buf = reply.readInt32(); *buf = reply.readInt32();
fence.clear();
bool hasFence = reply.readInt32();
if (hasFence) {
fence = new Fence();
reply.read(*fence.get());
}
result = reply.readInt32(); result = reply.readInt32();
return result; return result;
} }
@ -205,8 +211,13 @@ status_t BnSurfaceTexture::onTransact(
uint32_t format = data.readInt32(); uint32_t format = data.readInt32();
uint32_t usage = data.readInt32(); uint32_t usage = data.readInt32();
int buf; int buf;
int result = dequeueBuffer(&buf, w, h, format, usage); sp<Fence> fence;
int result = dequeueBuffer(&buf, fence, w, h, format, usage);
reply->writeInt32(buf); reply->writeInt32(buf);
reply->writeInt32(fence.get() != NULL);
if (fence.get() != NULL) {
reply->write(*fence.get());
}
reply->writeInt32(result); reply->writeInt32(result);
return NO_ERROR; return NO_ERROR;
} break; } break;

View File

@ -198,7 +198,8 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer,
int buf = -1; int buf = -1;
int reqW = mReqWidth ? mReqWidth : mUserWidth; int reqW = mReqWidth ? mReqWidth : mUserWidth;
int reqH = mReqHeight ? mReqHeight : mUserHeight; int reqH = mReqHeight ? mReqHeight : mUserHeight;
status_t result = mSurfaceTexture->dequeueBuffer(&buf, reqW, reqH, sp<Fence> fence;
status_t result = mSurfaceTexture->dequeueBuffer(&buf, fence, reqW, reqH,
mReqFormat, mReqUsage); mReqFormat, mReqUsage);
if (result < 0) { if (result < 0) {
ALOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer(%d, %d, %d, %d)" ALOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer(%d, %d, %d, %d)"
@ -219,6 +220,15 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer,
return result; return result;
} }
} }
if (fence.get()) {
status_t err = fence->wait(Fence::TIMEOUT_NEVER);
if (err != OK) {
ALOGE("dequeueBuffer: error waiting for fence: %d", err);
}
fence.clear();
}
*buffer = gbuf.get(); *buffer = gbuf.get();
*fenceFd = -1; *fenceFd = -1;
return OK; return OK;