Merge "BufferQueue: simplify max buffer count handling" into jb-mr1-dev
This commit is contained in:
commit
1847f7fd79
|
@ -307,6 +307,19 @@ private:
|
||||||
// given the current BufferQueue state.
|
// given the current BufferQueue state.
|
||||||
int getMinMaxBufferCountLocked() const;
|
int getMinMaxBufferCountLocked() const;
|
||||||
|
|
||||||
|
// getMaxBufferCountLocked returns the maximum number of buffers that can
|
||||||
|
// be allocated at once. This value depends upon the following member
|
||||||
|
// variables:
|
||||||
|
//
|
||||||
|
// mSynchronousMode
|
||||||
|
// mMinUndequeuedBuffers
|
||||||
|
// mDefaultMaxBufferCount
|
||||||
|
// mOverrideMaxBufferCount
|
||||||
|
//
|
||||||
|
// Any time one of these member variables is changed while a producer is
|
||||||
|
// connected, mDequeueCondition must be broadcast.
|
||||||
|
int getMaxBufferCountLocked() const;
|
||||||
|
|
||||||
struct BufferSlot {
|
struct BufferSlot {
|
||||||
|
|
||||||
BufferSlot()
|
BufferSlot()
|
||||||
|
@ -433,10 +446,6 @@ private:
|
||||||
// not dequeued at any time
|
// not dequeued at any time
|
||||||
int mMinUndequeuedBuffers;
|
int mMinUndequeuedBuffers;
|
||||||
|
|
||||||
// mMaxBufferCount is the maximum number of buffers that will be allocated
|
|
||||||
// at once.
|
|
||||||
int mMaxBufferCount;
|
|
||||||
|
|
||||||
// mDefaultMaxBufferCount is the default limit on the number of buffers
|
// mDefaultMaxBufferCount is the default limit on the number of buffers
|
||||||
// that will be allocated at one time. This default limit is set by the
|
// that will be allocated at one time. This default limit is set by the
|
||||||
// consumer. The limit (as opposed to the default limit) may be
|
// consumer. The limit (as opposed to the default limit) may be
|
||||||
|
|
|
@ -86,7 +86,6 @@ BufferQueue::BufferQueue(bool allowSynchronousMode, int bufferCount,
|
||||||
mDefaultWidth(1),
|
mDefaultWidth(1),
|
||||||
mDefaultHeight(1),
|
mDefaultHeight(1),
|
||||||
mMinUndequeuedBuffers(bufferCount),
|
mMinUndequeuedBuffers(bufferCount),
|
||||||
mMaxBufferCount(bufferCount + 1),
|
|
||||||
mDefaultMaxBufferCount(bufferCount + 1),
|
mDefaultMaxBufferCount(bufferCount + 1),
|
||||||
mOverrideMaxBufferCount(0),
|
mOverrideMaxBufferCount(0),
|
||||||
mSynchronousMode(false),
|
mSynchronousMode(false),
|
||||||
|
@ -119,37 +118,12 @@ BufferQueue::~BufferQueue() {
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t BufferQueue::setDefaultMaxBufferCountLocked(int count) {
|
status_t BufferQueue::setDefaultMaxBufferCountLocked(int count) {
|
||||||
if (count > NUM_BUFFER_SLOTS)
|
if (count < 2 || count > NUM_BUFFER_SLOTS)
|
||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
|
|
||||||
mDefaultMaxBufferCount = count;
|
mDefaultMaxBufferCount = count;
|
||||||
|
mDequeueCondition.broadcast();
|
||||||
|
|
||||||
if (count == mMaxBufferCount)
|
|
||||||
return OK;
|
|
||||||
|
|
||||||
if (!mOverrideMaxBufferCount &&
|
|
||||||
count >= mMaxBufferCount) {
|
|
||||||
// easy, we just have more buffers
|
|
||||||
mMaxBufferCount = count;
|
|
||||||
mDequeueCondition.broadcast();
|
|
||||||
} else {
|
|
||||||
// we're here because we're either
|
|
||||||
// - reducing the number of available buffers
|
|
||||||
// - or there is a client-buffer-count in effect
|
|
||||||
|
|
||||||
// less than 2 buffers is never allowed
|
|
||||||
if (count < 2)
|
|
||||||
return BAD_VALUE;
|
|
||||||
|
|
||||||
// When there is no client-buffer-count in effect, the client is not
|
|
||||||
// allowed to dequeue more than one buffer at a time, so the next time
|
|
||||||
// they dequeue a buffer, we know that they don't own one. the actual
|
|
||||||
// resizing will happen during the next dequeueBuffer.
|
|
||||||
|
|
||||||
// We signal this condition in case there is already a blocked
|
|
||||||
// dequeueBuffer call.
|
|
||||||
mDequeueCondition.broadcast();
|
|
||||||
}
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +172,8 @@ status_t BufferQueue::setBufferCount(int bufferCount) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error out if the user has dequeued buffers
|
// Error out if the user has dequeued buffers
|
||||||
for (int i=0 ; i<mMaxBufferCount ; i++) {
|
int maxBufferCount = getMaxBufferCountLocked();
|
||||||
|
for (int i=0 ; i<maxBufferCount; i++) {
|
||||||
if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
|
if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
|
||||||
ST_LOGE("setBufferCount: client owns some buffers");
|
ST_LOGE("setBufferCount: client owns some buffers");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -208,9 +183,8 @@ status_t BufferQueue::setBufferCount(int bufferCount) {
|
||||||
const int minBufferSlots = getMinMaxBufferCountLocked();
|
const int minBufferSlots = getMinMaxBufferCountLocked();
|
||||||
if (bufferCount == 0) {
|
if (bufferCount == 0) {
|
||||||
mOverrideMaxBufferCount = 0;
|
mOverrideMaxBufferCount = 0;
|
||||||
bufferCount = (mDefaultMaxBufferCount >= minBufferSlots) ?
|
mDequeueCondition.broadcast();
|
||||||
mDefaultMaxBufferCount : minBufferSlots;
|
return OK;
|
||||||
return setDefaultMaxBufferCountLocked(bufferCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bufferCount < minBufferSlots) {
|
if (bufferCount < minBufferSlots) {
|
||||||
|
@ -221,11 +195,11 @@ status_t BufferQueue::setBufferCount(int bufferCount) {
|
||||||
|
|
||||||
// here we're guaranteed that the client doesn't have dequeued buffers
|
// here we're guaranteed that the client doesn't have dequeued buffers
|
||||||
// and will release all of its buffer references.
|
// and will release all of its buffer references.
|
||||||
|
//
|
||||||
|
// XXX: Should this use drainQueueAndFreeBuffersLocked instead?
|
||||||
freeAllBuffersLocked();
|
freeAllBuffersLocked();
|
||||||
mMaxBufferCount = bufferCount;
|
|
||||||
mOverrideMaxBufferCount = bufferCount;
|
mOverrideMaxBufferCount = bufferCount;
|
||||||
mBufferHasBeenQueued = false;
|
mBufferHasBeenQueued = false;
|
||||||
mQueue.clear();
|
|
||||||
mDequeueCondition.broadcast();
|
mDequeueCondition.broadcast();
|
||||||
listener = mConsumerListener;
|
listener = mConsumerListener;
|
||||||
} // scope for lock
|
} // scope for lock
|
||||||
|
@ -280,9 +254,17 @@ status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
|
||||||
ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!");
|
ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!");
|
||||||
return NO_INIT;
|
return NO_INIT;
|
||||||
}
|
}
|
||||||
if (slot < 0 || mMaxBufferCount <= slot) {
|
int maxBufferCount = getMaxBufferCountLocked();
|
||||||
|
if (slot < 0 || maxBufferCount <= slot) {
|
||||||
ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
|
ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
|
||||||
mMaxBufferCount, slot);
|
maxBufferCount, slot);
|
||||||
|
return BAD_VALUE;
|
||||||
|
} else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
|
||||||
|
// XXX: I vaguely recall there was some reason this can be valid, but
|
||||||
|
// for the life of me I can't recall under what circumstances that's
|
||||||
|
// the case.
|
||||||
|
ST_LOGE("requestBuffer: slot %d is not owned by the client (state=%d)",
|
||||||
|
slot, mSlots[slot].mBufferState);
|
||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
}
|
}
|
||||||
mSlots[slot].mRequestBufferCalled = true;
|
mSlots[slot].mRequestBufferCalled = true;
|
||||||
|
@ -322,49 +304,22 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence,
|
||||||
return NO_INIT;
|
return NO_INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to wait for the FIFO to drain if the number of buffer
|
const int maxBufferCount = getMaxBufferCountLocked();
|
||||||
// needs to change.
|
|
||||||
//
|
|
||||||
// The condition "number of buffers needs to change" is true if
|
|
||||||
// - the client doesn't care about how many buffers there are
|
|
||||||
// - AND the actual number of buffer is different from what was
|
|
||||||
// set in the last setDefaultMaxBufferCount()
|
|
||||||
// - OR -
|
|
||||||
// setDefaultMaxBufferCount() was set to a value incompatible with
|
|
||||||
// the synchronization mode (for instance because the sync mode
|
|
||||||
// changed since)
|
|
||||||
//
|
|
||||||
// As long as this condition is true AND the FIFO is not empty, we
|
|
||||||
// wait on mDequeueCondition.
|
|
||||||
|
|
||||||
const int minBufferCountNeeded = getMinMaxBufferCountLocked();
|
// Free up any buffers that are in slots beyond the max buffer
|
||||||
|
// count.
|
||||||
const bool numberOfBuffersNeedsToChange = !mOverrideMaxBufferCount &&
|
for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
|
||||||
((mDefaultMaxBufferCount != mMaxBufferCount) ||
|
assert(mSlots[i].mBufferState == BufferSlot::FREE);
|
||||||
(mDefaultMaxBufferCount < minBufferCountNeeded));
|
if (mSlots[i].mGraphicBuffer != NULL) {
|
||||||
|
freeBufferLocked(i);
|
||||||
if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
|
returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
|
||||||
// wait for the FIFO to drain
|
}
|
||||||
mDequeueCondition.wait(mMutex);
|
|
||||||
// NOTE: we continue here because we need to reevaluate our
|
|
||||||
// whole state (eg: we could be abandoned or disconnected)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numberOfBuffersNeedsToChange) {
|
|
||||||
// here we're guaranteed that mQueue is empty
|
|
||||||
freeAllBuffersLocked();
|
|
||||||
mMaxBufferCount = mDefaultMaxBufferCount;
|
|
||||||
if (mMaxBufferCount < minBufferCountNeeded)
|
|
||||||
mMaxBufferCount = minBufferCountNeeded;
|
|
||||||
mBufferHasBeenQueued = false;
|
|
||||||
returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// look for a free buffer to give to the client
|
// look for a free buffer to give to the client
|
||||||
found = INVALID_BUFFER_SLOT;
|
found = INVALID_BUFFER_SLOT;
|
||||||
dequeuedCount = 0;
|
dequeuedCount = 0;
|
||||||
for (int i = 0; i < mMaxBufferCount; i++) {
|
for (int i = 0; i < maxBufferCount; i++) {
|
||||||
const int state = mSlots[i].mBufferState;
|
const int state = mSlots[i].mBufferState;
|
||||||
if (state == BufferSlot::DEQUEUED) {
|
if (state == BufferSlot::DEQUEUED) {
|
||||||
dequeuedCount++;
|
dequeuedCount++;
|
||||||
|
@ -406,7 +361,7 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence,
|
||||||
if (mBufferHasBeenQueued) {
|
if (mBufferHasBeenQueued) {
|
||||||
// make sure the client is not trying to dequeue more buffers
|
// make sure the client is not trying to dequeue more buffers
|
||||||
// than allowed.
|
// than allowed.
|
||||||
const int avail = mMaxBufferCount - (dequeuedCount+1);
|
const int avail = maxBufferCount - (dequeuedCount+1);
|
||||||
if (avail < (mMinUndequeuedBuffers-int(mSynchronousMode))) {
|
if (avail < (mMinUndequeuedBuffers-int(mSynchronousMode))) {
|
||||||
ST_LOGE("dequeueBuffer: mMinUndequeuedBuffers=%d exceeded "
|
ST_LOGE("dequeueBuffer: mMinUndequeuedBuffers=%d exceeded "
|
||||||
"(dequeued=%d)",
|
"(dequeued=%d)",
|
||||||
|
@ -416,7 +371,8 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if no buffer is found, wait for a buffer to be released
|
// If no buffer is found, wait for a buffer to be released or for
|
||||||
|
// the max buffer count to change.
|
||||||
tryAgain = found == INVALID_BUFFER_SLOT;
|
tryAgain = found == INVALID_BUFFER_SLOT;
|
||||||
if (tryAgain) {
|
if (tryAgain) {
|
||||||
mDequeueCondition.wait(mMutex);
|
mDequeueCondition.wait(mMutex);
|
||||||
|
@ -557,9 +513,10 @@ status_t BufferQueue::queueBuffer(int buf,
|
||||||
ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!");
|
ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!");
|
||||||
return NO_INIT;
|
return NO_INIT;
|
||||||
}
|
}
|
||||||
if (buf < 0 || buf >= mMaxBufferCount) {
|
int maxBufferCount = getMaxBufferCountLocked();
|
||||||
|
if (buf < 0 || buf >= maxBufferCount) {
|
||||||
ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
|
ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
|
||||||
mMaxBufferCount, buf);
|
maxBufferCount, buf);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
} else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
|
} else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
|
||||||
ST_LOGE("queueBuffer: slot %d is not owned by the client "
|
ST_LOGE("queueBuffer: slot %d is not owned by the client "
|
||||||
|
@ -653,9 +610,10 @@ void BufferQueue::cancelBuffer(int buf, sp<Fence> fence) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf < 0 || buf >= mMaxBufferCount) {
|
int maxBufferCount = getMaxBufferCountLocked();
|
||||||
|
if (buf < 0 || buf >= maxBufferCount) {
|
||||||
ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
|
ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
|
||||||
mMaxBufferCount, buf);
|
maxBufferCount, buf);
|
||||||
return;
|
return;
|
||||||
} else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
|
} else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
|
||||||
ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
|
ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
|
||||||
|
@ -775,10 +733,12 @@ void BufferQueue::dump(String8& result, const char* prefix,
|
||||||
fifo.append(buffer);
|
fifo.append(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int maxBufferCount = getMaxBufferCountLocked();
|
||||||
|
|
||||||
snprintf(buffer, SIZE,
|
snprintf(buffer, SIZE,
|
||||||
"%s-BufferQueue mMaxBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
|
"%s-BufferQueue maxBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
|
||||||
"default-format=%d, FIFO(%d)={%s}\n",
|
"default-format=%d, FIFO(%d)={%s}\n",
|
||||||
prefix, mMaxBufferCount, mSynchronousMode, mDefaultWidth,
|
prefix, maxBufferCount, mSynchronousMode, mDefaultWidth,
|
||||||
mDefaultHeight, mDefaultBufferFormat, fifoSize, fifo.string());
|
mDefaultHeight, mDefaultBufferFormat, fifoSize, fifo.string());
|
||||||
result.append(buffer);
|
result.append(buffer);
|
||||||
|
|
||||||
|
@ -795,7 +755,7 @@ void BufferQueue::dump(String8& result, const char* prefix,
|
||||||
}
|
}
|
||||||
} stateName;
|
} stateName;
|
||||||
|
|
||||||
for (int i=0 ; i<mMaxBufferCount ; i++) {
|
for (int i=0 ; i<maxBufferCount ; i++) {
|
||||||
const BufferSlot& slot(mSlots[i]);
|
const BufferSlot& slot(mSlots[i]);
|
||||||
snprintf(buffer, SIZE,
|
snprintf(buffer, SIZE,
|
||||||
"%s%s[%02d] "
|
"%s%s[%02d] "
|
||||||
|
@ -1039,6 +999,32 @@ int BufferQueue::getMinMaxBufferCountLocked() const {
|
||||||
return mSynchronousMode ? mMinUndequeuedBuffers : mMinUndequeuedBuffers + 1;
|
return mSynchronousMode ? mMinUndequeuedBuffers : mMinUndequeuedBuffers + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int BufferQueue::getMaxBufferCountLocked() const {
|
||||||
|
int minMaxBufferCount = getMinMaxBufferCountLocked();
|
||||||
|
|
||||||
|
int maxBufferCount = mDefaultMaxBufferCount;
|
||||||
|
if (maxBufferCount < minMaxBufferCount) {
|
||||||
|
maxBufferCount = minMaxBufferCount;
|
||||||
|
}
|
||||||
|
if (mOverrideMaxBufferCount != 0) {
|
||||||
|
assert(mOverrideMaxBufferCount >= minMaxBufferCount);
|
||||||
|
maxBufferCount = mOverrideMaxBufferCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any buffers that are dequeued by the producer or sitting in the queue
|
||||||
|
// waiting to be consumed need to have their slots preserved. Such
|
||||||
|
// buffers will temporarily keep the max buffer count up until the slots
|
||||||
|
// no longer need to be preserved.
|
||||||
|
for (int i = maxBufferCount; i < NUM_BUFFER_SLOTS; i++) {
|
||||||
|
BufferSlot::BufferState state = mSlots[i].mBufferState;
|
||||||
|
if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) {
|
||||||
|
maxBufferCount = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxBufferCount;
|
||||||
|
}
|
||||||
|
|
||||||
BufferQueue::ProxyConsumerListener::ProxyConsumerListener(
|
BufferQueue::ProxyConsumerListener::ProxyConsumerListener(
|
||||||
const wp<BufferQueue::ConsumerListener>& consumerListener):
|
const wp<BufferQueue::ConsumerListener>& consumerListener):
|
||||||
mConsumerListener(consumerListener) {}
|
mConsumerListener(consumerListener) {}
|
||||||
|
|
Loading…
Reference in New Issue