rework dequeueBuffer()'s main loop.
this simplifies the code a bit and also makes sure we reevaluate mAbandoned and mConnectedApi each time we come back from waiting on mDequeueCondition Change-Id: I1f8538b62ad321b51ed79d953b700036daba796d
This commit is contained in:
parent
ef51b99219
commit
2560d14ce8
@ -211,6 +211,11 @@ protected:
|
|||||||
// freeAllBuffers frees the resources (both GraphicBuffer and EGLImage) for
|
// freeAllBuffers frees the resources (both GraphicBuffer and EGLImage) for
|
||||||
// all slots.
|
// all slots.
|
||||||
void freeAllBuffersLocked();
|
void freeAllBuffersLocked();
|
||||||
|
|
||||||
|
// drainQueueLocked drains the buffer queue if we're in synchronous mode
|
||||||
|
// returns immediately otherwise.
|
||||||
|
void drainQueueLocked();
|
||||||
|
|
||||||
static bool isExternalFormat(uint32_t format);
|
static bool isExternalFormat(uint32_t format);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -158,7 +158,6 @@ status_t SurfaceTexture::setBufferCount(int bufferCount) {
|
|||||||
LOGE("setBufferCount: SurfaceTexture is not connected!");
|
LOGE("setBufferCount: SurfaceTexture is not connected!");
|
||||||
return NO_INIT;
|
return NO_INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bufferCount > NUM_BUFFER_SLOTS) {
|
if (bufferCount > NUM_BUFFER_SLOTS) {
|
||||||
LOGE("setBufferCount: bufferCount larger than slots available");
|
LOGE("setBufferCount: bufferCount larger than slots available");
|
||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
@ -236,15 +235,6 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
|
|||||||
uint32_t format, uint32_t usage) {
|
uint32_t format, uint32_t usage) {
|
||||||
LOGV("SurfaceTexture::dequeueBuffer");
|
LOGV("SurfaceTexture::dequeueBuffer");
|
||||||
|
|
||||||
if (mAbandoned) {
|
|
||||||
LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
|
|
||||||
return NO_INIT;
|
|
||||||
}
|
|
||||||
if (mConnectedApi == NO_CONNECTED_API) {
|
|
||||||
LOGE("dequeueBuffer: SurfaceTexture is not connected!");
|
|
||||||
return NO_INIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((w && !h) || (!w && h)) {
|
if ((w && !h) || (!w && h)) {
|
||||||
LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
|
LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
|
||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
@ -258,10 +248,19 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
|
|||||||
int dequeuedCount = 0;
|
int dequeuedCount = 0;
|
||||||
bool tryAgain = true;
|
bool tryAgain = true;
|
||||||
while (tryAgain) {
|
while (tryAgain) {
|
||||||
|
if (mAbandoned) {
|
||||||
|
LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
|
||||||
|
return NO_INIT;
|
||||||
|
}
|
||||||
|
if (mConnectedApi == NO_CONNECTED_API) {
|
||||||
|
LOGE("dequeueBuffer: SurfaceTexture is not connected!");
|
||||||
|
return NO_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
// We need to wait for the FIFO to drain if the number of buffer
|
// We need to wait for the FIFO to drain if the number of buffer
|
||||||
// needs to change.
|
// needs to change.
|
||||||
//
|
//
|
||||||
// The condition "number of buffer needs to change" is true if
|
// The condition "number of buffers needs to change" is true if
|
||||||
// - the client doesn't care about how many buffers there are
|
// - the client doesn't care about how many buffers there are
|
||||||
// - AND the actual number of buffer is different from what was
|
// - AND the actual number of buffer is different from what was
|
||||||
// set in the last setBufferCountServer()
|
// set in the last setBufferCountServer()
|
||||||
@ -273,29 +272,22 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
|
|||||||
// As long as this condition is true AND the FIFO is not empty, we
|
// As long as this condition is true AND the FIFO is not empty, we
|
||||||
// wait on mDequeueCondition.
|
// wait on mDequeueCondition.
|
||||||
|
|
||||||
int minBufferCountNeeded = mSynchronousMode ?
|
const int minBufferCountNeeded = mSynchronousMode ?
|
||||||
MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
|
MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
|
||||||
|
|
||||||
if (!mClientBufferCount &&
|
const bool numberOfBuffersNeedsToChange = !mClientBufferCount &&
|
||||||
((mServerBufferCount != mBufferCount) ||
|
((mServerBufferCount != mBufferCount) ||
|
||||||
(mServerBufferCount < minBufferCountNeeded))) {
|
(mServerBufferCount < minBufferCountNeeded));
|
||||||
|
|
||||||
|
if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
|
||||||
// wait for the FIFO to drain
|
// wait for the FIFO to drain
|
||||||
while (!mQueue.isEmpty()) {
|
|
||||||
mDequeueCondition.wait(mMutex);
|
mDequeueCondition.wait(mMutex);
|
||||||
if (mAbandoned) {
|
// NOTE: we continue here because we need to reevaluate our
|
||||||
LOGE("dequeueBuffer: SurfaceTexture was abandoned while "
|
// whole state (eg: we could be abandoned or disconnected)
|
||||||
"blocked!");
|
continue;
|
||||||
return NO_INIT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
minBufferCountNeeded = mSynchronousMode ?
|
|
||||||
MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (numberOfBuffersNeedsToChange) {
|
||||||
if (!mClientBufferCount &&
|
|
||||||
((mServerBufferCount != mBufferCount) ||
|
|
||||||
(mServerBufferCount < minBufferCountNeeded))) {
|
|
||||||
// here we're guaranteed that mQueue is empty
|
// here we're guaranteed that mQueue is empty
|
||||||
freeAllBuffersLocked();
|
freeAllBuffersLocked();
|
||||||
mBufferCount = mServerBufferCount;
|
mBufferCount = mServerBufferCount;
|
||||||
@ -426,9 +418,7 @@ status_t SurfaceTexture::setSynchronousMode(bool enabled) {
|
|||||||
|
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
// going to asynchronous mode, drain the queue
|
// going to asynchronous mode, drain the queue
|
||||||
while (mSynchronousMode != enabled && !mQueue.isEmpty()) {
|
drainQueueLocked();
|
||||||
mDequeueCondition.wait(mMutex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSynchronousMode != enabled) {
|
if (mSynchronousMode != enabled) {
|
||||||
@ -627,7 +617,12 @@ status_t SurfaceTexture::disconnect(int api) {
|
|||||||
case NATIVE_WINDOW_API_CAMERA:
|
case NATIVE_WINDOW_API_CAMERA:
|
||||||
if (mConnectedApi == api) {
|
if (mConnectedApi == api) {
|
||||||
mConnectedApi = NO_CONNECTED_API;
|
mConnectedApi = NO_CONNECTED_API;
|
||||||
|
if (mQueue.isEmpty()) {
|
||||||
|
// if the queue is not empty, we need to wait for it
|
||||||
|
// to drain before we can free all buffers. This is
|
||||||
|
// done in updateTexImage().
|
||||||
freeAllBuffersLocked();
|
freeAllBuffersLocked();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOGE("disconnect: connected to another api (cur=%d, req=%d)",
|
LOGE("disconnect: connected to another api (cur=%d, req=%d)",
|
||||||
mConnectedApi, api);
|
mConnectedApi, api);
|
||||||
@ -890,6 +885,12 @@ void SurfaceTexture::freeAllBuffersLocked() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SurfaceTexture::drainQueueLocked() {
|
||||||
|
while (mSynchronousMode && !mQueue.isEmpty()) {
|
||||||
|
mDequeueCondition.wait(mMutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
|
EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
|
||||||
const sp<GraphicBuffer>& graphicBuffer) {
|
const sp<GraphicBuffer>& graphicBuffer) {
|
||||||
EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
|
EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
|
||||||
@ -959,6 +960,7 @@ int SurfaceTexture::query(int what, int* outValue)
|
|||||||
|
|
||||||
void SurfaceTexture::abandon() {
|
void SurfaceTexture::abandon() {
|
||||||
Mutex::Autolock lock(mMutex);
|
Mutex::Autolock lock(mMutex);
|
||||||
|
// clear the queue
|
||||||
freeAllBuffersLocked();
|
freeAllBuffersLocked();
|
||||||
mAbandoned = true;
|
mAbandoned = true;
|
||||||
mCurrentTextureBuf.clear();
|
mCurrentTextureBuf.clear();
|
||||||
|
Loading…
Reference in New Issue
Block a user