From cf46eb9817dfbfc020720d1e45b5c085252500fb Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 11 May 2011 15:05:29 -0700 Subject: [PATCH] fix onFrameAvailable Change-Id: I391fe9f6684ac9fd4f91416ce18b583f7087d966 --- include/gui/SurfaceTexture.h | 10 ++++++++++ libs/gui/SurfaceTexture.cpp | 26 +++++++++++++++++++++----- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h index 45f18211d..43b2fa92d 100644 --- a/include/gui/SurfaceTexture.h +++ b/include/gui/SurfaceTexture.h @@ -46,6 +46,11 @@ public: enum { NUM_BUFFER_SLOTS = 32 }; struct FrameAvailableListener : public virtual RefBase { + // onFrameAvailable() is called from queueBuffer() is the FIFO is + // empty. You can use SurfaceTexture::getQueuedCount() to + // figure out if there are more frames waiting. + // This is called without any lock held can be called concurrently by + // multiple threads. virtual void onFrameAvailable() = 0; }; @@ -96,6 +101,11 @@ public: // target texture belongs is bound to the calling thread. status_t updateTexImage(); + // getqueuedCount returns the number of queued frames waiting in the + // FIFO. In asynchronous mode, this always returns 0 or 1 since + // frames are not accumulating in the FIFO. + size_t getQueuedCount() const; + // setBufferCountServer set the buffer count. If the client has requested // a buffer count using setBufferCount, the server-buffer count will // take effect once the client sets the count back to zero. diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 55b1a9ceb..d7c449c35 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -385,6 +385,10 @@ status_t SurfaceTexture::setSynchronousMode(bool enabled) { status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) { LOGV("SurfaceTexture::queueBuffer"); + + sp listener; + + { // scope for the lock Mutex::Autolock lock(mMutex); if (buf < 0 || buf >= mBufferCount) { LOGE("queueBuffer: slot index out of range [0, %d]: %d", @@ -403,6 +407,10 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) { return -EINVAL; } + if (mQueue.empty()) { + listener = mFrameAvailableListener; + } + if (mSynchronousMode) { // in synchronous mode we queue all buffers in a FIFO mQueue.push_back(buf); @@ -423,11 +431,13 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) { mSlots[buf].mLastQueuedCrop = mNextCrop; mSlots[buf].mLastQueuedTransform = mNextTransform; mSlots[buf].mLastQueuedTimestamp = timestamp; - - if (mFrameAvailableListener != 0) { - mFrameAvailableListener->onFrameAvailable(); - } mDequeueCondition.signal(); + } // scope for the lock + + // call back without lock held + if (listener != 0) { + listener->onFrameAvailable(); + } return OK; } @@ -463,6 +473,7 @@ status_t SurfaceTexture::setTransform(uint32_t transform) { status_t SurfaceTexture::updateTexImage() { LOGV("SurfaceTexture::updateTexImage"); + Mutex::Autolock lock(mMutex); int buf = mCurrentTexture; @@ -496,7 +507,7 @@ status_t SurfaceTexture::updateTexImage() { GLint error; while ((error = glGetError()) != GL_NO_ERROR) { - LOGE("GL error cleared before updating SurfaceTexture: %#04x", error); + LOGW("updateTexImage: clearing GL error: %#04x", error); } GLenum target = getTextureTarget(mSlots[buf].mGraphicBuffer->format); @@ -539,6 +550,11 @@ status_t SurfaceTexture::updateTexImage() { return OK; } +size_t SurfaceTexture::getQueuedCount() const { + Mutex::Autolock lock(mMutex); + return mQueue.size(); +} + bool SurfaceTexture::isExternalFormat(uint32_t format) { switch (format) {