BQ: Improved buffer/slot tracking
- Explicitly track active buffers and unused slots on top of the
already existing tracking for free slots and free buffers.
Change-Id: Ife2678678e96f0eb0b3fb21571058378134bd868
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 6f9f21f..d182f6b 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -49,7 +49,7 @@
// buffer so that the consumer can successfully set up the newly acquired
// buffer before releasing the old one.
int numAcquiredBuffers = 0;
- for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
+ for (int s : mCore->mActiveBuffers) {
if (mSlots[s].mBufferState.isAcquired()) {
++numAcquiredBuffers;
}
@@ -133,7 +133,8 @@
BQ_LOGV("acquireBuffer: drop desire=%" PRId64 " expect=%" PRId64
" size=%zu",
desiredPresent, expectedPresent, mCore->mQueue.size());
- if (mCore->stillTracking(front)) {
+
+ if (!front->mIsStale) {
// Front buffer is still in mSlots, so mark the slot as free
mSlots[front->mSlot].mBufferState.freeQueued();
@@ -144,13 +145,17 @@
mSlots[front->mSlot].mBufferState.isFree()) {
mSlots[front->mSlot].mBufferState.mShared = false;
}
- // Don't put the shared buffer on the free list.
+
+ // Don't put the shared buffer on the free list
if (!mSlots[front->mSlot].mBufferState.isShared()) {
+ mCore->mActiveBuffers.erase(front->mSlot);
mCore->mFreeBuffers.push_back(front->mSlot);
}
+
listener = mCore->mConnectedProducerListener;
++numDroppedBuffers;
}
+
mCore->mQueue.erase(front);
front = mCore->mQueue.begin();
}
@@ -205,6 +210,7 @@
outBuffer->mSurfaceDamage = Region::INVALID_REGION;
outBuffer->mSingleBufferMode = true;
outBuffer->mQueuedBuffer = false;
+ outBuffer->mIsStale = false;
} else {
slot = front->mSlot;
*outBuffer = *front;
@@ -216,10 +222,9 @@
BQ_LOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }",
slot, outBuffer->mFrameNumber, outBuffer->mGraphicBuffer->handle);
- // If the front buffer is still being tracked, update its slot state
- if (mCore->stillTracking(outBuffer)) {
+
+ if (!outBuffer->mIsStale) {
mSlots[slot].mAcquireCalled = true;
- mSlots[slot].mNeedsCleanupOnRelease = false;
// Don't decrease the queue count if the BufferItem wasn't
// previously in the queue. This happens in single buffer mode when
// the queue is empty and the BufferItem is created above.
@@ -270,7 +275,7 @@
return NO_INIT;
}
- if (mCore->mSingleBufferMode) {
+ if (mCore->mSingleBufferMode || slot == mCore->mSingleBufferSlot) {
BQ_LOGE("detachBuffer: detachBuffer not allowed in single buffer"
"mode");
return BAD_VALUE;
@@ -287,7 +292,9 @@
}
mSlots[slot].mBufferState.detachConsumer();
- mCore->freeBufferLocked(slot);
+ mCore->mActiveBuffers.erase(slot);
+ mCore->mFreeSlots.insert(slot);
+ mCore->clearBufferSlotLocked(slot);
mCore->mDequeueCondition.broadcast();
mCore->validateConsistencyLocked();
@@ -316,7 +323,7 @@
// Make sure we don't have too many acquired buffers
int numAcquiredBuffers = 0;
- for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
+ for (int s : mCore->mActiveBuffers) {
if (mSlots[s].mBufferState.isAcquired()) {
++numAcquiredBuffers;
}
@@ -351,14 +358,14 @@
return NO_MEMORY;
}
+ mCore->mActiveBuffers.insert(found);
*outSlot = found;
ATRACE_BUFFER_INDEX(*outSlot);
BQ_LOGV("attachBuffer: returning slot %d", *outSlot);
mSlots[*outSlot].mGraphicBuffer = buffer;
mSlots[*outSlot].mBufferState.attachConsumer();
- mSlots[*outSlot].mAttachedByConsumer = true;
- mSlots[*outSlot].mNeedsCleanupOnRelease = false;
+ mSlots[*outSlot].mNeedsReallocation = true;
mSlots[*outSlot].mFence = Fence::NO_FENCE;
mSlots[*outSlot].mFrameNumber = 0;
@@ -411,39 +418,33 @@
return STALE_BUFFER_SLOT;
}
-
- if (mSlots[slot].mBufferState.isAcquired()) {
- mSlots[slot].mEglDisplay = eglDisplay;
- mSlots[slot].mEglFence = eglFence;
- mSlots[slot].mFence = releaseFence;
- mSlots[slot].mBufferState.release();
-
- // After leaving single buffer mode, the shared buffer will
- // still be around. Mark it as no longer shared if this
- // operation causes it to be free.
- if (!mCore->mSingleBufferMode &&
- mSlots[slot].mBufferState.isFree()) {
- mSlots[slot].mBufferState.mShared = false;
- }
- // Don't put the shared buffer on the free list.
- if (!mSlots[slot].mBufferState.isShared()) {
- mCore->mFreeBuffers.push_back(slot);
- }
-
- listener = mCore->mConnectedProducerListener;
- BQ_LOGV("releaseBuffer: releasing slot %d", slot);
- } else if (mSlots[slot].mNeedsCleanupOnRelease) {
- BQ_LOGV("releaseBuffer: releasing a stale buffer slot %d "
- "(state = %s)", slot, mSlots[slot].mBufferState.string());
- mSlots[slot].mNeedsCleanupOnRelease = false;
- return STALE_BUFFER_SLOT;
- } else {
+ if (!mSlots[slot].mBufferState.isAcquired()) {
BQ_LOGE("releaseBuffer: attempted to release buffer slot %d "
"but its state was %s", slot,
mSlots[slot].mBufferState.string());
return BAD_VALUE;
}
+ mSlots[slot].mEglDisplay = eglDisplay;
+ mSlots[slot].mEglFence = eglFence;
+ mSlots[slot].mFence = releaseFence;
+ mSlots[slot].mBufferState.release();
+
+ // After leaving single buffer mode, the shared buffer will
+ // still be around. Mark it as no longer shared if this
+ // operation causes it to be free.
+ if (!mCore->mSingleBufferMode && mSlots[slot].mBufferState.isFree()) {
+ mSlots[slot].mBufferState.mShared = false;
+ }
+ // Don't put the shared buffer on the free list.
+ if (!mSlots[slot].mBufferState.isShared()) {
+ mCore->mActiveBuffers.erase(slot);
+ mCore->mFreeBuffers.push_back(slot);
+ }
+
+ listener = mCore->mConnectedProducerListener;
+ BQ_LOGV("releaseBuffer: releasing slot %d", slot);
+
mCore->mDequeueCondition.broadcast();
mCore->validateConsistencyLocked();
} // Autolock scope
@@ -497,6 +498,7 @@
mCore->mConsumerListener = NULL;
mCore->mQueue.clear();
mCore->freeAllBuffersLocked();
+ mCore->mSingleBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
mCore->mDequeueCondition.broadcast();
return NO_ERROR;
}
@@ -579,6 +581,15 @@
return BAD_VALUE;
}
+ int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
+ mCore->mDequeueBufferCannotBlock, bufferCount) -
+ mCore->getMaxBufferCountLocked();
+ if (!mCore->adjustAvailableSlotsLocked(delta)) {
+ BQ_LOGE("setMaxBufferCount: BufferQueue failed to adjust the number of "
+ "available slots. Delta = %d", delta);
+ return BAD_VALUE;
+ }
+
mCore->mMaxBufferCount = bufferCount;
return NO_ERROR;
}
@@ -612,8 +623,17 @@
return BAD_VALUE;
}
+ if (!mCore->adjustAvailableSlotsLocked(
+ maxAcquiredBuffers - mCore->mMaxAcquiredBufferCount)) {
+ BQ_LOGE("setMaxAcquiredBufferCount: BufferQueue failed to adjust the "
+ "number of available slots. Delta = %d",
+ maxAcquiredBuffers - mCore->mMaxAcquiredBufferCount);
+ return BAD_VALUE;
+ }
+
BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers);
mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
+ mCore->validateConsistencyLocked();
return NO_ERROR;
}