diff options
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/gui/SurfaceTexture.cpp | 110 | ||||
| -rw-r--r-- | libs/gui/SurfaceTextureClient.cpp | 3 | ||||
| -rw-r--r-- | libs/gui/tests/SurfaceTextureClient_test.cpp | 17 |
3 files changed, 72 insertions, 58 deletions
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index b08a5a8..ee97dcf 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -285,15 +285,19 @@ status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, return -EINVAL; } - // make sure the client is not trying to dequeue more buffers - // than allowed. - const int avail = mBufferCount - (dequeuedCount+1); - if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) { - LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)", - MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode), - dequeuedCount); - // TODO: Enable this error report after we fix issue 4435022 - // return -EBUSY; + // See whether a buffer has been queued since the last setBufferCount so + // we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below. + bool bufferHasBeenQueued = mCurrentTexture != INVALID_BUFFER_SLOT; + if (bufferHasBeenQueued) { + // make sure the client is not trying to dequeue more buffers + // than allowed. + const int avail = mBufferCount - (dequeuedCount+1); + if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) { + LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)", + MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode), + dequeuedCount); + return -EBUSY; + } } // we're in synchronous mode and didn't find a buffer, we need to wait @@ -390,49 +394,49 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) { sp<FrameAvailableListener> listener; { // scope for the lock - Mutex::Autolock lock(mMutex); - if (buf < 0 || buf >= mBufferCount) { - LOGE("queueBuffer: slot index out of range [0, %d]: %d", - mBufferCount, buf); - return -EINVAL; - } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { - LOGE("queueBuffer: slot %d is not owned by the client (state=%d)", - buf, mSlots[buf].mBufferState); - return -EINVAL; - } else if (buf == mCurrentTexture) { - LOGE("queueBuffer: slot %d is current!", buf); - return -EINVAL; - } else if (!mSlots[buf].mRequestBufferCalled) { - LOGE("queueBuffer: slot %d was enqueued without requesting a buffer", - buf); - return -EINVAL; - } - - if (mQueue.empty()) { - listener = mFrameAvailableListener; - } + Mutex::Autolock lock(mMutex); + if (buf < 0 || buf >= mBufferCount) { + LOGE("queueBuffer: slot index out of range [0, %d]: %d", + mBufferCount, buf); + return -EINVAL; + } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) { + LOGE("queueBuffer: slot %d is not owned by the client (state=%d)", + buf, mSlots[buf].mBufferState); + return -EINVAL; + } else if (buf == mCurrentTexture) { + LOGE("queueBuffer: slot %d is current!", buf); + return -EINVAL; + } else if (!mSlots[buf].mRequestBufferCalled) { + LOGE("queueBuffer: slot %d was enqueued without requesting a " + "buffer", buf); + return -EINVAL; + } - if (mSynchronousMode) { - // in synchronous mode we queue all buffers in a FIFO - mQueue.push_back(buf); - } else { - // in asynchronous mode we only keep the most recent buffer if (mQueue.empty()) { + listener = mFrameAvailableListener; + } + + if (mSynchronousMode) { + // in synchronous mode we queue all buffers in a FIFO mQueue.push_back(buf); } else { - Fifo::iterator front(mQueue.begin()); - // buffer currently queued is freed - mSlots[*front].mBufferState = BufferSlot::FREE; - // and we record the new buffer index in the queued list - *front = buf; + // in asynchronous mode we only keep the most recent buffer + if (mQueue.empty()) { + mQueue.push_back(buf); + } else { + Fifo::iterator front(mQueue.begin()); + // buffer currently queued is freed + mSlots[*front].mBufferState = BufferSlot::FREE; + // and we record the new buffer index in the queued list + *front = buf; + } } - } - mSlots[buf].mBufferState = BufferSlot::QUEUED; - mSlots[buf].mLastQueuedCrop = mNextCrop; - mSlots[buf].mLastQueuedTransform = mNextTransform; - mSlots[buf].mLastQueuedTimestamp = timestamp; - mDequeueCondition.signal(); + mSlots[buf].mBufferState = BufferSlot::QUEUED; + mSlots[buf].mCrop = mNextCrop; + mSlots[buf].mTransform = mNextTransform; + mSlots[buf].mTimestamp = timestamp; + mDequeueCondition.signal(); } // scope for the lock // call back without lock held @@ -540,9 +544,9 @@ status_t SurfaceTexture::updateTexImage() { mCurrentTexture = buf; mCurrentTextureTarget = target; mCurrentTextureBuf = mSlots[buf].mGraphicBuffer; - mCurrentCrop = mSlots[buf].mLastQueuedCrop; - mCurrentTransform = mSlots[buf].mLastQueuedTransform; - mCurrentTimestamp = mSlots[buf].mLastQueuedTimestamp; + mCurrentCrop = mSlots[buf].mCrop; + mCurrentTransform = mSlots[buf].mTransform; + mCurrentTimestamp = mSlots[buf].mTimestamp; mDequeueCondition.signal(); } else { // We always bind the texture even if we don't update its contents. @@ -826,12 +830,10 @@ void SurfaceTexture::dump(String8& result, const char* prefix, const BufferSlot& slot(mSlots[i]); snprintf(buffer, SIZE, "%s%s[%02d] state=%-8s, crop=[%d,%d,%d,%d], transform=0x%02x, " - "timestamp=%lld\n" - , + "timestamp=%lld\n", prefix, (i==mCurrentTexture)?">":" ", i, stateName(slot.mBufferState), - slot.mLastQueuedCrop.left, slot.mLastQueuedCrop.top, - slot.mLastQueuedCrop.right, slot.mLastQueuedCrop.bottom, - slot.mLastQueuedTransform, slot.mLastQueuedTimestamp + slot.mCrop.left, slot.mCrop.top, slot.mCrop.right, slot.mCrop.bottom, + slot.mTransform, slot.mTimestamp ); result.append(buffer); } diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index 6f10320..c20fcf2 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -117,7 +117,8 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) { mReqFormat, mReqUsage); if (result < 0) { LOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer(%d, %d, %d, %d)" - "failed: %d", result, mReqWidth, mReqHeight, mReqFormat, mReqUsage); + "failed: %d", mReqWidth, mReqHeight, mReqFormat, mReqUsage, + result); return result; } sp<GraphicBuffer>& gbuf(mSlots[buf]); diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp index 59a4cc5..2f704c8 100644 --- a/libs/gui/tests/SurfaceTextureClient_test.cpp +++ b/libs/gui/tests/SurfaceTextureClient_test.cpp @@ -400,7 +400,9 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) { EXPECT_EQ(st->getCurrentBuffer().get(), buf[2]); } -TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDequeueCurrent) { +// XXX: We currently have no hardware that properly handles dequeuing the +// buffer that is currently bound to the texture. +TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeDequeueCurrent) { sp<ANativeWindow> anw(mSTC); sp<SurfaceTexture> st(mST); android_native_buffer_t* buf[3]; @@ -429,10 +431,13 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) { android_native_buffer_t* buf[3]; ASSERT_EQ(OK, st->setSynchronousMode(true)); ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3)); + + // We should be able to dequeue all the buffers before we've queued any. EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0])); EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1])); - EXPECT_EQ(-EBUSY, anw->dequeueBuffer(anw.get(), &buf[2])); + EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2])); + ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[2])); ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1])); EXPECT_EQ(OK, st->updateTexImage()); @@ -440,11 +445,17 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) { EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2])); + // Once we've queued a buffer, however we should not be able to dequeue more + // than (buffer-count - MIN_UNDEQUEUED_BUFFERS), which is 2 in this case. + EXPECT_EQ(-EBUSY, anw->dequeueBuffer(anw.get(), &buf[1])); + ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0])); ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[2])); } -TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeWaitRetire) { +// XXX: This is not expected to pass until the synchronization hacks are removed +// from the SurfaceTexture class. +TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeWaitRetire) { sp<ANativeWindow> anw(mSTC); sp<SurfaceTexture> st(mST); |
