diff --git a/include/gui/CpuConsumer.h b/include/gui/CpuConsumer.h index a50a1debc..49c90db48 100644 --- a/include/gui/CpuConsumer.h +++ b/include/gui/CpuConsumer.h @@ -17,7 +17,7 @@ #ifndef ANDROID_GUI_CPUCONSUMER_H #define ANDROID_GUI_CPUCONSUMER_H -#include +#include #include @@ -37,19 +37,10 @@ namespace android { * This queue is synchronous by default. */ -class CpuConsumer: public virtual RefBase, - protected BufferQueue::ConsumerListener +class CpuConsumer: public ConsumerBase { public: - struct FrameAvailableListener : public virtual RefBase { - // 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; - }; + typedef ConsumerBase::FrameAvailableListener FrameAvailableListener; struct LockedBuffer { uint8_t *data; @@ -68,8 +59,6 @@ class CpuConsumer: public virtual RefBase, // how many buffers can be locked for user access at the same time. CpuConsumer(uint32_t maxLockedBuffers); - virtual ~CpuConsumer(); - // set the name of the CpuConsumer that will be used to identify it in // log messages. void setName(const String8& name); @@ -91,50 +80,20 @@ class CpuConsumer: public virtual RefBase, // lockNextBuffer. status_t unlockBuffer(const LockedBuffer &nativeBuffer); - // setFrameAvailableListener sets the listener object that will be notified - // when a new frame becomes available. - void setFrameAvailableListener(const sp& listener); - - sp 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(); + sp getProducerInterface() const { return getBufferQueue(); } private: - // Free local buffer state - status_t freeBufferLocked(int buf); - // Maximum number of buffers that can be locked at a time uint32_t mMaxLockedBuffers; - // mName is a string used to identify the SurfaceTexture in log messages. - // It can be set by the setName method. - String8 mName; + void freeBufferLocked(int slotIndex); - // 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 mFrameAvailableListener; - - // Underlying buffer queue - sp mBufferQueue; - - // Array for caching buffers from the buffer queue - sp mBufferSlot[BufferQueue::NUM_BUFFER_SLOTS]; // Array for tracking pointers passed to the consumer, matching the - // mBufferSlot indexing + // mSlots indexing void *mBufferPointers[BufferQueue::NUM_BUFFER_SLOTS]; // Count of currently locked buffers 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 diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp index 513828c37..90c8ea64b 100644 --- a/libs/gui/CpuConsumer.cpp +++ b/libs/gui/CpuConsumer.cpp @@ -29,49 +29,18 @@ 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) : + ConsumerBase(new BufferQueue(true, maxLockedBuffers) ), mMaxLockedBuffers(maxLockedBuffers), mCurrentLockedBuffers(0) { - mName = String8::format("cc-unnamed-%d-%d", getpid(), - createProcessUniqueId()); for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { mBufferPointers[i] = NULL; } - mBufferQueue = new BufferQueue(true); - - wp listener; - sp proxy; - listener = static_cast(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->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(); + mBufferQueue->setSynchronousMode(true); + mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN); } void CpuConsumer::setName(const String8& name) { @@ -92,7 +61,7 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { Mutex::Autolock _l(mMutex); - err = mBufferQueue->acquireBuffer(&b); + err = acquireBufferLocked(&b); if (err != OK) { if (err == BufferQueue::NO_BUFFER_AVAILABLE) { return BAD_VALUE; @@ -104,16 +73,6 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { 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()) { err = b.mFence->wait(Fence::TIMEOUT_NEVER); if (err != OK) { @@ -123,7 +82,7 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { } } - err = mBufferSlot[buf]->lock( + err = mSlots[buf].mGraphicBuffer->lock( GraphicBuffer::USAGE_SW_READ_OFTEN, b.mCrop, &mBufferPointers[buf]); @@ -135,10 +94,10 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { } nativeBuffer->data = reinterpret_cast(mBufferPointers[buf]); - nativeBuffer->width = mBufferSlot[buf]->getWidth(); - nativeBuffer->height = mBufferSlot[buf]->getHeight(); - nativeBuffer->format = mBufferSlot[buf]->getPixelFormat(); - nativeBuffer->stride = mBufferSlot[buf]->getStride(); + nativeBuffer->width = mSlots[buf].mGraphicBuffer->getWidth(); + nativeBuffer->height = mSlots[buf].mGraphicBuffer->getHeight(); + nativeBuffer->format = mSlots[buf].mGraphicBuffer->getPixelFormat(); + nativeBuffer->stride = mSlots[buf].mGraphicBuffer->getStride(); nativeBuffer->crop = b.mCrop; nativeBuffer->transform = b.mTransform; @@ -153,90 +112,44 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) { status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) { Mutex::Autolock _l(mMutex); - int buf = 0; + int slotIndex = 0; status_t err; void *bufPtr = reinterpret_cast(nativeBuffer.data); - for (; buf < BufferQueue::NUM_BUFFER_SLOTS; buf++) { - if (bufPtr == mBufferPointers[buf]) break; + for (; slotIndex < BufferQueue::NUM_BUFFER_SLOTS; slotIndex++) { + 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__); return BAD_VALUE; } - mBufferPointers[buf] = NULL; - err = mBufferSlot[buf]->unlock(); + mBufferPointers[slotIndex] = NULL; + err = mSlots[slotIndex].mGraphicBuffer->unlock(); if (err != OK) { - CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, buf); - 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); + CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, slotIndex); return err; } + releaseBufferLocked(slotIndex, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); mCurrentLockedBuffers--; return OK; } -void CpuConsumer::setFrameAvailableListener( - const sp& listener) { - CC_LOGV("setFrameAvailableListener"); - Mutex::Autolock lock(mMutex); - mFrameAvailableListener = listener; -} - - -void CpuConsumer::onFrameAvailable() { - CC_LOGV("onFrameAvailable"); - sp 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(); +void CpuConsumer::freeBufferLocked(int slotIndex) { + if (mBufferPointers[slotIndex] != NULL) { + status_t err; + CC_LOGW("Buffer %d freed while locked by consumer", slotIndex); + mBufferPointers[slotIndex] = NULL; + err = mSlots[slotIndex].mGraphicBuffer->unlock(); 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--; } - mBufferSlot[buf] = NULL; - return err; + ConsumerBase::freeBufferLocked(slotIndex); } } // namespace android