am aaebffd5: Merge "CpuConsumer: Properly track acquired buffers" into jb-mr2-dev

* commit 'aaebffd52f1bfa3d239bba0d60b699c01c6d791c':
  CpuConsumer: Properly track acquired buffers
This commit is contained in:
Eino-Ville Talvala 2013-03-21 16:40:18 +00:00 committed by Android Git Automerger
commit a010749b41
2 changed files with 63 additions and 34 deletions

View File

@ -37,7 +37,7 @@ namespace android {
* This queue is synchronous by default. * This queue is synchronous by default.
*/ */
class CpuConsumer: public ConsumerBase class CpuConsumer : public ConsumerBase
{ {
public: public:
typedef ConsumerBase::FrameAvailableListener FrameAvailableListener; typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;
@ -88,14 +88,25 @@ class CpuConsumer: public ConsumerBase
// Maximum number of buffers that can be locked at a time // Maximum number of buffers that can be locked at a time
uint32_t mMaxLockedBuffers; uint32_t mMaxLockedBuffers;
status_t releaseAcquiredBufferLocked(int lockedIdx);
virtual void freeBufferLocked(int slotIndex); virtual void freeBufferLocked(int slotIndex);
// Array for tracking pointers passed to the consumer, matching the // Tracking for buffers acquired by the user
// mSlots indexing struct AcquiredBuffer {
struct LockedSlot { // Need to track the original mSlot index and the buffer itself because
// the mSlot entry may be freed/reused before the acquired buffer is
// released.
int mSlot;
sp<GraphicBuffer> mGraphicBuffer; sp<GraphicBuffer> mGraphicBuffer;
void *mBufferPointer; void *mBufferPointer;
} mLockedSlots[BufferQueue::NUM_BUFFER_SLOTS];
AcquiredBuffer() :
mSlot(BufferQueue::INVALID_BUFFER_SLOT),
mBufferPointer(NULL) {
}
};
Vector<AcquiredBuffer> mAcquiredBuffers;
// Count of currently locked buffers // Count of currently locked buffers
uint32_t mCurrentLockedBuffers; uint32_t mCurrentLockedBuffers;

View File

@ -17,8 +17,9 @@
//#define LOG_NDEBUG 0 //#define LOG_NDEBUG 0
#define LOG_TAG "CpuConsumer" #define LOG_TAG "CpuConsumer"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS #define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <utils/Log.h>
#include <cutils/compiler.h>
#include <utils/Log.h>
#include <gui/CpuConsumer.h> #include <gui/CpuConsumer.h>
#define CC_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__) #define CC_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
@ -34,9 +35,8 @@ CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers, bool synchronousMode) :
mMaxLockedBuffers(maxLockedBuffers), mMaxLockedBuffers(maxLockedBuffers),
mCurrentLockedBuffers(0) mCurrentLockedBuffers(0)
{ {
for (size_t i=0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { // Create tracking entries for locked buffers
mLockedSlots[i].mBufferPointer = NULL; mAcquiredBuffers.insertAt(0, maxLockedBuffers);
}
mBufferQueue->setSynchronousMode(synchronousMode); mBufferQueue->setSynchronousMode(synchronousMode);
mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN); mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);
@ -44,21 +44,11 @@ CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers, bool synchronousMode) :
} }
CpuConsumer::~CpuConsumer() { CpuConsumer::~CpuConsumer() {
status_t err; // ConsumerBase destructor does all the work.
for (size_t i=0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
if (mLockedSlots[i].mBufferPointer != NULL) {
mLockedSlots[i].mBufferPointer = NULL;
err = mLockedSlots[i].mGraphicBuffer->unlock();
mLockedSlots[i].mGraphicBuffer.clear();
if (err != OK) {
CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__,
i);
}
}
}
} }
void CpuConsumer::setName(const String8& name) { void CpuConsumer::setName(const String8& name) {
Mutex::Autolock _l(mMutex); Mutex::Autolock _l(mMutex);
mName = name; mName = name;
@ -109,8 +99,19 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
err); err);
return err; return err;
} }
mLockedSlots[buf].mBufferPointer = bufferPointer; size_t lockedIdx = 0;
mLockedSlots[buf].mGraphicBuffer = mSlots[buf].mGraphicBuffer; for (; lockedIdx < mMaxLockedBuffers; lockedIdx++) {
if (mAcquiredBuffers[lockedIdx].mSlot ==
BufferQueue::INVALID_BUFFER_SLOT) {
break;
}
}
assert(lockedIdx < mMaxLockedBuffers);
AcquiredBuffer &ab = mAcquiredBuffers.editItemAt(lockedIdx);
ab.mSlot = buf;
ab.mBufferPointer = bufferPointer;
ab.mGraphicBuffer = mSlots[buf].mGraphicBuffer;
nativeBuffer->data = nativeBuffer->data =
reinterpret_cast<uint8_t*>(bufferPointer); reinterpret_cast<uint8_t*>(bufferPointer);
@ -132,29 +133,46 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) { status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) {
Mutex::Autolock _l(mMutex); Mutex::Autolock _l(mMutex);
int slotIndex = 0; size_t lockedIdx = 0;
status_t err; status_t err;
void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data); void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data);
for (; slotIndex < BufferQueue::NUM_BUFFER_SLOTS; slotIndex++) { for (; lockedIdx < mMaxLockedBuffers; lockedIdx++) {
if (bufPtr == mLockedSlots[slotIndex].mBufferPointer) break; if (bufPtr == mAcquiredBuffers[lockedIdx].mBufferPointer) break;
} }
if (slotIndex == BufferQueue::NUM_BUFFER_SLOTS) { if (lockedIdx == mMaxLockedBuffers) {
CC_LOGE("%s: Can't find buffer to free", __FUNCTION__); CC_LOGE("%s: Can't find buffer to free", __FUNCTION__);
return BAD_VALUE; return BAD_VALUE;
} }
mLockedSlots[slotIndex].mBufferPointer = NULL; return releaseAcquiredBufferLocked(lockedIdx);
err = mLockedSlots[slotIndex].mGraphicBuffer->unlock(); }
mLockedSlots[slotIndex].mGraphicBuffer.clear();
status_t CpuConsumer::releaseAcquiredBufferLocked(int lockedIdx) {
status_t err;
err = mAcquiredBuffers[lockedIdx].mGraphicBuffer->unlock();
if (err != OK) { if (err != OK) {
CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, slotIndex); CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__,
lockedIdx);
return err; return err;
} }
releaseBufferLocked(slotIndex, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR); int buf = mAcquiredBuffers[lockedIdx].mSlot;
// release the buffer if it hasn't already been freed by the BufferQueue.
// This can happen, for example, when the producer of this buffer
// disconnected after this buffer was acquired.
if (CC_LIKELY(mAcquiredBuffers[lockedIdx].mGraphicBuffer ==
mSlots[buf].mGraphicBuffer)) {
releaseBufferLocked(buf, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
}
AcquiredBuffer &ab = mAcquiredBuffers.editItemAt(lockedIdx);
ab.mSlot = BufferQueue::INVALID_BUFFER_SLOT;
ab.mBufferPointer = NULL;
ab.mGraphicBuffer.clear();
mCurrentLockedBuffers--; mCurrentLockedBuffers--;
return OK; return OK;
} }