diff options
| -rw-r--r-- | include/gui/BufferQueue.h | 36 | ||||
| -rw-r--r-- | libs/gui/BufferQueue.cpp | 74 | ||||
| -rw-r--r-- | libs/gui/tests/Surface_test.cpp | 4 |
3 files changed, 36 insertions, 78 deletions
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h index f02e25f254..b968287cac 100644 --- a/include/gui/BufferQueue.h +++ b/include/gui/BufferQueue.h @@ -223,13 +223,13 @@ public: // public facing structure for BufferSlot struct BufferItem { - BufferItem() - : + BufferItem() : mTransform(0), mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mTimestamp(0), mFrameNumber(0), mBuf(INVALID_BUFFER_SLOT), + mDequeueBufferCannotBlock(false), mAcquireCalled(false) { mCrop.makeInvalid(); } @@ -260,6 +260,13 @@ public: // mFence is a fence that will signal when the buffer is idle. sp<Fence> mFence; + // mDequeueBufferCannotBlock whether this buffer was queued with the + // property that it can be replaced by a new buffer for the purpose of + // making sure dequeueBuffer() won't block. + // i.e.: was the BufferQueue in "mDequeueBufferCannotBlock" when this buffer + // was queued. + bool mDequeueBufferCannotBlock; + // Indicates whether this buffer has been seen by a consumer yet bool mAcquireCalled; }; @@ -366,17 +373,6 @@ private: // all slots. void freeAllBuffersLocked(); - // drainQueueLocked waits for the buffer queue to empty if we're in - // synchronous mode, or returns immediately otherwise. It returns NO_INIT - // if the BufferQueue is abandoned (consumer disconnected) or disconnected - // (producer disconnected) during the call. - status_t drainQueueLocked(); - - // drainQueueAndFreeBuffersLocked drains the buffer queue if we're in - // synchronous mode and free all buffers. In asynchronous mode, all buffers - // are freed except the currently queued buffer (if it exists). - status_t drainQueueAndFreeBuffersLocked(); - // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots // that will be used if the producer does not override the buffer slot // count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. @@ -387,15 +383,11 @@ 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 + // mDequeueBufferCannotBlock // mMaxAcquiredBufferCount // mDefaultMaxBufferCount // mOverrideMaxBufferCount @@ -524,6 +516,11 @@ private: // in dequeueBuffer() if a width and height of zero is specified. uint32_t mDefaultHeight; + // mMinUndequeuedBufferCount holds the minimum number of buffers + // that must remain in a state other than DEQUEUED. + // This value cannot change while connected. + int mMinUndequeuedBufferCount; + // 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 @@ -564,9 +561,6 @@ private: // by the application. bool mDequeueBufferCannotBlock; - // mSynchronousMode whether we're in synchronous mode or not - bool mSynchronousMode; - // mConnectedApi indicates the producer API that is currently connected // to this BufferQueue. It defaults to NO_CONNECTED_API (= 0), and gets // updated by the connect and disconnect methods. diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index 1e86a4f3df..f99bd29bd5 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -71,7 +71,6 @@ BufferQueue::BufferQueue(const sp<IGraphicBufferAlloc>& allocator) : mOverrideMaxBufferCount(0), mConsumerControlledByApp(false), mDequeueBufferCannotBlock(false), - mSynchronousMode(true), mConnectedApi(NO_CONNECTED_API), mAbandoned(false), mFrameCounter(0), @@ -210,7 +209,7 @@ int BufferQueue::query(int what, int* outValue) value = mDefaultBufferFormat; break; case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: - value = getMinUndequeuedBufferCountLocked(); + value = mMinUndequeuedBufferCount; break; case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: value = (mQueue.size() >= 2); @@ -329,7 +328,7 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, // make sure the client is not trying to dequeue more buffers // than allowed. const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1); - const int minUndequeuedCount = getMinUndequeuedBufferCountLocked(); + const int minUndequeuedCount = mMinUndequeuedBufferCount; if (newUndequeuedCount < minUndequeuedCount) { ST_LOGE("dequeueBuffer: min undequeued buffer count (%d) " "exceeded (dequeued=%d undequeudCount=%d)", @@ -524,31 +523,27 @@ status_t BufferQueue::queueBuffer(int buf, item.mFrameNumber = mFrameCounter; item.mBuf = buf; item.mFence = fence; + item.mDequeueBufferCannotBlock = mDequeueBufferCannotBlock; - if (mSynchronousMode) { - // In synchronous mode we queue all buffers in a FIFO. + if (mQueue.empty()) { + // when the queue is empty, we can ignore "mDequeueBufferCannotBlock", and + // simply queue this buffer. mQueue.push_back(item); - - // Synchronous mode always signals that an additional frame should - // be consumed. listener = mConsumerListener; } else { - // In asynchronous mode we only keep the most recent buffer. - if (mQueue.empty()) { - mQueue.push_back(item); - - // Asynchronous mode only signals that a frame should be - // consumed if no previous frame was pending. If a frame were - // pending then the consumer would have already been notified. - listener = mConsumerListener; - } else { - Fifo::iterator front(mQueue.begin()); + // when the queue is not empty, we need to look at the front buffer + // state and see if we need to replace it. + Fifo::iterator front(mQueue.begin()); + if (front->mDequeueBufferCannotBlock) { // buffer slot currently queued is marked free if still tracked if (stillTracking(front)) { mSlots[front->mBuf].mBufferState = BufferSlot::FREE; } - // and we record the new buffer index in the queued list + // and we record the new buffer in the queued list *front = item; + } else { + mQueue.push_back(item); + listener = mConsumerListener; } } @@ -635,7 +630,8 @@ status_t BufferQueue::connect(int api, bool producerControlledByApp, QueueBuffer mBufferHasBeenQueued = false; mDequeueBufferCannotBlock = mConsumerControlledByApp && producerControlledByApp; - mSynchronousMode = !mDequeueBufferCannotBlock; + mMinUndequeuedBufferCount = mDequeueBufferCannotBlock ? + mMaxAcquiredBufferCount+1 : mMaxAcquiredBufferCount; return err; } @@ -662,7 +658,7 @@ status_t BufferQueue::disconnect(int api) { case NATIVE_WINDOW_API_MEDIA: case NATIVE_WINDOW_API_CAMERA: if (mConnectedApi == api) { - drainQueueAndFreeBuffersLocked(); + freeAllBuffersLocked(); mConnectedApi = NO_CONNECTED_API; mDequeueCondition.broadcast(); listener = mConsumerListener; @@ -711,9 +707,9 @@ void BufferQueue::dump(String8& result, const char* prefix) const { int maxBufferCount = getMaxBufferCountLocked(); result.appendFormat( - "%s-BufferQueue maxBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], " + "%s-BufferQueue maxBufferCount=%d, mDequeueBufferCannotBlock=%d, default-size=[%dx%d], " "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n", - prefix, maxBufferCount, mSynchronousMode, mDefaultWidth, + prefix, maxBufferCount, mDequeueBufferCannotBlock, mDefaultWidth, mDefaultHeight, mDefaultBufferFormat, mTransformHint, fifoSize, fifo.string()); @@ -768,8 +764,6 @@ void BufferQueue::freeBufferLocked(int slot) { } void BufferQueue::freeAllBuffersLocked() { - ALOGD_IF(!mQueue.isEmpty(), - "freeAllBuffersLocked called with non-empty mQueue"); mBufferHasBeenQueued = false; for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { freeBufferLocked(i); @@ -1024,36 +1018,8 @@ status_t BufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) { return NO_ERROR; } -status_t BufferQueue::drainQueueLocked() { - while (mSynchronousMode && mQueue.size() > 1) { - mDequeueCondition.wait(mMutex); - if (mAbandoned) { - ST_LOGE("drainQueueLocked: BufferQueue has been abandoned!"); - return NO_INIT; - } - if (mConnectedApi == NO_CONNECTED_API) { - ST_LOGE("drainQueueLocked: BufferQueue is not connected!"); - return NO_INIT; - } - } - return NO_ERROR; -} - -status_t BufferQueue::drainQueueAndFreeBuffersLocked() { - status_t err = drainQueueLocked(); - if (err == NO_ERROR) { - freeAllBuffersLocked(); - } - return err; -} - int BufferQueue::getMinMaxBufferCountLocked() const { - return getMinUndequeuedBufferCountLocked() + 1; -} - -int BufferQueue::getMinUndequeuedBufferCountLocked() const { - return mSynchronousMode ? mMaxAcquiredBufferCount : - mMaxAcquiredBufferCount + 1; + return mMinUndequeuedBufferCount + 1; } int BufferQueue::getMaxBufferCountLocked() const { diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index c55b02aa21..953f6f91dc 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -83,9 +83,7 @@ TEST_F(SurfaceTest, QueuesToWindowComposerIsTrueWhenPurgatorized) { } // This test probably doesn't belong here. -// DISABLED because it hangs when disconnecting because of draining the queue. -// will be fixed in a subsequent BQ change -TEST_F(SurfaceTest, DISABLED_ScreenshotsOfProtectedBuffersSucceed) { +TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) { sp<ANativeWindow> anw(mSurface); // Verify the screenshot works with no protected buffers. |