Loading include/gui/CpuConsumer.h +6 −47 Original line number Original line Diff line number Diff line Loading @@ -17,7 +17,7 @@ #ifndef ANDROID_GUI_CPUCONSUMER_H #ifndef ANDROID_GUI_CPUCONSUMER_H #define ANDROID_GUI_CPUCONSUMER_H #define ANDROID_GUI_CPUCONSUMER_H #include <gui/BufferQueue.h> #include <gui/ConsumerBase.h> #include <ui/GraphicBuffer.h> #include <ui/GraphicBuffer.h> Loading @@ -37,19 +37,10 @@ namespace android { * This queue is synchronous by default. * This queue is synchronous by default. */ */ class CpuConsumer: public virtual RefBase, class CpuConsumer: public ConsumerBase protected BufferQueue::ConsumerListener { { public: public: struct FrameAvailableListener : public virtual RefBase { typedef ConsumerBase::FrameAvailableListener FrameAvailableListener; // onFrameAvailable() is called each time an additional frame becomes // available for consumption. A new frame queued will always trigger the // callback, whether the queue is empty or not. // // This is called without any lock held and can be called concurrently // by multiple threads. virtual void onFrameAvailable() = 0; }; struct LockedBuffer { struct LockedBuffer { uint8_t *data; uint8_t *data; Loading @@ -68,8 +59,6 @@ class CpuConsumer: public virtual RefBase, // how many buffers can be locked for user access at the same time. // how many buffers can be locked for user access at the same time. CpuConsumer(uint32_t maxLockedBuffers); CpuConsumer(uint32_t maxLockedBuffers); virtual ~CpuConsumer(); // set the name of the CpuConsumer that will be used to identify it in // set the name of the CpuConsumer that will be used to identify it in // log messages. // log messages. void setName(const String8& name); void setName(const String8& name); Loading @@ -91,50 +80,20 @@ class CpuConsumer: public virtual RefBase, // lockNextBuffer. // lockNextBuffer. status_t unlockBuffer(const LockedBuffer &nativeBuffer); status_t unlockBuffer(const LockedBuffer &nativeBuffer); // setFrameAvailableListener sets the listener object that will be notified sp<ISurfaceTexture> getProducerInterface() const { return getBufferQueue(); } // when a new frame becomes available. void setFrameAvailableListener(const sp<FrameAvailableListener>& listener); sp<ISurfaceTexture> getProducerInterface() const { return mBufferQueue; } protected: // Implementation of the BufferQueue::ConsumerListener interface. These // calls are used to notify the CpuConsumer of asynchronous events in the // BufferQueue. virtual void onFrameAvailable(); virtual void onBuffersReleased(); private: private: // Free local buffer state status_t freeBufferLocked(int buf); // 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; // mName is a string used to identify the SurfaceTexture in log messages. void freeBufferLocked(int slotIndex); // It can be set by the setName method. String8 mName; // mFrameAvailableListener is the listener object that will be called when a // new frame becomes available. If it is not NULL it will be called from // queueBuffer. sp<FrameAvailableListener> mFrameAvailableListener; // Underlying buffer queue sp<BufferQueue> mBufferQueue; // Array for caching buffers from the buffer queue sp<GraphicBuffer> mBufferSlot[BufferQueue::NUM_BUFFER_SLOTS]; // Array for tracking pointers passed to the consumer, matching the // Array for tracking pointers passed to the consumer, matching the // mBufferSlot indexing // mSlots indexing void *mBufferPointers[BufferQueue::NUM_BUFFER_SLOTS]; void *mBufferPointers[BufferQueue::NUM_BUFFER_SLOTS]; // Count of currently locked buffers // Count of currently locked buffers uint32_t mCurrentLockedBuffers; uint32_t mCurrentLockedBuffers; // mMutex is the mutex used to prevent concurrent access to the member // variables of CpuConsumer objects. It must be locked whenever the // member variables are accessed. mutable Mutex mMutex; }; }; } // namespace android } // namespace android Loading libs/gui/CpuConsumer.cpp +26 −113 Original line number Original line Diff line number Diff line Loading @@ -29,49 +29,18 @@ namespace android { namespace android { // Get an ID that's unique within this process. static int32_t createProcessUniqueId() { static volatile int32_t globalCounter = 0; return android_atomic_inc(&globalCounter); } CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers) : CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers) : ConsumerBase(new BufferQueue(true, maxLockedBuffers) ), mMaxLockedBuffers(maxLockedBuffers), mMaxLockedBuffers(maxLockedBuffers), mCurrentLockedBuffers(0) mCurrentLockedBuffers(0) { { mName = String8::format("cc-unnamed-%d-%d", getpid(), createProcessUniqueId()); for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { mBufferPointers[i] = NULL; mBufferPointers[i] = NULL; } } mBufferQueue = new BufferQueue(true); wp<BufferQueue::ConsumerListener> listener; sp<BufferQueue::ConsumerListener> proxy; listener = static_cast<BufferQueue::ConsumerListener*>(this); proxy = new BufferQueue::ProxyConsumerListener(listener); status_t err = mBufferQueue->consumerConnect(proxy); if (err != NO_ERROR) { ALOGE("CpuConsumer: error connecting to BufferQueue: %s (%d)", strerror(-err), err); } else { mBufferQueue->setSynchronousMode(true); mBufferQueue->setSynchronousMode(true); mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN); mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN); mBufferQueue->setConsumerName(mName); } } CpuConsumer::~CpuConsumer() { Mutex::Autolock _l(mMutex); for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { freeBufferLocked(i); } mBufferQueue->consumerDisconnect(); mBufferQueue.clear(); } } void CpuConsumer::setName(const String8& name) { void CpuConsumer::setName(const String8& name) { Loading @@ -92,7 +61,7 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { Mutex::Autolock _l(mMutex); Mutex::Autolock _l(mMutex); err = mBufferQueue->acquireBuffer(&b); err = acquireBufferLocked(&b); if (err != OK) { if (err != OK) { if (err == BufferQueue::NO_BUFFER_AVAILABLE) { if (err == BufferQueue::NO_BUFFER_AVAILABLE) { return BAD_VALUE; return BAD_VALUE; Loading @@ -104,16 +73,6 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { int buf = b.mBuf; int buf = b.mBuf; if (b.mGraphicBuffer != NULL) { if (mBufferPointers[buf] != NULL) { CC_LOGE("Reallocation of buffer %d while in consumer use!", buf); mBufferQueue->releaseBuffer(buf, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); return BAD_VALUE; } mBufferSlot[buf] = b.mGraphicBuffer; } if (b.mFence.get()) { if (b.mFence.get()) { err = b.mFence->wait(Fence::TIMEOUT_NEVER); err = b.mFence->wait(Fence::TIMEOUT_NEVER); if (err != OK) { if (err != OK) { Loading @@ -123,7 +82,7 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { } } } } err = mBufferSlot[buf]->lock( err = mSlots[buf].mGraphicBuffer->lock( GraphicBuffer::USAGE_SW_READ_OFTEN, GraphicBuffer::USAGE_SW_READ_OFTEN, b.mCrop, b.mCrop, &mBufferPointers[buf]); &mBufferPointers[buf]); Loading @@ -135,10 +94,10 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { } } nativeBuffer->data = reinterpret_cast<uint8_t*>(mBufferPointers[buf]); nativeBuffer->data = reinterpret_cast<uint8_t*>(mBufferPointers[buf]); nativeBuffer->width = mBufferSlot[buf]->getWidth(); nativeBuffer->width = mSlots[buf].mGraphicBuffer->getWidth(); nativeBuffer->height = mBufferSlot[buf]->getHeight(); nativeBuffer->height = mSlots[buf].mGraphicBuffer->getHeight(); nativeBuffer->format = mBufferSlot[buf]->getPixelFormat(); nativeBuffer->format = mSlots[buf].mGraphicBuffer->getPixelFormat(); nativeBuffer->stride = mBufferSlot[buf]->getStride(); nativeBuffer->stride = mSlots[buf].mGraphicBuffer->getStride(); nativeBuffer->crop = b.mCrop; nativeBuffer->crop = b.mCrop; nativeBuffer->transform = b.mTransform; nativeBuffer->transform = b.mTransform; Loading @@ -153,90 +112,44 @@ 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 buf = 0; int slotIndex = 0; status_t err; status_t err; void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data); void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data); for (; buf < BufferQueue::NUM_BUFFER_SLOTS; buf++) { for (; slotIndex < BufferQueue::NUM_BUFFER_SLOTS; slotIndex++) { if (bufPtr == mBufferPointers[buf]) break; if (bufPtr == mBufferPointers[slotIndex]) break; } } if (buf == BufferQueue::NUM_BUFFER_SLOTS) { if (slotIndex == BufferQueue::NUM_BUFFER_SLOTS) { 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; } } mBufferPointers[buf] = NULL; mBufferPointers[slotIndex] = NULL; err = mBufferSlot[buf]->unlock(); err = mSlots[slotIndex].mGraphicBuffer->unlock(); if (err != OK) { if (err != OK) { CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, buf); CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, slotIndex); return err; } err = mBufferQueue->releaseBuffer(buf, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); if (err == BufferQueue::STALE_BUFFER_SLOT) { freeBufferLocked(buf); } else if (err != OK) { CC_LOGE("%s: Unable to release graphic buffer %d to queue", __FUNCTION__, buf); return err; return err; } } releaseBufferLocked(slotIndex, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); mCurrentLockedBuffers--; mCurrentLockedBuffers--; return OK; return OK; } } void CpuConsumer::setFrameAvailableListener( void CpuConsumer::freeBufferLocked(int slotIndex) { const sp<FrameAvailableListener>& listener) { if (mBufferPointers[slotIndex] != NULL) { CC_LOGV("setFrameAvailableListener"); status_t err; Mutex::Autolock lock(mMutex); CC_LOGW("Buffer %d freed while locked by consumer", slotIndex); mFrameAvailableListener = listener; mBufferPointers[slotIndex] = NULL; } err = mSlots[slotIndex].mGraphicBuffer->unlock(); void CpuConsumer::onFrameAvailable() { CC_LOGV("onFrameAvailable"); sp<FrameAvailableListener> listener; { // scope for the lock Mutex::Autolock _l(mMutex); listener = mFrameAvailableListener; } if (listener != NULL) { CC_LOGV("actually calling onFrameAvailable"); listener->onFrameAvailable(); } } void CpuConsumer::onBuffersReleased() { CC_LOGV("onBuffersReleased"); Mutex::Autolock lock(mMutex); uint32_t mask = 0; mBufferQueue->getReleasedBuffers(&mask); for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { if (mask & (1 << i)) { freeBufferLocked(i); } } } status_t CpuConsumer::freeBufferLocked(int buf) { status_t err = OK; if (mBufferPointers[buf] != NULL) { CC_LOGW("Buffer %d freed while locked by consumer", buf); mBufferPointers[buf] = NULL; err = mBufferSlot[buf]->unlock(); if (err != OK) { if (err != OK) { CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, buf); CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, slotIndex); } } mCurrentLockedBuffers--; mCurrentLockedBuffers--; } } mBufferSlot[buf] = NULL; ConsumerBase::freeBufferLocked(slotIndex); return err; } } } // namespace android } // namespace android Loading
include/gui/CpuConsumer.h +6 −47 Original line number Original line Diff line number Diff line Loading @@ -17,7 +17,7 @@ #ifndef ANDROID_GUI_CPUCONSUMER_H #ifndef ANDROID_GUI_CPUCONSUMER_H #define ANDROID_GUI_CPUCONSUMER_H #define ANDROID_GUI_CPUCONSUMER_H #include <gui/BufferQueue.h> #include <gui/ConsumerBase.h> #include <ui/GraphicBuffer.h> #include <ui/GraphicBuffer.h> Loading @@ -37,19 +37,10 @@ namespace android { * This queue is synchronous by default. * This queue is synchronous by default. */ */ class CpuConsumer: public virtual RefBase, class CpuConsumer: public ConsumerBase protected BufferQueue::ConsumerListener { { public: public: struct FrameAvailableListener : public virtual RefBase { typedef ConsumerBase::FrameAvailableListener FrameAvailableListener; // onFrameAvailable() is called each time an additional frame becomes // available for consumption. A new frame queued will always trigger the // callback, whether the queue is empty or not. // // This is called without any lock held and can be called concurrently // by multiple threads. virtual void onFrameAvailable() = 0; }; struct LockedBuffer { struct LockedBuffer { uint8_t *data; uint8_t *data; Loading @@ -68,8 +59,6 @@ class CpuConsumer: public virtual RefBase, // how many buffers can be locked for user access at the same time. // how many buffers can be locked for user access at the same time. CpuConsumer(uint32_t maxLockedBuffers); CpuConsumer(uint32_t maxLockedBuffers); virtual ~CpuConsumer(); // set the name of the CpuConsumer that will be used to identify it in // set the name of the CpuConsumer that will be used to identify it in // log messages. // log messages. void setName(const String8& name); void setName(const String8& name); Loading @@ -91,50 +80,20 @@ class CpuConsumer: public virtual RefBase, // lockNextBuffer. // lockNextBuffer. status_t unlockBuffer(const LockedBuffer &nativeBuffer); status_t unlockBuffer(const LockedBuffer &nativeBuffer); // setFrameAvailableListener sets the listener object that will be notified sp<ISurfaceTexture> getProducerInterface() const { return getBufferQueue(); } // when a new frame becomes available. void setFrameAvailableListener(const sp<FrameAvailableListener>& listener); sp<ISurfaceTexture> getProducerInterface() const { return mBufferQueue; } protected: // Implementation of the BufferQueue::ConsumerListener interface. These // calls are used to notify the CpuConsumer of asynchronous events in the // BufferQueue. virtual void onFrameAvailable(); virtual void onBuffersReleased(); private: private: // Free local buffer state status_t freeBufferLocked(int buf); // 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; // mName is a string used to identify the SurfaceTexture in log messages. void freeBufferLocked(int slotIndex); // It can be set by the setName method. String8 mName; // mFrameAvailableListener is the listener object that will be called when a // new frame becomes available. If it is not NULL it will be called from // queueBuffer. sp<FrameAvailableListener> mFrameAvailableListener; // Underlying buffer queue sp<BufferQueue> mBufferQueue; // Array for caching buffers from the buffer queue sp<GraphicBuffer> mBufferSlot[BufferQueue::NUM_BUFFER_SLOTS]; // Array for tracking pointers passed to the consumer, matching the // Array for tracking pointers passed to the consumer, matching the // mBufferSlot indexing // mSlots indexing void *mBufferPointers[BufferQueue::NUM_BUFFER_SLOTS]; void *mBufferPointers[BufferQueue::NUM_BUFFER_SLOTS]; // Count of currently locked buffers // Count of currently locked buffers uint32_t mCurrentLockedBuffers; uint32_t mCurrentLockedBuffers; // mMutex is the mutex used to prevent concurrent access to the member // variables of CpuConsumer objects. It must be locked whenever the // member variables are accessed. mutable Mutex mMutex; }; }; } // namespace android } // namespace android Loading
libs/gui/CpuConsumer.cpp +26 −113 Original line number Original line Diff line number Diff line Loading @@ -29,49 +29,18 @@ namespace android { namespace android { // Get an ID that's unique within this process. static int32_t createProcessUniqueId() { static volatile int32_t globalCounter = 0; return android_atomic_inc(&globalCounter); } CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers) : CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers) : ConsumerBase(new BufferQueue(true, maxLockedBuffers) ), mMaxLockedBuffers(maxLockedBuffers), mMaxLockedBuffers(maxLockedBuffers), mCurrentLockedBuffers(0) mCurrentLockedBuffers(0) { { mName = String8::format("cc-unnamed-%d-%d", getpid(), createProcessUniqueId()); for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { mBufferPointers[i] = NULL; mBufferPointers[i] = NULL; } } mBufferQueue = new BufferQueue(true); wp<BufferQueue::ConsumerListener> listener; sp<BufferQueue::ConsumerListener> proxy; listener = static_cast<BufferQueue::ConsumerListener*>(this); proxy = new BufferQueue::ProxyConsumerListener(listener); status_t err = mBufferQueue->consumerConnect(proxy); if (err != NO_ERROR) { ALOGE("CpuConsumer: error connecting to BufferQueue: %s (%d)", strerror(-err), err); } else { mBufferQueue->setSynchronousMode(true); mBufferQueue->setSynchronousMode(true); mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN); mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN); mBufferQueue->setConsumerName(mName); } } CpuConsumer::~CpuConsumer() { Mutex::Autolock _l(mMutex); for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { freeBufferLocked(i); } mBufferQueue->consumerDisconnect(); mBufferQueue.clear(); } } void CpuConsumer::setName(const String8& name) { void CpuConsumer::setName(const String8& name) { Loading @@ -92,7 +61,7 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { Mutex::Autolock _l(mMutex); Mutex::Autolock _l(mMutex); err = mBufferQueue->acquireBuffer(&b); err = acquireBufferLocked(&b); if (err != OK) { if (err != OK) { if (err == BufferQueue::NO_BUFFER_AVAILABLE) { if (err == BufferQueue::NO_BUFFER_AVAILABLE) { return BAD_VALUE; return BAD_VALUE; Loading @@ -104,16 +73,6 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { int buf = b.mBuf; int buf = b.mBuf; if (b.mGraphicBuffer != NULL) { if (mBufferPointers[buf] != NULL) { CC_LOGE("Reallocation of buffer %d while in consumer use!", buf); mBufferQueue->releaseBuffer(buf, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); return BAD_VALUE; } mBufferSlot[buf] = b.mGraphicBuffer; } if (b.mFence.get()) { if (b.mFence.get()) { err = b.mFence->wait(Fence::TIMEOUT_NEVER); err = b.mFence->wait(Fence::TIMEOUT_NEVER); if (err != OK) { if (err != OK) { Loading @@ -123,7 +82,7 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { } } } } err = mBufferSlot[buf]->lock( err = mSlots[buf].mGraphicBuffer->lock( GraphicBuffer::USAGE_SW_READ_OFTEN, GraphicBuffer::USAGE_SW_READ_OFTEN, b.mCrop, b.mCrop, &mBufferPointers[buf]); &mBufferPointers[buf]); Loading @@ -135,10 +94,10 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { } } nativeBuffer->data = reinterpret_cast<uint8_t*>(mBufferPointers[buf]); nativeBuffer->data = reinterpret_cast<uint8_t*>(mBufferPointers[buf]); nativeBuffer->width = mBufferSlot[buf]->getWidth(); nativeBuffer->width = mSlots[buf].mGraphicBuffer->getWidth(); nativeBuffer->height = mBufferSlot[buf]->getHeight(); nativeBuffer->height = mSlots[buf].mGraphicBuffer->getHeight(); nativeBuffer->format = mBufferSlot[buf]->getPixelFormat(); nativeBuffer->format = mSlots[buf].mGraphicBuffer->getPixelFormat(); nativeBuffer->stride = mBufferSlot[buf]->getStride(); nativeBuffer->stride = mSlots[buf].mGraphicBuffer->getStride(); nativeBuffer->crop = b.mCrop; nativeBuffer->crop = b.mCrop; nativeBuffer->transform = b.mTransform; nativeBuffer->transform = b.mTransform; Loading @@ -153,90 +112,44 @@ 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 buf = 0; int slotIndex = 0; status_t err; status_t err; void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data); void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data); for (; buf < BufferQueue::NUM_BUFFER_SLOTS; buf++) { for (; slotIndex < BufferQueue::NUM_BUFFER_SLOTS; slotIndex++) { if (bufPtr == mBufferPointers[buf]) break; if (bufPtr == mBufferPointers[slotIndex]) break; } } if (buf == BufferQueue::NUM_BUFFER_SLOTS) { if (slotIndex == BufferQueue::NUM_BUFFER_SLOTS) { 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; } } mBufferPointers[buf] = NULL; mBufferPointers[slotIndex] = NULL; err = mBufferSlot[buf]->unlock(); err = mSlots[slotIndex].mGraphicBuffer->unlock(); if (err != OK) { if (err != OK) { CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, buf); CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, slotIndex); return err; } err = mBufferQueue->releaseBuffer(buf, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); if (err == BufferQueue::STALE_BUFFER_SLOT) { freeBufferLocked(buf); } else if (err != OK) { CC_LOGE("%s: Unable to release graphic buffer %d to queue", __FUNCTION__, buf); return err; return err; } } releaseBufferLocked(slotIndex, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); mCurrentLockedBuffers--; mCurrentLockedBuffers--; return OK; return OK; } } void CpuConsumer::setFrameAvailableListener( void CpuConsumer::freeBufferLocked(int slotIndex) { const sp<FrameAvailableListener>& listener) { if (mBufferPointers[slotIndex] != NULL) { CC_LOGV("setFrameAvailableListener"); status_t err; Mutex::Autolock lock(mMutex); CC_LOGW("Buffer %d freed while locked by consumer", slotIndex); mFrameAvailableListener = listener; mBufferPointers[slotIndex] = NULL; } err = mSlots[slotIndex].mGraphicBuffer->unlock(); void CpuConsumer::onFrameAvailable() { CC_LOGV("onFrameAvailable"); sp<FrameAvailableListener> listener; { // scope for the lock Mutex::Autolock _l(mMutex); listener = mFrameAvailableListener; } if (listener != NULL) { CC_LOGV("actually calling onFrameAvailable"); listener->onFrameAvailable(); } } void CpuConsumer::onBuffersReleased() { CC_LOGV("onBuffersReleased"); Mutex::Autolock lock(mMutex); uint32_t mask = 0; mBufferQueue->getReleasedBuffers(&mask); for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { if (mask & (1 << i)) { freeBufferLocked(i); } } } status_t CpuConsumer::freeBufferLocked(int buf) { status_t err = OK; if (mBufferPointers[buf] != NULL) { CC_LOGW("Buffer %d freed while locked by consumer", buf); mBufferPointers[buf] = NULL; err = mBufferSlot[buf]->unlock(); if (err != OK) { if (err != OK) { CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, buf); CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, slotIndex); } } mCurrentLockedBuffers--; mCurrentLockedBuffers--; } } mBufferSlot[buf] = NULL; ConsumerBase::freeBufferLocked(slotIndex); return err; } } } // namespace android } // namespace android