diff --git a/include/gui/CpuConsumer.h b/include/gui/CpuConsumer.h index c99ab297d..0e3e1ec37 100644 --- a/include/gui/CpuConsumer.h +++ b/include/gui/CpuConsumer.h @@ -114,6 +114,20 @@ class CpuConsumer : public ConsumerBase // 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& 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 526c3b729..c7faeebe7 100644 --- a/libs/gui/BufferQueueConsumer.cpp +++ b/libs/gui/BufferQueueConsumer.cpp @@ -247,12 +247,16 @@ status_t BufferQueueConsumer::attachBuffer(int* outSlot, 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 eb39469b0..a054b3254 100644 --- a/libs/gui/CpuConsumer.cpp +++ b/libs/gui/CpuConsumer.cpp @@ -277,4 +277,59 @@ void CpuConsumer::freeBufferLocked(int slotIndex) { 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& 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