diff options
author | Jesse Hall <jessehall@google.com> | 2012-06-28 12:52:05 -0700 |
---|---|---|
committer | Jesse Hall <jessehall@google.com> | 2012-06-30 21:38:51 -0700 |
commit | c777b0b3b9b0ea5d8e378fccde6935765e28e329 (patch) | |
tree | 83ef3d6288766dc474bb9a77ebc947b0857865df /libs | |
parent | 02a7be74dd0c4eb47a522cb0f646736cb6d0de01 (diff) | |
download | frameworks_native-c777b0b3b9b0ea5d8e378fccde6935765e28e329.zip frameworks_native-c777b0b3b9b0ea5d8e378fccde6935765e28e329.tar.gz frameworks_native-c777b0b3b9b0ea5d8e378fccde6935765e28e329.tar.bz2 |
Pass fences with buffers from SurfaceTextureClient
Change-Id: I09b49433788d01e8b2b3684bb4d0112be29538d3
Diffstat (limited to 'libs')
-rw-r--r-- | libs/gui/BufferQueue.cpp | 39 | ||||
-rw-r--r-- | libs/gui/ISurfaceTexture.cpp | 86 | ||||
-rw-r--r-- | libs/gui/SurfaceTextureClient.cpp | 23 | ||||
-rw-r--r-- | libs/ui/Fence.cpp | 3 |
4 files changed, 108 insertions, 43 deletions
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index 40e43a1..a868537 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -306,7 +306,7 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence, status_t returnFlags(OK); EGLDisplay dpy = EGL_NO_DISPLAY; - EGLSyncKHR fence = EGL_NO_SYNC_KHR; + EGLSyncKHR eglFence = EGL_NO_SYNC_KHR; { // Scope for the lock Mutex::Autolock lock(mMutex); @@ -480,22 +480,22 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence, mSlots[buf].mAcquireCalled = false; mSlots[buf].mGraphicBuffer = graphicBuffer; mSlots[buf].mRequestBufferCalled = false; - mSlots[buf].mFence = EGL_NO_SYNC_KHR; - mSlots[buf].mReleaseFence.clear(); + mSlots[buf].mEglFence = EGL_NO_SYNC_KHR; + mSlots[buf].mFence.clear(); mSlots[buf].mEglDisplay = EGL_NO_DISPLAY; returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; } dpy = mSlots[buf].mEglDisplay; - fence = mSlots[buf].mFence; - outFence = mSlots[buf].mReleaseFence; - mSlots[buf].mFence = EGL_NO_SYNC_KHR; - mSlots[buf].mReleaseFence.clear(); + eglFence = mSlots[buf].mEglFence; + outFence = mSlots[buf].mFence; + mSlots[buf].mEglFence = EGL_NO_SYNC_KHR; + mSlots[buf].mFence.clear(); } // end lock scope - if (fence != EGL_NO_SYNC_KHR) { - EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000); + if (eglFence != EGL_NO_SYNC_KHR) { + EGLint result = eglClientWaitSyncKHR(dpy, eglFence, 0, 1000000000); // If something goes wrong, log the error, but return the buffer without // synchronizing access to it. It's too late at this point to abort the // dequeue operation. @@ -504,7 +504,7 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence, } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { ST_LOGE("dequeueBuffer: timeout waiting for fence"); } - eglDestroySyncKHR(dpy, fence); + eglDestroySyncKHR(dpy, eglFence); } ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf, @@ -554,8 +554,9 @@ status_t BufferQueue::queueBuffer(int buf, uint32_t transform; int scalingMode; int64_t timestamp; + sp<Fence> fence; - input.deflate(×tamp, &crop, &scalingMode, &transform); + input.deflate(×tamp, &crop, &scalingMode, &transform, &fence); ST_LOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x " "scale=%s", @@ -622,6 +623,7 @@ status_t BufferQueue::queueBuffer(int buf, mSlots[buf].mTimestamp = timestamp; mSlots[buf].mCrop = crop; mSlots[buf].mTransform = transform; + mSlots[buf].mFence = fence; switch (scalingMode) { case NATIVE_WINDOW_SCALING_MODE_FREEZE: @@ -655,7 +657,7 @@ status_t BufferQueue::queueBuffer(int buf, return OK; } -void BufferQueue::cancelBuffer(int buf) { +void BufferQueue::cancelBuffer(int buf, sp<Fence> fence) { ATRACE_CALL(); ST_LOGV("cancelBuffer: slot=%d", buf); Mutex::Autolock lock(mMutex); @@ -676,6 +678,7 @@ void BufferQueue::cancelBuffer(int buf) { } mSlots[buf].mBufferState = BufferSlot::FREE; mSlots[buf].mFrameNumber = 0; + mSlots[buf].mFence = fence; mDequeueCondition.broadcast(); } @@ -842,11 +845,11 @@ void BufferQueue::freeBufferLocked(int i) { mSlots[i].mAcquireCalled = false; // destroy fence as BufferQueue now takes ownership - if (mSlots[i].mFence != EGL_NO_SYNC_KHR) { - eglDestroySyncKHR(mSlots[i].mEglDisplay, mSlots[i].mFence); - mSlots[i].mFence = EGL_NO_SYNC_KHR; + if (mSlots[i].mEglFence != EGL_NO_SYNC_KHR) { + eglDestroySyncKHR(mSlots[i].mEglDisplay, mSlots[i].mEglFence); + mSlots[i].mEglFence = EGL_NO_SYNC_KHR; } - mSlots[i].mReleaseFence.clear(); + mSlots[i].mFence.clear(); } void BufferQueue::freeAllBuffersLocked() { @@ -897,7 +900,7 @@ status_t BufferQueue::acquireBuffer(BufferItem *buffer) { } status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display, - EGLSyncKHR fence, const sp<Fence>& releaseFence) { + EGLSyncKHR eglFence, const sp<Fence>& fence) { ATRACE_CALL(); ATRACE_BUFFER_INDEX(buf); @@ -908,8 +911,8 @@ status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display, } mSlots[buf].mEglDisplay = display; + mSlots[buf].mEglFence = eglFence; mSlots[buf].mFence = fence; - mSlots[buf].mReleaseFence = releaseFence; // The buffer can now only be released if its in the acquired state if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) { diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp index c8fef06..a0b1e74 100644 --- a/libs/gui/ISurfaceTexture.cpp +++ b/libs/gui/ISurfaceTexture.cpp @@ -109,7 +109,7 @@ public: Parcel data, reply; data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); data.writeInt32(buf); - memcpy(data.writeInplace(sizeof(input)), &input, sizeof(input)); + data.write(input); status_t result = remote()->transact(QUEUE_BUFFER, data, &reply); if (result != NO_ERROR) { return result; @@ -119,10 +119,15 @@ public: return result; } - virtual void cancelBuffer(int buf) { + virtual void cancelBuffer(int buf, sp<Fence> fence) { Parcel data, reply; + bool hasFence = fence.get() && fence->isValid(); data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor()); data.writeInt32(buf); + data.writeInt32(hasFence); + if (hasFence) { + data.write(*fence.get()); + } remote()->transact(CANCEL_BUFFER, data, &reply); } @@ -213,9 +218,10 @@ status_t BnSurfaceTexture::onTransact( int buf; sp<Fence> fence; int result = dequeueBuffer(&buf, fence, w, h, format, usage); + bool hasFence = fence.get() && fence->isValid(); reply->writeInt32(buf); - reply->writeInt32(fence.get() != NULL); - if (fence.get() != NULL) { + reply->writeInt32(hasFence); + if (hasFence) { reply->write(*fence.get()); } reply->writeInt32(result); @@ -224,20 +230,24 @@ status_t BnSurfaceTexture::onTransact( case QUEUE_BUFFER: { CHECK_INTERFACE(ISurfaceTexture, data, reply); int buf = data.readInt32(); - QueueBufferInput const* const input = - reinterpret_cast<QueueBufferInput const *>( - data.readInplace(sizeof(QueueBufferInput))); + QueueBufferInput input(data); QueueBufferOutput* const output = reinterpret_cast<QueueBufferOutput *>( reply->writeInplace(sizeof(QueueBufferOutput))); - status_t result = queueBuffer(buf, *input, output); + status_t result = queueBuffer(buf, input, output); reply->writeInt32(result); return NO_ERROR; } break; case CANCEL_BUFFER: { CHECK_INTERFACE(ISurfaceTexture, data, reply); int buf = data.readInt32(); - cancelBuffer(buf); + sp<Fence> fence; + bool hasFence = data.readInt32(); + if (hasFence) { + fence = new Fence(); + data.read(*fence.get()); + } + cancelBuffer(buf, fence); return NO_ERROR; } break; case QUERY: { @@ -279,4 +289,62 @@ status_t BnSurfaceTexture::onTransact( // ---------------------------------------------------------------------------- +static bool isValid(const sp<Fence>& fence) { + return fence.get() && fence->isValid(); +} + +ISurfaceTexture::QueueBufferInput::QueueBufferInput(const Parcel& parcel) { + parcel.read(*this); +} + +size_t ISurfaceTexture::QueueBufferInput::getFlattenedSize() const +{ + return sizeof(timestamp) + + sizeof(crop) + + sizeof(scalingMode) + + sizeof(transform) + + sizeof(bool) + + (isValid(fence) ? fence->getFlattenedSize() : 0); +} + +size_t ISurfaceTexture::QueueBufferInput::getFdCount() const +{ + return isValid(fence) ? fence->getFdCount() : 0; +} + +status_t ISurfaceTexture::QueueBufferInput::flatten(void* buffer, size_t size, + int fds[], size_t count) const +{ + status_t err = NO_ERROR; + bool haveFence = isValid(fence); + char* p = (char*)buffer; + memcpy(p, ×tamp, sizeof(timestamp)); p += sizeof(timestamp); + memcpy(p, &crop, sizeof(crop)); p += sizeof(crop); + memcpy(p, &scalingMode, sizeof(scalingMode)); p += sizeof(scalingMode); + memcpy(p, &transform, sizeof(transform)); p += sizeof(transform); + memcpy(p, &haveFence, sizeof(haveFence)); p += sizeof(haveFence); + if (haveFence) { + err = fence->flatten(p, size - (p - (char*)buffer), fds, count); + } + return err; +} + +status_t ISurfaceTexture::QueueBufferInput::unflatten(void const* buffer, + size_t size, int fds[], size_t count) +{ + status_t err = NO_ERROR; + bool haveFence; + const char* p = (const char*)buffer; + memcpy(×tamp, p, sizeof(timestamp)); p += sizeof(timestamp); + memcpy(&crop, p, sizeof(crop)); p += sizeof(crop); + memcpy(&scalingMode, p, sizeof(scalingMode)); p += sizeof(scalingMode); + memcpy(&transform, p, sizeof(transform)); p += sizeof(transform); + memcpy(&haveFence, p, sizeof(haveFence)); p += sizeof(haveFence); + if (haveFence) { + fence = new Fence(); + err = fence->unflatten(p, size - (p - (const char*)buffer), fds, count); + } + return err; +} + }; // namespace android diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index 84f2ff4..718fe84 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -237,7 +237,8 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer, return OK; } -int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer, int fenceFd) { +int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer, + int fenceFd) { ATRACE_CALL(); ALOGV("SurfaceTextureClient::cancelBuffer"); Mutex::Autolock lock(mMutex); @@ -245,13 +246,8 @@ int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer, int fenc if (i < 0) { return i; } - sp<Fence> fence(new Fence(fenceFd)); - status_t err = fence->wait(Fence::TIMEOUT_NEVER); - if (err != OK) { - ALOGE("queueBuffer: Fence::wait returned an error: %d", err); - return err; - } - mSurfaceTexture->cancelBuffer(i); + sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : NULL); + mSurfaceTexture->cancelBuffer(i, fence); return OK; } @@ -291,21 +287,16 @@ int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer, int fence return i; } - sp<Fence> fence(new Fence(fenceFd)); - status_t err = fence->wait(Fence::TIMEOUT_NEVER); - if (err != OK) { - ALOGE("queueBuffer: Fence::wait returned an error: %d", err); - return err; - } // Make sure the crop rectangle is entirely inside the buffer. Rect crop; mCrop.intersect(Rect(buffer->width, buffer->height), &crop); + sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : NULL); ISurfaceTexture::QueueBufferOutput output; ISurfaceTexture::QueueBufferInput input(timestamp, crop, mScalingMode, - mTransform); - err = mSurfaceTexture->queueBuffer(i, input, &output); + mTransform, fence); + status_t err = mSurfaceTexture->queueBuffer(i, input, &output); if (err != OK) { ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err); } diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp index 08340f2..932bcdd 100644 --- a/libs/ui/Fence.cpp +++ b/libs/ui/Fence.cpp @@ -63,6 +63,9 @@ sp<Fence> Fence::merge(const String8& name, const sp<Fence>& f1, } int Fence::dup() const { + if (mFenceFd == -1) { + return -1; + } return ::dup(mFenceFd); } |