libgui: Plumb attach/detach through CpuConsumer
Adds CpuConsumer::{detachNextBuffer,attachAndReleaseBuffer}, which
can be used to more carefully manage the ownership of GraphicBuffers.
Bug: 19628705
Change-Id: Ia7a7e30da6d81eb2367241998f14988db0afc3bf
diff --git a/include/gui/CpuConsumer.h b/include/gui/CpuConsumer.h
index c99ab29..0e3e1ec 100644
--- a/include/gui/CpuConsumer.h
+++ b/include/gui/CpuConsumer.h
@@ -114,6 +114,20 @@
// lockNextBuffer.
status_t unlockBuffer(const LockedBuffer &nativeBuffer);
+ // Gets the next buffer from the producer (if any), and transfers ownership
+ // of it from the queue to the caller.
+ //
+ // See IGraphicBufferConsumer::{acquireBuffer,detachBuffer} for possible
+ // error codes.
+ status_t detachNextBuffer(BufferItem* outItem);
+
+ // Transfers ownership of the buffer from the caller to the queue, and
+ // releases the buffer for use by the producer.
+ //
+ // See IGraphicBufferConsumer::{attachBuffer,releaseBuffer} for possible
+ // error codes.
+ status_t attachAndReleaseBuffer(const sp<GraphicBuffer>& buffer);
+
private:
// Maximum number of buffers that can be locked at a time
size_t mMaxLockedBuffers;
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 526c3b7..c7faeeb 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -247,12 +247,16 @@
ATRACE_BUFFER_INDEX(*outSlot);
BQ_LOGV("attachBuffer(C): returning slot %d", *outSlot);
+ // If these are modified, they also need to be modified in
+ // CpuConsumer::attachAndReleaseBuffer
mSlots[*outSlot].mGraphicBuffer = buffer;
+ mSlots[*outSlot].mFence = Fence::NO_FENCE;
+ mSlots[*outSlot].mFrameNumber = 0;
+
+ // Changes to these do not need to be propagated to CpuConsumer
mSlots[*outSlot].mBufferState = BufferSlot::ACQUIRED;
mSlots[*outSlot].mAttachedByConsumer = true;
mSlots[*outSlot].mNeedsCleanupOnRelease = false;
- mSlots[*outSlot].mFence = Fence::NO_FENCE;
- mSlots[*outSlot].mFrameNumber = 0;
// mAcquireCalled tells BufferQueue that it doesn't need to send a valid
// GraphicBuffer pointer on the next acquireBuffer call, which decreases
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index eb39469..1f9c657 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -277,4 +277,59 @@
ConsumerBase::freeBufferLocked(slotIndex);
}
+status_t CpuConsumer::detachNextBuffer(BufferItem* outItem) {
+ if (outItem == NULL) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock lock(mMutex);
+
+ BufferItem item;
+ status_t result = acquireBufferLocked(&item, 0);
+ if (result != NO_ERROR) {
+ CC_LOGE("%s: Failed to acquire buffer (%d)", __FUNCTION__, result);
+ return result;
+ }
+
+ result = mConsumer->detachBuffer(item.mSlot);
+ if (result != NO_ERROR) {
+ CC_LOGE("%s: Failed to detach buffer (%d)", __FUNCTION__, result);
+ return result;
+ }
+
+ freeBufferLocked(item.mSlot);
+
+ *outItem = item;
+ return NO_ERROR;
+}
+
+status_t CpuConsumer::attachAndReleaseBuffer(const sp<GraphicBuffer>& buffer) {
+ if (buffer == NULL) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock lock(mMutex);
+
+ int slot = -1;
+ status_t result = mConsumer->attachBuffer(&slot, buffer);
+ if (result != NO_ERROR) {
+ CC_LOGE("%s: Failed to attach buffer (%d)", __FUNCTION__, result);
+ return result;
+ }
+
+ // These behaviors must be kept in sync with
+ // BufferQueueConsumer::attachBuffer
+ mSlots[slot].mGraphicBuffer = buffer;
+ mSlots[slot].mFence = Fence::NO_FENCE;
+ mSlots[slot].mFrameNumber = 0;
+
+ result = releaseBufferLocked(slot, buffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
+ if (result != NO_ERROR) {
+ CC_LOGE("%s: Failed to release buffer (%d)", __FUNCTION__, result);
+ return result;
+ }
+
+ return NO_ERROR;
+}
+
} // namespace android