diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h index 5b68b05a5..0a95bb3db 100644 --- a/include/gui/BufferQueue.h +++ b/include/gui/BufferQueue.h @@ -92,13 +92,11 @@ public: }; - // BufferQueue manages a pool of gralloc memory slots to be used - // by producers and consumers. - // allowSynchronousMode specifies whether or not synchronous mode can be - // enabled. - // bufferCount sets the minimum number of undequeued buffers for this queue + // BufferQueue manages a pool of gralloc memory slots to be used by + // producers and consumers. allowSynchronousMode specifies whether or not + // synchronous mode can be enabled by the producer. allocator is used to + // allocate all the needed gralloc buffers. BufferQueue(bool allowSynchronousMode = true, - int bufferCount = MIN_UNDEQUEUED_BUFFERS, const sp& allocator = NULL); virtual ~BufferQueue(); @@ -257,6 +255,11 @@ public: // take effect once the client sets the count back to zero. status_t setDefaultMaxBufferCount(int bufferCount); + // setMaxAcquiredBufferCount sets the maximum number of buffers that can + // be acquired by the consumer at one time. This call will fail if a + // producer is connected to the BufferQueue. + status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers); + // isSynchronousMode returns whether the SurfaceTexture is currently in // synchronous mode. bool isSynchronousMode() const; @@ -307,12 +310,16 @@ private: // given the current BufferQueue state. int getMinMaxBufferCountLocked() const; + // getMinUndequeuedBufferCountLocked returns the minimum number of buffers + // that must remain in a state other than DEQUEUED. + int getMinUndequeuedBufferCountLocked() const; + // getMaxBufferCountLocked returns the maximum number of buffers that can // be allocated at once. This value depends upon the following member // variables: // // mSynchronousMode - // mMinUndequeuedBuffers + // mMaxAcquiredBufferCount // mDefaultMaxBufferCount // mOverrideMaxBufferCount // @@ -442,9 +449,14 @@ private: // in requestBuffers() if a width and height of zero is specified. uint32_t mDefaultHeight; - // mMinUndequeuedBuffers is a constraint on the number of buffers - // not dequeued at any time - int mMinUndequeuedBuffers; + // mMaxAcquiredBufferCount is the number of buffers that the consumer may + // acquire at one time. It defaults to 1 and can be changed by the + // consumer via the setMaxAcquiredBufferCount method, but this may only be + // done when no producer is connected to the BufferQueue. + // + // This value is used to derive the value returned for the + // MIN_UNDEQUEUED_BUFFERS query by the producer. + int mMaxAcquiredBufferCount; // mDefaultMaxBufferCount is the default limit on the number of buffers // that will be allocated at one time. This default limit is set by the diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp index 218d92973..57df39c74 100644 --- a/libs/gui/BufferItemConsumer.cpp +++ b/libs/gui/BufferItemConsumer.cpp @@ -31,10 +31,11 @@ namespace android { BufferItemConsumer::BufferItemConsumer(uint32_t consumerUsage, int bufferCount, bool synchronousMode) : - ConsumerBase(new BufferQueue(true, bufferCount) ) + ConsumerBase(new BufferQueue(true) ) { mBufferQueue->setConsumerUsageBits(consumerUsage); mBufferQueue->setSynchronousMode(synchronousMode); + mBufferQueue->setMaxAcquiredBufferCount(bufferCount); } BufferItemConsumer::~BufferItemConsumer() { diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index 6689e84af..db021ff69 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -81,12 +81,12 @@ static const char* scalingModeName(int scalingMode) { } } -BufferQueue::BufferQueue(bool allowSynchronousMode, int bufferCount, +BufferQueue::BufferQueue(bool allowSynchronousMode, const sp& allocator) : mDefaultWidth(1), mDefaultHeight(1), - mMinUndequeuedBuffers(bufferCount), - mDefaultMaxBufferCount(bufferCount + 1), + mMaxAcquiredBufferCount(1), + mDefaultMaxBufferCount(2), mOverrideMaxBufferCount(0), mSynchronousMode(false), mAllowSynchronousMode(allowSynchronousMode), @@ -233,8 +233,7 @@ int BufferQueue::query(int what, int* outValue) value = mDefaultBufferFormat; break; case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: - value = mSynchronousMode ? - (mMinUndequeuedBuffers-1) : mMinUndequeuedBuffers; + value = getMinUndequeuedBufferCountLocked(); break; case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: value = (mQueue.size() >= 2); @@ -356,17 +355,18 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp& outFence, } // See whether a buffer has been queued since the last - // setBufferCount so we know whether to perform the - // mMinUndequeuedBuffers check below. + // setBufferCount so we know whether to perform the min undequeued + // buffers check below. if (mBufferHasBeenQueued) { // make sure the client is not trying to dequeue more buffers // than allowed. - const int avail = maxBufferCount - (dequeuedCount+1); - if (avail < (mMinUndequeuedBuffers-int(mSynchronousMode))) { - ST_LOGE("dequeueBuffer: mMinUndequeuedBuffers=%d exceeded " - "(dequeued=%d)", - mMinUndequeuedBuffers-int(mSynchronousMode), - dequeuedCount); + const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1); + const int minUndequeuedCount = getMinUndequeuedBufferCountLocked(); + if (newUndequeuedCount < minUndequeuedCount) { + ST_LOGE("dequeueBuffer: min undequeued buffer count (%d) " + "exceeded (dequeued=%d undequeudCount=%d)", + minUndequeuedCount, dequeuedCount, + newUndequeuedCount); return -EBUSY; } } @@ -954,6 +954,16 @@ status_t BufferQueue::setDefaultMaxBufferCount(int bufferCount) { return setDefaultMaxBufferCountLocked(bufferCount); } +status_t BufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) { + ATRACE_CALL(); + Mutex::Autolock lock(mMutex); + if (mConnectedApi != NO_CONNECTED_API) { + return INVALID_OPERATION; + } + mMaxAcquiredBufferCount = maxAcquiredBuffers; + return OK; +} + void BufferQueue::freeAllBuffersExceptHeadLocked() { int head = -1; if (!mQueue.empty()) { @@ -996,7 +1006,12 @@ status_t BufferQueue::drainQueueAndFreeBuffersLocked() { } int BufferQueue::getMinMaxBufferCountLocked() const { - return mSynchronousMode ? mMinUndequeuedBuffers : mMinUndequeuedBuffers + 1; + return getMinUndequeuedBufferCountLocked() + 1; +} + +int BufferQueue::getMinUndequeuedBufferCountLocked() const { + return mSynchronousMode ? mMaxAcquiredBufferCount : + mMaxAcquiredBufferCount + 1; } int BufferQueue::getMaxBufferCountLocked() const { diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp index 242ac45d3..fc4a85493 100644 --- a/libs/gui/CpuConsumer.cpp +++ b/libs/gui/CpuConsumer.cpp @@ -30,7 +30,7 @@ namespace android { CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers) : - ConsumerBase(new BufferQueue(true, maxLockedBuffers) ), + ConsumerBase(new BufferQueue(true) ), mMaxLockedBuffers(maxLockedBuffers), mCurrentLockedBuffers(0) { @@ -41,6 +41,7 @@ CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers) : mBufferQueue->setSynchronousMode(true); mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN); + mBufferQueue->setMaxAcquiredBufferCount(maxLockedBuffers); } CpuConsumer::~CpuConsumer() { diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index d601fca38..7fb1159bf 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -67,8 +67,7 @@ public: */ FramebufferSurface::FramebufferSurface(): - ConsumerBase(new BufferQueue(true, NUM_FRAME_BUFFERS, - new GraphicBufferAlloc())), + ConsumerBase(new BufferQueue(true, new GraphicBufferAlloc())), fbDev(0), mCurrentBufferSlot(-1), mCurrentBuffer(0)