diff options
| -rw-r--r-- | include/gui/ConsumerBase.h | 8 | ||||
| -rw-r--r-- | include/gui/SurfaceTexture.h | 113 | ||||
| -rw-r--r-- | libs/gui/ConsumerBase.cpp | 3 | ||||
| -rw-r--r-- | libs/gui/SurfaceTexture.cpp | 284 | 
4 files changed, 121 insertions, 287 deletions
diff --git a/include/gui/ConsumerBase.h b/include/gui/ConsumerBase.h index d2bf0f649d..1f643a32eb 100644 --- a/include/gui/ConsumerBase.h +++ b/include/gui/ConsumerBase.h @@ -189,14 +189,6 @@ protected:      // if none is supplied      sp<BufferQueue> mBufferQueue; -    // mAttached indicates whether the ConsumerBase is currently attached to -    // an OpenGL ES context.  For legacy reasons, this is initialized to true, -    // indicating that the ConsumerBase is considered to be attached to -    // whatever context is current at the time of the first updateTexImage call. -    // It is set to false by detachFromContext, and then set to true again by -    // attachToContext. -    bool mAttached; -      // mMutex is the mutex used to prevent concurrent access to the member      // variables of ConsumerBase objects. It must be locked whenever the      // member variables are accessed. diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h index 66c390a849..0a83ce6af1 100644 --- a/include/gui/SurfaceTexture.h +++ b/include/gui/SurfaceTexture.h @@ -24,6 +24,7 @@  #include <gui/ISurfaceTexture.h>  #include <gui/BufferQueue.h> +#include <gui/ConsumerBase.h>  #include <ui/GraphicBuffer.h> @@ -39,20 +40,9 @@ namespace android {  class String8; -class SurfaceTexture : public virtual RefBase, -        protected BufferQueue::ConsumerListener { +class SurfaceTexture : public ConsumerBase {  public: -    struct FrameAvailableListener : public virtual RefBase { -        // onFrameAvailable() is called each time an additional frame becomes -        // available for consumption. This means that frames that are queued -        // while in asynchronous mode only trigger the callback if no previous -        // frames are pending. Frames queued while in synchronous mode always -        // trigger the callback. -        // -        // This is called without any lock held and can be called concurrently -        // by multiple threads. -        virtual void onFrameAvailable() = 0; -    }; +    typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;      // SurfaceTexture constructs a new SurfaceTexture object. tex indicates the      // name of the OpenGL ES texture to which images are to be streamed. @@ -82,8 +72,6 @@ public:              GLenum texTarget = GL_TEXTURE_EXTERNAL_OES, bool useFenceSync = true,              const sp<BufferQueue> &bufferQueue = 0); -    virtual ~SurfaceTexture(); -      // updateTexImage sets the image contents of the target texture to that of      // the most recently queued buffer.      // @@ -132,16 +120,6 @@ public:      // documented by the source.      int64_t getTimestamp(); -    // setFrameAvailableListener sets the listener object that will be notified -    // when a new frame becomes available. -    void setFrameAvailableListener(const sp<FrameAvailableListener>& listener); - -    // getAllocator retrieves the binder object that must be referenced as long -    // as the GraphicBuffers dequeued from this SurfaceTexture are referenced. -    // Holding this binder reference prevents SurfaceFlinger from freeing the -    // buffers before the client is done with them. -    sp<IBinder> getAllocator(); -      // setDefaultBufferSize is used to set the size of buffers returned by      // requestBuffers when a with and height of zero is requested.      // A call to setDefaultBufferSize() may trigger requestBuffers() to @@ -180,17 +158,6 @@ public:      // synchronous mode.      bool isSynchronousMode() const; -    // abandon frees all the buffers and puts the SurfaceTexture into the -    // 'abandoned' state.  Once put in this state the SurfaceTexture can never -    // leave it.  When in the 'abandoned' state, all methods of the -    // ISurfaceTexture interface will fail with the NO_INIT error. -    // -    // Note that while calling this method causes all the buffers to be freed -    // from the perspective of the the SurfaceTexture, if there are additional -    // references on the buffers (e.g. if a buffer is referenced by a client or -    // by OpenGL ES as a texture) then those buffer will remain allocated. -    void abandon(); -      // set the name of the SurfaceTexture that will be used to identify it in      // log messages.      void setName(const String8& name); @@ -204,7 +171,9 @@ public:      // getBufferQueue returns the BufferQueue object to which this      // SurfaceTexture is connected. -    sp<BufferQueue> getBufferQueue() const; +    sp<BufferQueue> getBufferQueue() const { +        return mBufferQueue; +    }      // detachFromContext detaches the SurfaceTexture from the calling thread's      // current OpenGL ES context.  This context must be the same as the context @@ -233,17 +202,25 @@ public:      // current at the time of the last call to detachFromContext.      status_t attachToContext(GLuint tex); -    // dump our state in a String -    virtual void dump(String8& result) const; -    virtual void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const; -  protected: -    // Implementation of the BufferQueue::ConsumerListener interface.  These -    // calls are used to notify the SurfaceTexture of asynchronous events in the -    // BufferQueue. -    virtual void onFrameAvailable(); -    virtual void onBuffersReleased(); +    // abandonLocked overrides the ConsumerBase method to clear +    // mCurrentTextureBuf in addition to the ConsumerBase behavior. +    virtual void abandonLocked(); + +    // dumpLocked overrides the ConsumerBase method to dump SurfaceTexture- +    // specific info in addition to the ConsumerBase behavior. +    virtual void dumpLocked(String8& result, const char* prefix, char* buffer, +           size_t size) const; + +    // acquireBufferLocked overrides the ConsumerBase method to update the +    // mEglSlots array in addition to the ConsumerBase behavior. +    virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item); + +    // releaseBufferLocked overrides the ConsumerBase method to update the +    // mEglSlots array in addition to the ConsumerBase. +    virtual status_t releaseBufferLocked(int buf, EGLDisplay display, +           EGLSyncKHR eglFence, const sp<Fence>& fence);      static bool isExternalFormat(uint32_t format); @@ -351,11 +328,9 @@ private:      struct EGLSlot {          EGLSlot()          : mEglImage(EGL_NO_IMAGE_KHR), -          mFence(EGL_NO_SYNC_KHR) { +          mEglFence(EGL_NO_SYNC_KHR) {          } -        sp<GraphicBuffer> mGraphicBuffer; -          // mEglImage is the EGLImage created from mGraphicBuffer.          EGLImageKHR mEglImage; @@ -363,14 +338,7 @@ private:          // associated with this buffer slot may be dequeued. It is initialized          // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based          // on a compile-time option) set to a new sync object in updateTexImage. -        EGLSyncKHR mFence; - -        // mReleaseFence is a fence which will signal when the buffer -        // associated with this buffer slot is no longer being used by the -        // consumer and can be overwritten. The buffer can be dequeued before -        // the fence signals; the producer is responsible for delaying writes -        // until it signals. -        sp<Fence> mReleaseFence; +        EGLSyncKHR mEglFence;      };      // mEglDisplay is the EGLDisplay with which this SurfaceTexture is currently @@ -392,23 +360,7 @@ private:      // slot that has not yet been used. The buffer allocated to a slot will also      // be replaced if the requested buffer usage or geometry differs from that      // of the buffer allocated to a slot. -    EGLSlot mEGLSlots[BufferQueue::NUM_BUFFER_SLOTS]; - -    // mAbandoned indicates that the BufferQueue will no longer be used to -    // consume images buffers pushed to it using the ISurfaceTexture interface. -    // It is initialized to false, and set to true in the abandon method.  A -    // BufferQueue that has been abandoned will return the NO_INIT error from -    // all ISurfaceTexture methods capable of returning an error. -    bool mAbandoned; - -    // mName is a string used to identify the SurfaceTexture in log messages. -    // It can be set by the setName method. -    String8 mName; - -    // mFrameAvailableListener is the listener object that will be called when a -    // new frame becomes available. If it is not NULL it will be called from -    // queueBuffer. -    sp<FrameAvailableListener> mFrameAvailableListener; +    EGLSlot mEglSlots[BufferQueue::NUM_BUFFER_SLOTS];      // mCurrentTexture is the buffer slot index of the buffer that is currently      // bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT, @@ -418,22 +370,13 @@ private:      // reset mCurrentTexture to INVALID_BUFFER_SLOT.      int mCurrentTexture; -    // The SurfaceTexture has-a BufferQueue and is responsible for creating this object -    // if none is supplied -    sp<BufferQueue> mBufferQueue; - -    // mAttached indicates whether the SurfaceTexture is currently attached to +    // mAttached indicates whether the ConsumerBase is currently attached to      // an OpenGL ES context.  For legacy reasons, this is initialized to true, -    // indicating that the SurfaceTexture is considered to be attached to +    // indicating that the ConsumerBase is considered to be attached to      // whatever context is current at the time of the first updateTexImage call.      // It is set to false by detachFromContext, and then set to true again by      // attachToContext.      bool mAttached; - -    // mMutex is the mutex used to prevent concurrent access to the member -    // variables of SurfaceTexture objects. It must be locked whenever the -    // member variables are accessed. -    mutable Mutex mMutex;  };  // ---------------------------------------------------------------------------- diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp index af19ac0811..17bbfd11ee 100644 --- a/libs/gui/ConsumerBase.cpp +++ b/libs/gui/ConsumerBase.cpp @@ -53,7 +53,8 @@ static int32_t createProcessUniqueId() {  }  ConsumerBase::ConsumerBase(const sp<BufferQueue>& bufferQueue) : -	mBufferQueue(bufferQueue) { +        mAbandoned(false), +        mBufferQueue(bufferQueue) {      // Choose a name using the PID and a process-unique ID.      mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId()); diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 66660810f9..451ccc26ec 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -26,6 +26,8 @@  #include <GLES2/gl2.h>  #include <GLES2/gl2ext.h> +#include <hardware/hardware.h> +  #include <gui/IGraphicBufferAlloc.h>  #include <gui/ISurfaceComposer.h>  #include <gui/SurfaceComposerClient.h> @@ -96,14 +98,10 @@ static float mtxRot270[16] = {  static void mtxMul(float out[16], const float a[16], const float b[16]); -// Get an ID that's unique within this process. -static int32_t createProcessUniqueId() { -    static volatile int32_t globalCounter = 0; -    return android_atomic_inc(&globalCounter); -}  SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,          GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) : +    ConsumerBase(bufferQueue == 0 ? new BufferQueue(allowSynchronousMode) : bufferQueue),      mCurrentTransform(0),      mCurrentTimestamp(0),      mFilteringEnabled(true), @@ -116,47 +114,15 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,      mTexTarget(texTarget),      mEglDisplay(EGL_NO_DISPLAY),      mEglContext(EGL_NO_CONTEXT), -    mAbandoned(false),      mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),      mAttached(true)  { -    // Choose a name using the PID and a process-unique ID. -    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());      ST_LOGV("SurfaceTexture"); -    if (bufferQueue == 0) { -        ST_LOGV("Creating a new BufferQueue"); -        mBufferQueue = new BufferQueue(allowSynchronousMode); -    } -    else { -        mBufferQueue = bufferQueue; -    }      memcpy(mCurrentTransformMatrix, mtxIdentity,              sizeof(mCurrentTransformMatrix)); -    // Note that we can't create an sp<...>(this) in a ctor that will not keep a -    // reference once the ctor ends, as that would cause the refcount of 'this' -    // dropping to 0 at the end of the ctor.  Since all we need is a wp<...> -    // that's what we create. -    wp<BufferQueue::ConsumerListener> listener; -    sp<BufferQueue::ConsumerListener> proxy; -    listener = static_cast<BufferQueue::ConsumerListener*>(this); -    proxy = new BufferQueue::ProxyConsumerListener(listener); - -    status_t err = mBufferQueue->consumerConnect(proxy); -    if (err != NO_ERROR) { -        ST_LOGE("SurfaceTexture: error connecting to BufferQueue: %s (%d)", -                strerror(-err), err); -    } else { -        mBufferQueue->setConsumerName(mName); -        mBufferQueue->setConsumerUsageBits(DEFAULT_USAGE_FLAGS); -    } -} - -SurfaceTexture::~SurfaceTexture() { -    ST_LOGV("~SurfaceTexture"); - -    abandon(); +    mBufferQueue->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);  }  status_t SurfaceTexture::setBufferCountServer(int bufferCount) { @@ -177,6 +143,42 @@ status_t SurfaceTexture::updateTexImage() {      return SurfaceTexture::updateTexImage(NULL);  } +status_t SurfaceTexture::acquireBufferLocked(BufferQueue::BufferItem *item) { +    status_t err = ConsumerBase::acquireBufferLocked(item); +    if (err != NO_ERROR) { +        return err; +    } + +    int slot = item->mBuf; +    if (item->mGraphicBuffer != NULL) { +        if (mEglSlots[slot].mEglImage != EGL_NO_IMAGE_KHR) { +            eglDestroyImageKHR(mEglDisplay, mEglSlots[slot].mEglImage); +            mEglSlots[slot].mEglImage = EGL_NO_IMAGE_KHR; +        } +    } + +    // Update the GL texture object. We may have to do this even when +    // item.mGraphicBuffer == NULL, if we destroyed the EGLImage when +    // detaching from a context but the buffer has not been re-allocated. +    EGLImageKHR image = createImage(mEglDisplay, mSlots[slot].mGraphicBuffer); +    if (image == EGL_NO_IMAGE_KHR) { +        return UNKNOWN_ERROR; +    } +    mEglSlots[slot].mEglImage = image; + +    return NO_ERROR; +} + +status_t SurfaceTexture::releaseBufferLocked(int buf, EGLDisplay display, +       EGLSyncKHR eglFence, const sp<Fence>& fence) { +    status_t err = ConsumerBase::releaseBufferLocked(buf, mEglDisplay, +           eglFence, fence); + +    mEglSlots[mCurrentTexture].mEglFence = EGL_NO_SYNC_KHR; + +    return err; +} +  status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {      ATRACE_CALL();      ST_LOGV("updateTexImage"); @@ -217,97 +219,65 @@ status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {      // In asynchronous mode the list is guaranteed to be one buffer      // deep, while in synchronous mode we use the oldest buffer. -    err = mBufferQueue->acquireBuffer(&item); +    err = acquireBufferLocked(&item);      if (err == NO_ERROR) {          int buf = item.mBuf; -        // This buffer was newly allocated, so we need to clean up on our side -        if (item.mGraphicBuffer != NULL) { -            mEGLSlots[buf].mGraphicBuffer = 0; -            if (mEGLSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) { -                eglDestroyImageKHR(dpy, mEGLSlots[buf].mEglImage); -                mEGLSlots[buf].mEglImage = EGL_NO_IMAGE_KHR; -            } -            mEGLSlots[buf].mGraphicBuffer = item.mGraphicBuffer; -        }          // we call the rejecter here, in case the caller has a reason to          // not accept this buffer. this is used by SurfaceFlinger to          // reject buffers which have the wrong size -        if (rejecter && rejecter->reject(mEGLSlots[buf].mGraphicBuffer, item)) { -            mBufferQueue->releaseBuffer(buf, dpy, EGL_NO_SYNC_KHR, item.mFence); +        if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) { +            releaseBufferLocked(buf, dpy, EGL_NO_SYNC_KHR, item.mFence);              glBindTexture(mTexTarget, mTexName);              return NO_ERROR;          } -        // Update the GL texture object. We may have to do this even when -        // item.mGraphicBuffer == NULL, if we destroyed the EGLImage when -        // detaching from a context but the buffer has not been re-allocated. -        EGLImageKHR image = mEGLSlots[buf].mEglImage; -        if (image == EGL_NO_IMAGE_KHR) { -            if (mEGLSlots[buf].mGraphicBuffer == NULL) { -                ST_LOGE("updateTexImage: buffer at slot %d is null", buf); -                err = BAD_VALUE; -            } else { -                image = createImage(dpy, mEGLSlots[buf].mGraphicBuffer); -                mEGLSlots[buf].mEglImage = image; -                if (image == EGL_NO_IMAGE_KHR) { -                    // NOTE: if dpy was invalid, createImage() is guaranteed to -                    // fail. so we'd end up here. -                    err = UNKNOWN_ERROR; -                } -            } +        GLint error; +        while ((error = glGetError()) != GL_NO_ERROR) { +            ST_LOGW("updateTexImage: clearing GL error: %#04x", error);          } -        if (err == NO_ERROR) { -            GLint error; -            while ((error = glGetError()) != GL_NO_ERROR) { -                ST_LOGW("updateTexImage: clearing GL error: %#04x", error); -            } - -            glBindTexture(mTexTarget, mTexName); -            glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image); +        EGLImageKHR image = mEglSlots[buf].mEglImage; +        glBindTexture(mTexTarget, mTexName); +        glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image); -            while ((error = glGetError()) != GL_NO_ERROR) { -                ST_LOGE("updateTexImage: error binding external texture image %p " -                        "(slot %d): %#04x", image, buf, error); -                err = UNKNOWN_ERROR; -            } +        while ((error = glGetError()) != GL_NO_ERROR) { +            ST_LOGE("updateTexImage: error binding external texture image %p " +                    "(slot %d): %#04x", image, buf, error); +            err = UNKNOWN_ERROR; +        } -            if (err == NO_ERROR) { -                err = syncForReleaseLocked(dpy); -            } +        if (err == NO_ERROR) { +            err = syncForReleaseLocked(dpy);          }          if (err != NO_ERROR) {              // Release the buffer we just acquired.  It's not safe to              // release the old buffer, so instead we just drop the new frame. -            mBufferQueue->releaseBuffer(buf, dpy, EGL_NO_SYNC_KHR, item.mFence); +            releaseBufferLocked(buf, dpy, EGL_NO_SYNC_KHR, item.mFence);              return err;          }          ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)",                  mCurrentTexture,                  mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0, -                buf, item.mGraphicBuffer != NULL ? item.mGraphicBuffer->handle : 0); +                buf, mSlots[buf].mGraphicBuffer->handle);          // release old buffer          if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { -            status_t status = mBufferQueue->releaseBuffer(mCurrentTexture, dpy, -                    mEGLSlots[mCurrentTexture].mFence, -                    mEGLSlots[mCurrentTexture].mReleaseFence); -            mEGLSlots[mCurrentTexture].mFence = EGL_NO_SYNC_KHR; -            mEGLSlots[mCurrentTexture].mReleaseFence.clear(); -            if (status == BufferQueue::STALE_BUFFER_SLOT) { -                freeBufferLocked(mCurrentTexture); -            } else if (status != NO_ERROR) { -                ST_LOGE("updateTexImage: released invalid buffer"); +            status_t status = releaseBufferLocked(mCurrentTexture, dpy, +                    mEglSlots[mCurrentTexture].mEglFence, +                    mSlots[mCurrentTexture].mFence); +            if (status != NO_ERROR && status != BufferQueue::STALE_BUFFER_SLOT) { +                ST_LOGE("updateTexImage: failed to release buffer: %s (%d)", +                       strerror(-status), status);                  err = status;              }          }          // Update the SurfaceTexture state.          mCurrentTexture = buf; -        mCurrentTextureBuf = mEGLSlots[buf].mGraphicBuffer; +        mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;          mCurrentCrop = item.mCrop;          mCurrentTransform = item.mTransform;          mCurrentScalingMode = item.mScalingMode; @@ -330,20 +300,20 @@ void SurfaceTexture::setReleaseFence(int fenceFd) {      sp<Fence> fence(new Fence(fenceFd));      if (fenceFd == -1 || mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT)          return; -    if (!mEGLSlots[mCurrentTexture].mReleaseFence.get()) { -        mEGLSlots[mCurrentTexture].mReleaseFence = fence; +    if (!mSlots[mCurrentTexture].mFence.get()) { +        mSlots[mCurrentTexture].mFence = fence;      } else {          sp<Fence> mergedFence = Fence::merge(                  String8("SurfaceTexture merged release"), -                mEGLSlots[mCurrentTexture].mReleaseFence, fence); +                mSlots[mCurrentTexture].mFence, fence);          if (!mergedFence.get()) {              ST_LOGE("failed to merge release fences");              // synchronization is broken, the best we can do is hope fences              // signal in order so the new fence will act like a union -            mEGLSlots[mCurrentTexture].mReleaseFence = fence; +            mSlots[mCurrentTexture].mFence = fence;              return;          } -        mEGLSlots[mCurrentTexture].mReleaseFence = mergedFence; +        mSlots[mCurrentTexture].mFence = mergedFence;      }  } @@ -390,10 +360,10 @@ status_t SurfaceTexture::detachFromContext() {      // SurfaceTexture gets attached to a new OpenGL ES context (and thus gets a      // new EGLDisplay).      for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { -        EGLImageKHR img = mEGLSlots[i].mEglImage; +        EGLImageKHR img = mEglSlots[i].mEglImage;          if (img != EGL_NO_IMAGE_KHR) {              eglDestroyImageKHR(mEglDisplay, img); -            mEGLSlots[i].mEglImage = EGL_NO_IMAGE_KHR; +            mEglSlots[i].mEglImage = EGL_NO_IMAGE_KHR;          }      } @@ -481,7 +451,7 @@ status_t SurfaceTexture::syncForReleaseLocked(EGLDisplay dpy) {      ST_LOGV("syncForReleaseLocked");      if (mUseFenceSync && mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { -        EGLSyncKHR fence = mEGLSlots[mCurrentTexture].mFence; +        EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;          if (fence != EGL_NO_SYNC_KHR) {              // There is already a fence for the current slot.  We need to wait              // on that before replacing it with another fence to ensure that all @@ -509,7 +479,7 @@ status_t SurfaceTexture::syncForReleaseLocked(EGLDisplay dpy) {              return UNKNOWN_ERROR;          }          glFlush(); -        mEGLSlots[mCurrentTexture].mFence = fence; +        mEglSlots[mCurrentTexture].mEglFence = fence;      }      return OK; @@ -607,10 +577,12 @@ void SurfaceTexture::computeCurrentTransformMatrix() {                      // only need to shrink by a half a pixel.                      shrinkAmount = 0.5;                      break; +                  default:                      // If we don't recognize the format, we must assume the                      // worst case (that we care about), which is YUV420.                      shrinkAmount = 1.0; +                    break;              }          } @@ -650,13 +622,6 @@ nsecs_t SurfaceTexture::getTimestamp() {      return mCurrentTimestamp;  } -void SurfaceTexture::setFrameAvailableListener( -        const sp<FrameAvailableListener>& listener) { -    ST_LOGV("setFrameAvailableListener"); -    Mutex::Autolock lock(mMutex); -    mFrameAvailableListener = listener; -} -  EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,          const sp<GraphicBuffer>& graphicBuffer) {      EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer(); @@ -736,35 +701,21 @@ bool SurfaceTexture::isSynchronousMode() const {  void SurfaceTexture::freeBufferLocked(int slotIndex) {      ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex); -    mEGLSlots[slotIndex].mGraphicBuffer = 0;      if (slotIndex == mCurrentTexture) {          mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;      } -    EGLImageKHR img = mEGLSlots[slotIndex].mEglImage; +    EGLImageKHR img = mEglSlots[slotIndex].mEglImage;      if (img != EGL_NO_IMAGE_KHR) {          ST_LOGV("destroying EGLImage dpy=%p img=%p", mEglDisplay, img);          eglDestroyImageKHR(mEglDisplay, img);      } -    mEGLSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR; +    mEglSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR;  } -void SurfaceTexture::abandon() { -    ST_LOGV("abandon"); -    Mutex::Autolock lock(mMutex); - -    if (!mAbandoned) { -        mAbandoned = true; -        mCurrentTextureBuf.clear(); - -        // destroy all egl buffers -        for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { -            freeBufferLocked(i); -        } - -        // disconnect from the BufferQueue -        mBufferQueue->consumerDisconnect(); -        mBufferQueue.clear(); -    } +void SurfaceTexture::abandonLocked() { +    ST_LOGV("abandonLocked"); +    mCurrentTextureBuf.clear(); +    ConsumerBase::abandonLocked();  }  void SurfaceTexture::setName(const String8& name) { @@ -796,71 +747,18 @@ status_t SurfaceTexture::setSynchronousMode(bool enabled) {      return mBufferQueue->setSynchronousMode(enabled);  } -// Used for refactoring, should not be in final interface -sp<BufferQueue> SurfaceTexture::getBufferQueue() const { -    Mutex::Autolock lock(mMutex); -    return mBufferQueue; -} - -void SurfaceTexture::onFrameAvailable() { -    ST_LOGV("onFrameAvailable"); - -    sp<FrameAvailableListener> listener; -    { // scope for the lock -        Mutex::Autolock lock(mMutex); -        listener = mFrameAvailableListener; -    } - -    if (listener != NULL) { -        ST_LOGV("actually calling onFrameAvailable"); -        listener->onFrameAvailable(); -    } -} - -void SurfaceTexture::onBuffersReleased() { -    ST_LOGV("onBuffersReleased"); - -    Mutex::Autolock lock(mMutex); - -    if (mAbandoned) { -        // Nothing to do if we're already abandoned. -        return; -    } - -    uint32_t mask = 0; -    mBufferQueue->getReleasedBuffers(&mask); -    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { -        if (mask & (1 << i)) { -            freeBufferLocked(i); -        } -    } -} - -void SurfaceTexture::dump(String8& result) const -{ -    char buffer[1024]; -    dump(result, "", buffer, 1024); -} - -void SurfaceTexture::dump(String8& result, const char* prefix, -        char* buffer, size_t SIZE) const +void SurfaceTexture::dumpLocked(String8& result, const char* prefix, +        char* buffer, size_t size) const  { -    Mutex::Autolock _l(mMutex); -    snprintf(buffer, SIZE, "%smTexName=%d, mAbandoned=%d\n", prefix, mTexName, -            int(mAbandoned)); +    snprintf(buffer, size, +       "%smTexName=%d mCurrentTexture=%d\n" +       "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n", +       prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left, +       mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom, +       mCurrentTransform);      result.append(buffer); -    snprintf(buffer, SIZE, -            "%snext   : {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n", -            prefix, mCurrentCrop.left, -            mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom, -            mCurrentTransform, mCurrentTexture -    ); -    result.append(buffer); - -    if (!mAbandoned) { -        mBufferQueue->dump(result, prefix, buffer, SIZE); -    } +    ConsumerBase::dumpLocked(result, prefix, buffer, size);  }  static void mtxMul(float out[16], const float a[16], const float b[16]) {  |