diff options
author | Dan Stoza <stoza@google.com> | 2014-03-28 15:25:31 -0700 |
---|---|---|
committer | Dan Stoza <stoza@google.com> | 2014-04-15 10:27:25 -0700 |
commit | d9822a3843017444364899afc3c23fb5be6b9cb9 (patch) | |
tree | 563f14d7526d30eebe5913d66ed150609c2796eb | |
parent | 7f605bd4c09e2b086e69751491e25e98f4a0eb98 (diff) | |
download | frameworks_native-d9822a3843017444364899afc3c23fb5be6b9cb9.zip frameworks_native-d9822a3843017444364899afc3c23fb5be6b9cb9.tar.gz frameworks_native-d9822a3843017444364899afc3c23fb5be6b9cb9.tar.bz2 |
BufferQueueProducer: add detachNextBuffer
Adds a new method, IGBP::detachNextBuffer, that effectively does
dequeue + request + detach in a single call, but does not need to
know anything about the dequeued buffer, and will not block on
dequeue. This is mostly for the upcoming StreamSplitter to use in
its onBufferReleased callback.
Change-Id: Ie88a69de109003acebaa486a5b44c8a455726550
-rw-r--r-- | include/gui/BufferQueue.h | 4 | ||||
-rw-r--r-- | include/gui/BufferQueueProducer.h | 4 | ||||
-rw-r--r-- | include/gui/IGraphicBufferProducer.h | 21 | ||||
-rw-r--r-- | libs/gui/BufferQueue.cpp | 5 | ||||
-rw-r--r-- | libs/gui/BufferQueueProducer.cpp | 44 | ||||
-rw-r--r-- | libs/gui/IGraphicBufferProducer.cpp | 50 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp | 6 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/MonitoredProducer.cpp | 5 | ||||
-rw-r--r-- | services/surfaceflinger/MonitoredProducer.h | 2 |
10 files changed, 143 insertions, 0 deletions
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h index da876ec..311926d 100644 --- a/include/gui/BufferQueue.h +++ b/include/gui/BufferQueue.h @@ -199,6 +199,10 @@ public: // See IGraphicBufferProducer::detachBuffer virtual status_t detachProducerBuffer(int slot); + // See IGraphicBufferProducer::detachNextBuffer + virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, + sp<Fence>* outFence); + // See IGraphicBufferProducer::attachBuffer virtual status_t attachProducerBuffer(int* slot, const sp<GraphicBuffer>& buffer); diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h index 04692a5..9df3633 100644 --- a/include/gui/BufferQueueProducer.h +++ b/include/gui/BufferQueueProducer.h @@ -99,6 +99,10 @@ public: // See IGraphicBufferProducer::detachBuffer virtual status_t detachBuffer(int slot); + // See IGraphicBufferProducer::detachNextBuffer + virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, + sp<Fence>* outFence); + // See IGraphicBufferProducer::attachBuffer virtual status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer); diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h index 2b61ab3..d9e116b 100644 --- a/include/gui/IGraphicBufferProducer.h +++ b/include/gui/IGraphicBufferProducer.h @@ -185,6 +185,27 @@ public: // it refers to is not currently dequeued and requested. virtual status_t detachBuffer(int slot) = 0; + // detachNextBuffer is equivalent to calling dequeueBuffer, requestBuffer, + // and detachBuffer in sequence, except for two things: + // + // 1) It is unnecessary to know the dimensions, format, or usage of the + // next buffer. + // 2) It will not block, since if it cannot find an appropriate buffer to + // return, it will return an error instead. + // + // Only slots that are free but still contain a GraphicBuffer will be + // considered, and the oldest of those will be returned. outBuffer is + // equivalent to outBuffer from the requestBuffer call, and outFence is + // equivalent to fence from the dequeueBuffer call. + // + // Return of a value other than NO_ERROR means an error has occurred: + // * NO_INIT - the buffer queue has been abandoned. + // * BAD_VALUE - either outBuffer or outFence were NULL. + // * NO_MEMORY - no slots were found that were both free and contained a + // GraphicBuffer. + virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, + sp<Fence>* outFence) = 0; + // attachBuffer attempts to transfer ownership of a buffer to the buffer // queue. If this call succeeds, it will be as if this buffer was dequeued // from the returned slot number. As such, this call will fail if attaching diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index d04b67d..da980a7 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -103,6 +103,11 @@ status_t BufferQueue::detachProducerBuffer(int slot) { return mProducer->detachBuffer(slot); } +status_t BufferQueue::detachNextBuffer(sp<GraphicBuffer>* outBuffer, + sp<Fence>* outFence) { + return mProducer->detachNextBuffer(outBuffer, outFence); +} + status_t BufferQueue::attachProducerBuffer(int* slot, const sp<GraphicBuffer>& buffer) { return mProducer->attachBuffer(slot, buffer); diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index ea37309..61846dd 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -393,6 +393,50 @@ status_t BufferQueueProducer::detachBuffer(int slot) { return NO_ERROR; } +status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer, + sp<Fence>* outFence) { + ATRACE_CALL(); + + if (outBuffer == NULL) { + BQ_LOGE("detachNextBuffer: outBuffer must not be NULL"); + return BAD_VALUE; + } else if (outFence == NULL) { + BQ_LOGE("detachNextBuffer: outFence must not be NULL"); + return BAD_VALUE; + } + + Mutex::Autolock lock(mCore->mMutex); + + if (mCore->mIsAbandoned) { + BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned"); + return NO_INIT; + } + + // Find the oldest valid slot + int found = BufferQueueCore::INVALID_BUFFER_SLOT; + for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { + if (mSlots[s].mBufferState == BufferSlot::FREE && + mSlots[s].mGraphicBuffer != NULL) { + if (found == BufferQueueCore::INVALID_BUFFER_SLOT || + mSlots[s].mFrameNumber < mSlots[found].mFrameNumber) { + found = s; + } + } + } + + if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { + return NO_MEMORY; + } + + BQ_LOGV("detachNextBuffer detached slot %d", found); + + *outBuffer = mSlots[found].mGraphicBuffer; + *outFence = mSlots[found].mFence; + mCore->freeBufferLocked(found); + + return NO_ERROR; +} + status_t BufferQueueProducer::attachBuffer(int* outSlot, const sp<android::GraphicBuffer>& buffer) { ATRACE_CALL(); diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index c0b08c1..aa6acb9 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -37,6 +37,7 @@ enum { SET_BUFFER_COUNT, DEQUEUE_BUFFER, DETACH_BUFFER, + DETACH_NEXT_BUFFER, ATTACH_BUFFER, QUEUE_BUFFER, CANCEL_BUFFER, @@ -123,6 +124,37 @@ public: return result; } + virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, + sp<Fence>* outFence) { + if (outBuffer == NULL) { + ALOGE("detachNextBuffer: outBuffer must not be NULL"); + return BAD_VALUE; + } else if (outFence == NULL) { + ALOGE("detachNextBuffer: outFence must not be NULL"); + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); + status_t result = remote()->transact(DETACH_NEXT_BUFFER, data, &reply); + if (result != NO_ERROR) { + return result; + } + result = reply.readInt32(); + if (result == NO_ERROR) { + bool nonNull = reply.readInt32(); + if (nonNull) { + *outBuffer = new GraphicBuffer; + reply.read(**outBuffer); + } + nonNull = reply.readInt32(); + if (nonNull) { + *outFence = new Fence; + reply.read(**outFence); + } + } + return result; + } + virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); @@ -274,6 +306,24 @@ status_t BnGraphicBufferProducer::onTransact( reply->writeInt32(result); return NO_ERROR; } break; + case DETACH_NEXT_BUFFER: { + CHECK_INTERFACE(IGraphicBufferProducer, data, reply); + sp<GraphicBuffer> buffer; + sp<Fence> fence; + int32_t result = detachNextBuffer(&buffer, &fence); + reply->writeInt32(result); + if (result == NO_ERROR) { + reply->writeInt32(buffer != NULL); + if (buffer != NULL) { + reply->write(*buffer); + } + reply->writeInt32(fence != NULL); + if (fence != NULL) { + reply->write(*fence); + } + } + return NO_ERROR; + } break; case ATTACH_BUFFER: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); sp<GraphicBuffer> buffer = new GraphicBuffer(); diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index 67229d5..85e2ee5 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -380,6 +380,12 @@ status_t VirtualDisplaySurface::detachBuffer(int /* slot */) { return INVALID_OPERATION; } +status_t VirtualDisplaySurface::detachNextBuffer( + sp<GraphicBuffer>* /* outBuffer */, sp<Fence>* /* outFence */) { + VDS_LOGE("detachNextBuffer is not available for VirtualDisplaySurface"); + return INVALID_OPERATION; +} + status_t VirtualDisplaySurface::attachBuffer(int* /* outSlot */, const sp<GraphicBuffer>& /* buffer */) { VDS_LOGE("attachBuffer is not available for VirtualDisplaySurface"); diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index 165224a..144f871 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -101,6 +101,8 @@ private: virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, bool async, uint32_t w, uint32_t h, uint32_t format, uint32_t usage); virtual status_t detachBuffer(int slot); + virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, + sp<Fence>* outFence); virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer); virtual status_t queueBuffer(int pslot, const QueueBufferInput& input, QueueBufferOutput* output); diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp index 1a2b7e5..d0e81bc 100644 --- a/services/surfaceflinger/MonitoredProducer.cpp +++ b/services/surfaceflinger/MonitoredProducer.cpp @@ -69,6 +69,11 @@ status_t MonitoredProducer::detachBuffer(int slot) { return mProducer->detachBuffer(slot); } +status_t MonitoredProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer, + sp<Fence>* outFence) { + return mProducer->detachNextBuffer(outBuffer, outFence); +} + status_t MonitoredProducer::attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer) { return mProducer->attachBuffer(outSlot, buffer); diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h index 1e6431e..f034e39 100644 --- a/services/surfaceflinger/MonitoredProducer.h +++ b/services/surfaceflinger/MonitoredProducer.h @@ -39,6 +39,8 @@ public: virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, bool async, uint32_t w, uint32_t h, uint32_t format, uint32_t usage); virtual status_t detachBuffer(int slot); + virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, + sp<Fence>* outFence); virtual status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer); virtual status_t queueBuffer(int slot, const QueueBufferInput& input, |