From 8dc55396fc9bc425b5e2c82e76a38080f2a655ff Mon Sep 17 00:00:00 2001 From: Dan Stoza Date: Tue, 4 Nov 2014 11:37:46 -0800 Subject: Add a BufferItem parameter to onFrameAvailable Passes the BufferItem for the queued buffer to the onFrameAvailable callback so the consumer can track the BufferQueue's contents. Also adds an onFrameReplaced callback, which is necessary if the consumer wants to do anything more than simple queue length tracking. Bug: 18111837 Change-Id: If9d07229c9b586c668e5f99074e9b63b0468feb0 --- libs/gui/BufferQueueProducer.cpp | 44 ++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) (limited to 'libs/gui/BufferQueueProducer.cpp') diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 284ddb2bf4..4d3b008dff 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -39,7 +39,11 @@ BufferQueueProducer::BufferQueueProducer(const sp& core) : mSlots(core->mSlots), mConsumerName(), mStickyTransform(0), - mLastQueueBufferFence(Fence::NO_FENCE) {} + mLastQueueBufferFence(Fence::NO_FENCE), + mCallbackMutex(), + mNextCallbackTicket(0), + mCurrentCallbackTicket(0), + mCallbackCondition() {} BufferQueueProducer::~BufferQueueProducer() {} @@ -542,7 +546,10 @@ status_t BufferQueueProducer::queueBuffer(int slot, return BAD_VALUE; } - sp listener; + sp frameAvailableListener; + sp frameReplacedListener; + int callbackTicket = 0; + BufferItem item; { // Autolock scope Mutex::Autolock lock(mCore->mMutex); @@ -598,7 +605,6 @@ status_t BufferQueueProducer::queueBuffer(int slot, ++mCore->mFrameCounter; mSlots[slot].mFrameNumber = mCore->mFrameCounter; - BufferItem item; item.mAcquireCalled = mSlots[slot].mAcquireCalled; item.mGraphicBuffer = mSlots[slot].mGraphicBuffer; item.mCrop = crop; @@ -619,7 +625,7 @@ status_t BufferQueueProducer::queueBuffer(int slot, // When the queue is empty, we can ignore mDequeueBufferCannotBlock // and simply queue this buffer mCore->mQueue.push_back(item); - listener = mCore->mConsumerListener; + frameAvailableListener = mCore->mConsumerListener; } else { // When the queue is not empty, we need to look at the front buffer // state to see if we need to replace it @@ -635,9 +641,10 @@ status_t BufferQueueProducer::queueBuffer(int slot, } // Overwrite the droppable buffer with the incoming one *front = item; + frameReplacedListener = mCore->mConsumerListener; } else { mCore->mQueue.push_back(item); - listener = mCore->mConsumerListener; + frameAvailableListener = mCore->mConsumerListener; } } @@ -648,6 +655,9 @@ status_t BufferQueueProducer::queueBuffer(int slot, mCore->mTransformHint, mCore->mQueue.size()); ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size()); + + // Take a ticket for the callback functions + callbackTicket = mNextCallbackTicket++; } // Autolock scope // Wait without lock held @@ -659,9 +669,27 @@ status_t BufferQueueProducer::queueBuffer(int slot, mLastQueueBufferFence = fence; } - // Call back without lock held - if (listener != NULL) { - listener->onFrameAvailable(); + // Don't send the GraphicBuffer through the callback, and don't send + // the slot number, since the consumer shouldn't need it + item.mGraphicBuffer.clear(); + item.mSlot = BufferItem::INVALID_BUFFER_SLOT; + + // Call back without the main BufferQueue lock held, but with the callback + // lock held so we can ensure that callbacks occur in order + { + Mutex::Autolock lock(mCallbackMutex); + while (callbackTicket != mCurrentCallbackTicket) { + mCallbackCondition.wait(mCallbackMutex); + } + + if (frameAvailableListener != NULL) { + frameAvailableListener->onFrameAvailable(item); + } else if (frameReplacedListener != NULL) { + frameReplacedListener->onFrameReplaced(item); + } + + ++mCurrentCallbackTicket; + mCallbackCondition.broadcast(); } return NO_ERROR; -- cgit v1.2.3-59-g8ed1b