Merge "Revert "Removed dependecies between BufferQueue and SurfaceTexture""
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 8c21a28..dd1558c 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -40,7 +40,6 @@
     };
     enum { NUM_BUFFER_SLOTS = 32 };
     enum { NO_CONNECTED_API = 0 };
-    enum { INVALID_BUFFER_SLOT = -1 };
 
     struct FrameAvailableListener : public virtual RefBase {
         // onFrameAvailable() is called from queueBuffer() each time an
@@ -120,91 +119,8 @@
     // connected to the specified client API.
     virtual status_t disconnect(int api);
 
-    // 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:
 
-    // public facing structure for BufferSlot
-    struct BufferItem {
-
-        BufferItem()
-         :
-           mTransform(0),
-           mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
-           mTimestamp(0),
-           mFrameNumber(0),
-           mBuf(INVALID_BUFFER_SLOT) {
-             mCrop.makeInvalid();
-         }
-        // mGraphicBuffer points to the buffer allocated for this slot or is NULL
-        // if no buffer has been allocated.
-        sp<GraphicBuffer> mGraphicBuffer;
-
-        // mCrop is the current crop rectangle for this buffer slot. This gets
-        // set to mNextCrop each time queueBuffer gets called for this buffer.
-        Rect mCrop;
-
-        // mTransform is the current transform flags for this buffer slot. This
-        // gets set to mNextTransform each time queueBuffer gets called for this
-        // slot.
-        uint32_t mTransform;
-
-        // mScalingMode is the current scaling mode for this buffer slot. This
-        // gets set to mNextScalingMode each time queueBuffer gets called for
-        // this slot.
-        uint32_t mScalingMode;
-
-        // mTimestamp is the current timestamp for this buffer slot. This gets
-        // to set by queueBuffer each time this slot is queued.
-        int64_t mTimestamp;
-
-        // mFrameNumber is the number of the queued frame for this slot.
-        uint64_t mFrameNumber;
-
-        // buf is the slot index of this buffer
-        int mBuf;
-
-    };
-
-    // The following public functions is the consumer facing interface
-
-    // acquire consumes a buffer by transferring its ownership to a consumer.
-    // buffer contains the GraphicBuffer and its corresponding information.
-    // buffer.mGraphicsBuffer will be NULL when the buffer has been already
-    // acquired by the consumer.
-
-    status_t acquire(BufferItem *buffer);
-
-    // releaseBuffer releases a buffer slot from the consumer back to the
-    // BufferQueue pending a fence sync.
-    status_t releaseBuffer(int buf, EGLDisplay display, EGLSyncKHR fence);
-
-    // consumerDisconnect disconnects a consumer from the BufferQueue. All
-    // buffers will be freed.
-    status_t consumerDisconnect();
-
-    // setDefaultBufferSize is used to set the size of buffers returned by
-    // requestBuffers when a with and height of zero is requested.
-    status_t setDefaultBufferSize(uint32_t w, uint32_t h);
-
-    // 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.
-    status_t setBufferCountServer(int bufferCount);
-
-    // isSynchronousMode returns whether the SurfaceTexture is currently in
-    // synchronous mode.
-    bool isSynchronousMode() const;
-
-    // setConsumerName sets the name used in logging
-    void setConsumerName(const String8& name);
-
-    // setFrameAvailableListener sets the listener object that will be notified
-    // when a new frame becomes available.
-    void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
-
-
-private:
     // freeBufferLocked frees the resources (both GraphicBuffer and EGLImage)
     // for the given slot.
     void freeBufferLocked(int index);
@@ -229,18 +145,20 @@
 
     status_t setBufferCountServerLocked(int bufferCount);
 
+    enum { INVALID_BUFFER_SLOT = -1 };
+
     struct BufferSlot {
 
         BufferSlot()
-        : mEglDisplay(EGL_NO_DISPLAY),
+        : mEglImage(EGL_NO_IMAGE_KHR),
+          mEglDisplay(EGL_NO_DISPLAY),
           mBufferState(BufferSlot::FREE),
           mRequestBufferCalled(false),
           mTransform(0),
           mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
           mTimestamp(0),
           mFrameNumber(0),
-          mFence(EGL_NO_SYNC_KHR),
-          mAcquireCalled(false) {
+          mFence(EGL_NO_SYNC_KHR) {
             mCrop.makeInvalid();
         }
 
@@ -248,6 +166,9 @@
         // if no buffer has been allocated.
         sp<GraphicBuffer> mGraphicBuffer;
 
+        // mEglImage is the EGLImage created from mGraphicBuffer.
+        EGLImageKHR mEglImage;
+
         // mEglDisplay is the EGLDisplay used to create mEglImage.
         EGLDisplay mEglDisplay;
 
@@ -257,7 +178,6 @@
             // FREE indicates that the buffer is not currently being used and
             // will not be used in the future until it gets dequeued and
             // subsequently queued by the client.
-            // aka "owned by BufferQueue, ready to be dequeued"
             FREE = 0,
 
             // DEQUEUED indicates that the buffer has been dequeued by the
@@ -270,7 +190,6 @@
             // dequeued by the client.  That means that the current buffer can
             // be in either the DEQUEUED or QUEUED state.  In asynchronous mode,
             // however, the current buffer is always in the QUEUED state.
-            // aka "owned by producer, ready to be queued"
             DEQUEUED = 1,
 
             // QUEUED indicates that the buffer has been queued by the client,
@@ -280,11 +199,7 @@
             // the current buffer may be dequeued by the client under some
             // circumstances. See the note about the current buffer in the
             // documentation for DEQUEUED.
-            // aka "owned by BufferQueue, ready to be acquired"
             QUEUED = 2,
-
-            // aka "owned by consumer, ready to be released"
-            ACQUIRED = 3
         };
 
         // mBufferState is the current state of this buffer slot.
@@ -321,9 +236,6 @@
         // 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;
-
-        // Indicates whether this buffer has been seen by a consumer yet
-        bool mAcquireCalled;
     };
 
     // mSlots is the array of buffer slots that must be mirrored on the client
@@ -333,6 +245,7 @@
     // for a slot when requestBuffer is called with that slot's index.
     BufferSlot mSlots[NUM_BUFFER_SLOTS];
 
+
     // mDefaultWidth holds the default width of allocated buffers. It is used
     // in requestBuffers() if a width and height of zero is specified.
     uint32_t mDefaultWidth;
@@ -358,6 +271,14 @@
     // mServerBufferCount buffer count requested by the server-side
     int mServerBufferCount;
 
+    // mCurrentTexture is the buffer slot index of the buffer that is currently
+    // bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT,
+    // indicating that no buffer slot is currently bound to the texture. Note,
+    // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
+    // that no buffer is bound to the texture. A call to setBufferCount will
+    // reset mCurrentTexture to INVALID_BUFFER_SLOT.
+    int mCurrentTexture;
+
     // mNextCrop is the crop rectangle that will be used for the next buffer
     // that gets queued. It is set by calling setCrop.
     Rect mNextCrop;
@@ -406,7 +327,7 @@
 
     // mName is a string used to identify the BufferQueue in log messages.
     // It is set by the setName method.
-    String8 mConsumerName;
+    String8 mName;
 
     // mMutex is the mutex used to prevent concurrent access to the member
     // variables of BufferQueue objects. It must be locked whenever the
@@ -416,8 +337,6 @@
     // mFrameCounter is the free running counter, incremented for every buffer queued
     // with the surface Texture.
     uint64_t mFrameCounter;
-
-    bool mBufferHasBeenQueued;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 5531e53..dcab049 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -153,8 +153,8 @@
     void setName(const String8& name);
 
     // 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;
+    void dump(String8& result) const;
+    void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
 
 protected:
 
@@ -217,56 +217,6 @@
     // browser's tile cache exceeds.
     const GLenum mTexTarget;
 
-    // SurfaceTexture maintains EGL information about GraphicBuffers that corresponds
-    // directly with BufferQueue's buffers
-    struct EGLSlot {
-        EGLSlot()
-        : mEglImage(EGL_NO_IMAGE_KHR),
-          mEglDisplay(EGL_NO_DISPLAY),
-          mFence(EGL_NO_SYNC_KHR) {
-        }
-
-        sp<GraphicBuffer> mGraphicBuffer;
-
-        // mEglImage is the EGLImage created from mGraphicBuffer.
-        EGLImageKHR mEglImage;
-
-        // mEglDisplay is the EGLDisplay used to create mEglImage.
-        EGLDisplay mEglDisplay;
-
-        // mFence is the EGL sync object that must signal before the buffer
-        // 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;
-    };
-
-    EGLSlot mEGLSlots[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;
-
-    // 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;
-
-    // mCurrentTexture is the buffer slot index of the buffer that is currently
-    // bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT,
-    // indicating that no buffer slot is currently bound to the texture. Note,
-    // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
-    // that no buffer is bound to the texture. A call to setBufferCount will
-    // reset mCurrentTexture to INVALID_BUFFER_SLOT.
-    int mCurrentTexture;
-
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 20c4e3a..261336a 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -15,7 +15,6 @@
  */
 
 #define LOG_TAG "BufferQueue"
-//#define LOG_NDEBUG 0
 
 #define GL_GLEXT_PROTOTYPES
 #define EGL_EGLEXT_PROTOTYPES
@@ -28,7 +27,6 @@
 #include <private/gui/ComposerService.h>
 
 #include <utils/Log.h>
-#include <gui/SurfaceTexture.h>
 
 // This compile option causes SurfaceTexture to return the buffer that is currently
 // attached to the GL texture from dequeueBuffer when no other buffers are
@@ -44,11 +42,11 @@
 #endif
 
 // Macros for including the BufferQueue name in log messages
-#define ST_LOGV(x, ...) ALOGV("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define ST_LOGD(x, ...) ALOGD("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define ST_LOGI(x, ...) ALOGI("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define ST_LOGW(x, ...) ALOGW("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define ST_LOGE(x, ...) ALOGE("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
+#define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define ST_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define ST_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
 
 namespace android {
 
@@ -65,17 +63,17 @@
     mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
     mClientBufferCount(0),
     mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
+    mCurrentTexture(INVALID_BUFFER_SLOT),
     mNextTransform(0),
     mNextScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
     mSynchronousMode(false),
     mAllowSynchronousMode(allowSynchronousMode),
     mConnectedApi(NO_CONNECTED_API),
     mAbandoned(false),
-    mFrameCounter(0),
-    mBufferHasBeenQueued(false)
+    mFrameCounter(0)
 {
     // Choose a name using the PID and a process-unique ID.
-    mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
+    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
 
     ST_LOGV("BufferQueue");
     sp<ISurfaceComposer> composer(ComposerService::getComposerService());
@@ -121,23 +119,6 @@
     return OK;
 }
 
-bool BufferQueue::isSynchronousMode() const {
-    Mutex::Autolock lock(mMutex);
-    return mSynchronousMode;
-}
-
-void BufferQueue::setConsumerName(const String8& name) {
-    Mutex::Autolock lock(mMutex);
-    mConsumerName = name;
-}
-
-void BufferQueue::setFrameAvailableListener(
-        const sp<FrameAvailableListener>& listener) {
-    ST_LOGV("setFrameAvailableListener");
-    Mutex::Autolock lock(mMutex);
-    mFrameAvailableListener = listener;
-}
-
 status_t BufferQueue::setBufferCount(int bufferCount) {
     ST_LOGV("setBufferCount: count=%d", bufferCount);
     Mutex::Autolock lock(mMutex);
@@ -179,7 +160,7 @@
     freeAllBuffersLocked();
     mBufferCount = bufferCount;
     mClientBufferCount = bufferCount;
-    mBufferHasBeenQueued = false;
+    mCurrentTexture = INVALID_BUFFER_SLOT;
     mQueue.clear();
     mDequeueCondition.signal();
     return OK;
@@ -295,7 +276,7 @@
                 mBufferCount = mServerBufferCount;
                 if (mBufferCount < minBufferCountNeeded)
                     mBufferCount = minBufferCountNeeded;
-                mBufferHasBeenQueued = false;
+                mCurrentTexture = INVALID_BUFFER_SLOT;
                 returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
             }
 
@@ -309,10 +290,19 @@
                     dequeuedCount++;
                 }
 
+                // if buffer is FREE it CANNOT be current
+                ALOGW_IF((state == BufferSlot::FREE) && (mCurrentTexture==i),
+                        "dequeueBuffer: buffer %d is both FREE and current!",
+                        i);
+
                 if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER) {
-                    // This functionality has been temporarily removed so
-                    // BufferQueue and SurfaceTexture can be refactored into
-                    // separate objects
+                    if (state == BufferSlot::FREE || i == mCurrentTexture) {
+                        foundSync = i;
+                        if (i != mCurrentTexture) {
+                            found = i;
+                            break;
+                        }
+                    }
                 } else {
                     if (state == BufferSlot::FREE) {
                         /* We return the oldest of the free buffers to avoid
@@ -341,7 +331,8 @@
             // See whether a buffer has been queued since the last
             // setBufferCount so we know whether to perform the
             // MIN_UNDEQUEUED_BUFFERS check below.
-            if (mBufferHasBeenQueued) {
+            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);
@@ -413,23 +404,27 @@
             if (updateFormat) {
                 mPixelFormat = format;
             }
-
-            mSlots[buf].mAcquireCalled = false;
             mSlots[buf].mGraphicBuffer = graphicBuffer;
             mSlots[buf].mRequestBufferCalled = false;
             mSlots[buf].mFence = EGL_NO_SYNC_KHR;
-            mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
-
-
-
-
+            if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
+                eglDestroyImageKHR(mSlots[buf].mEglDisplay,
+                        mSlots[buf].mEglImage);
+                mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
+                mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
+            }
+            if (mCurrentTexture == buf) {
+                // The current texture no longer references the buffer in this slot
+                // since we just allocated a new buffer.
+                mCurrentTexture = INVALID_BUFFER_SLOT;
+            }
             returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
         }
 
         dpy = mSlots[buf].mEglDisplay;
         fence = mSlots[buf].mFence;
         mSlots[buf].mFence = EGL_NO_SYNC_KHR;
-    }  // end lock scope
+    }
 
     if (fence != EGL_NO_SYNC_KHR) {
         EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
@@ -442,7 +437,6 @@
             ALOGE("dequeueBuffer: timeout waiting for fence");
         }
         eglDestroySyncKHR(dpy, fence);
-
     }
 
     ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
@@ -502,6 +496,9 @@
             ST_LOGE("queueBuffer: slot %d is not owned by the client "
                     "(state=%d)", buf, mSlots[buf].mBufferState);
             return -EINVAL;
+        } else if (buf == mCurrentTexture) {
+            ST_LOGE("queueBuffer: slot %d is current!", buf);
+            return -EINVAL;
         } else if (!mSlots[buf].mRequestBufferCalled) {
             ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
                     "buffer", buf);
@@ -541,7 +538,6 @@
         mFrameCounter++;
         mSlots[buf].mFrameNumber = mFrameCounter;
 
-        mBufferHasBeenQueued = true;
         mDequeueCondition.signal();
 
         *outWidth = mDefaultWidth;
@@ -651,9 +647,6 @@
             err = -EINVAL;
             break;
     }
-
-    mBufferHasBeenQueued = false;
-
     return err;
 }
 
@@ -694,185 +687,26 @@
     return err;
 }
 
-void BufferQueue::dump(String8& result) const
-{
-    char buffer[1024];
-    BufferQueue::dump(result, "", buffer, 1024);
-}
-
-void BufferQueue::dump(String8& result, const char* prefix,
-        char* buffer, size_t SIZE) const
-{
-    Mutex::Autolock _l(mMutex);
-    snprintf(buffer, SIZE,
-            "%snext   : {crop=[%d,%d,%d,%d], transform=0x%02x}\n"
-            ,prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right,
-            mNextCrop.bottom, mNextTransform
-    );
-    result.append(buffer);
-
-    String8 fifo;
-    int fifoSize = 0;
-    Fifo::const_iterator i(mQueue.begin());
-    while (i != mQueue.end()) {
-       snprintf(buffer, SIZE, "%02d ", *i++);
-       fifoSize++;
-       fifo.append(buffer);
-    }
-
-    snprintf(buffer, SIZE,
-            "%s-BufferQueue mBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
-            "mPixelFormat=%d, FIFO(%d)={%s}\n",
-            prefix, mBufferCount, mSynchronousMode, mDefaultWidth,
-            mDefaultHeight, mPixelFormat, fifoSize, fifo.string());
-    result.append(buffer);
-
-
-    struct {
-        const char * operator()(int state) const {
-            switch (state) {
-                case BufferSlot::DEQUEUED: return "DEQUEUED";
-                case BufferSlot::QUEUED: return "QUEUED";
-                case BufferSlot::FREE: return "FREE";
-                case BufferSlot::ACQUIRED: return "ACQUIRED";
-                default: return "Unknown";
-            }
-        }
-    } stateName;
-
-    for (int i=0 ; i<mBufferCount ; i++) {
-        const BufferSlot& slot(mSlots[i]);
-        snprintf(buffer, SIZE,
-                "%s%s[%02d] "
-                "state=%-8s, crop=[%d,%d,%d,%d], "
-                "transform=0x%02x, timestamp=%lld",
-                prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i,
-                stateName(slot.mBufferState),
-                slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
-                slot.mCrop.bottom, slot.mTransform, slot.mTimestamp
-        );
-        result.append(buffer);
-
-        const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
-        if (buf != NULL) {
-            snprintf(buffer, SIZE,
-                    ", %p [%4ux%4u:%4u,%3X]",
-                    buf->handle, buf->width, buf->height, buf->stride,
-                    buf->format);
-            result.append(buffer);
-        }
-        result.append("\n");
-    }
-}
-
 void BufferQueue::freeBufferLocked(int i) {
     mSlots[i].mGraphicBuffer = 0;
     mSlots[i].mBufferState = BufferSlot::FREE;
     mSlots[i].mFrameNumber = 0;
-    mSlots[i].mAcquireCalled = false;
-
-    // destroy fence as BufferQueue now takes ownership
-    if (mSlots[i].mFence != EGL_NO_SYNC_KHR) {
-        eglDestroySyncKHR(mSlots[i].mEglDisplay, mSlots[i].mFence);
-        mSlots[i].mFence = EGL_NO_SYNC_KHR;
+    if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
+        eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage);
+        mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
+        mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
     }
 }
 
 void BufferQueue::freeAllBuffersLocked() {
     ALOGW_IF(!mQueue.isEmpty(),
             "freeAllBuffersLocked called but mQueue is not empty");
-    mQueue.clear();
-    mBufferHasBeenQueued = false;
+    mCurrentTexture = INVALID_BUFFER_SLOT;
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         freeBufferLocked(i);
     }
 }
 
-status_t BufferQueue::acquire(BufferItem *buffer) {
-    Mutex::Autolock _l(mMutex);
-    // check if queue is empty
-    // In asynchronous mode the list is guaranteed to be one buffer
-    // deep, while in synchronous mode we use the oldest buffer.
-    if (!mQueue.empty()) {
-        Fifo::iterator front(mQueue.begin());
-        int buf = *front;
-
-        if (mSlots[buf].mAcquireCalled) {
-            buffer->mGraphicBuffer = NULL;
-        }
-        else {
-            buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
-        }
-        buffer->mCrop = mSlots[buf].mCrop;
-        buffer->mTransform = mSlots[buf].mTransform;
-        buffer->mScalingMode = mSlots[buf].mScalingMode;
-        buffer->mFrameNumber = mSlots[buf].mFrameNumber;
-        buffer->mBuf = buf;
-        mSlots[buf].mAcquireCalled = true;
-
-        mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
-        mQueue.erase(front);
-    }
-    else {
-        return -EINVAL; //should be a better return code
-    }
-
-    return OK;
-}
-
-status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display,
-        EGLSyncKHR fence) {
-    Mutex::Autolock _l(mMutex);
-
-    if (buf == INVALID_BUFFER_SLOT) {
-        return -EINVAL;
-    }
-
-    mSlots[buf].mEglDisplay = display;
-    mSlots[buf].mFence = fence;
-
-    // The current buffer becomes FREE if it was still in the queued
-    // state. If it has already been given to the client
-    // (synchronous mode), then it stays in DEQUEUED state.
-    if (mSlots[buf].mBufferState == BufferSlot::QUEUED
-            || mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
-        mSlots[buf].mBufferState = BufferSlot::FREE;
-    }
-    mDequeueCondition.signal();
-
-    return OK;
-}
-
-status_t BufferQueue::consumerDisconnect() {
-    Mutex::Autolock lock(mMutex);
-    // Once the SurfaceTexture disconnects, the BufferQueue
-    // is considered abandoned
-    mAbandoned = true;
-    freeAllBuffersLocked();
-    mDequeueCondition.signal();
-    return OK;
-}
-
-status_t BufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h)
-{
-    ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
-    if (!w || !h) {
-        ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
-                w, h);
-        return BAD_VALUE;
-    }
-
-    Mutex::Autolock lock(mMutex);
-    mDefaultWidth = w;
-    mDefaultHeight = h;
-    return OK;
-}
-
-status_t BufferQueue::setBufferCountServer(int bufferCount) {
-    Mutex::Autolock lock(mMutex);
-    return setBufferCountServerLocked(bufferCount);
-}
-
 void BufferQueue::freeAllBuffersExceptHeadLocked() {
     ALOGW_IF(!mQueue.isEmpty(),
             "freeAllBuffersExceptCurrentLocked called but mQueue is not empty");
@@ -881,7 +715,7 @@
         Fifo::iterator front(mQueue.begin());
         head = *front;
     }
-    mBufferHasBeenQueued = false;
+    mCurrentTexture = INVALID_BUFFER_SLOT;
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         if (i != head) {
             freeBufferLocked(i);
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index e1fd700..5f0013c 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -96,11 +96,6 @@
 
 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) :
@@ -113,13 +108,8 @@
 #else
     mUseFenceSync(false),
 #endif
-    mTexTarget(texTarget),
-    mAbandoned(false),
-    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT)
+    mTexTarget(texTarget)
 {
-    // Choose a name using the PID and a process-unique ID.
-    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
-    BufferQueue::setConsumerName(mName);
 
     ST_LOGV("SurfaceTexture");
     memcpy(mCurrentTransformMatrix, mtxIdentity,
@@ -128,18 +118,28 @@
 
 SurfaceTexture::~SurfaceTexture() {
     ST_LOGV("~SurfaceTexture");
-    abandon();
+    freeAllBuffersLocked();
 }
 
 status_t SurfaceTexture::setBufferCountServer(int bufferCount) {
     Mutex::Autolock lock(mMutex);
-    return BufferQueue::setBufferCountServer(bufferCount);
+    return setBufferCountServerLocked(bufferCount);
 }
 
 
 status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
 {
-    return BufferQueue::setDefaultBufferSize(w, h);
+    ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
+    if (!w || !h) {
+        ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
+                w, h);
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock lock(mMutex);
+    mDefaultWidth = w;
+    mDefaultHeight = h;
+    return OK;
 }
 
 status_t SurfaceTexture::updateTexImage() {
@@ -151,35 +151,23 @@
         return NO_INIT;
     }
 
-    BufferItem item;
-
     // In asynchronous mode the list is guaranteed to be one buffer
     // deep, while in synchronous mode we use the oldest buffer.
-    if (acquire(&item) == 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(mEGLSlots[buf].mEglDisplay,
-                        mEGLSlots[buf].mEglImage);
-                mEGLSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
-                mEGLSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
-            }
-            mEGLSlots[buf].mGraphicBuffer = item.mGraphicBuffer;
-        }
+    if (!mQueue.empty()) {
+        Fifo::iterator front(mQueue.begin());
+        int buf = *front;
 
         // Update the GL texture object.
-        EGLImageKHR image = mEGLSlots[buf].mEglImage;
+        EGLImageKHR image = mSlots[buf].mEglImage;
         EGLDisplay dpy = eglGetCurrentDisplay();
         if (image == EGL_NO_IMAGE_KHR) {
-            if (item.mGraphicBuffer == 0) {
+            if (mSlots[buf].mGraphicBuffer == 0) {
                 ST_LOGE("buffer at slot %d is null", buf);
                 return BAD_VALUE;
             }
-            image = createImage(dpy, item.mGraphicBuffer);
-            mEGLSlots[buf].mEglImage = image;
-            mEGLSlots[buf].mEglDisplay = dpy;
+            image = createImage(dpy, mSlots[buf].mGraphicBuffer);
+            mSlots[buf].mEglImage = image;
+            mSlots[buf].mEglDisplay = dpy;
             if (image == EGL_NO_IMAGE_KHR) {
                 // NOTE: if dpy was invalid, createImage() is guaranteed to
                 // fail. so we'd end up here.
@@ -202,8 +190,6 @@
             failed = true;
         }
         if (failed) {
-            releaseBuffer(buf, mEGLSlots[buf].mEglDisplay,
-                    mEGLSlots[buf].mFence);
             return -EINVAL;
         }
 
@@ -214,37 +200,40 @@
                 if (fence == EGL_NO_SYNC_KHR) {
                     ALOGE("updateTexImage: error creating fence: %#x",
                             eglGetError());
-                    releaseBuffer(buf, mEGLSlots[buf].mEglDisplay,
-                            mEGLSlots[buf].mFence);
                     return -EINVAL;
                 }
                 glFlush();
-                mEGLSlots[mCurrentTexture].mFence = fence;
+                mSlots[mCurrentTexture].mFence = fence;
             }
         }
 
         ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)",
                 mCurrentTexture,
                 mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
-                buf, item.mGraphicBuffer->handle);
+                buf, mSlots[buf].mGraphicBuffer->handle);
 
-        // release old buffer
-        releaseBuffer(mCurrentTexture,
-                mEGLSlots[mCurrentTexture].mEglDisplay,
-                mEGLSlots[mCurrentTexture].mFence);
+        if (mCurrentTexture != INVALID_BUFFER_SLOT) {
+            // The current buffer becomes FREE if it was still in the queued
+            // state. If it has already been given to the client
+            // (synchronous mode), then it stays in DEQUEUED state.
+            if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED) {
+                mSlots[mCurrentTexture].mBufferState = BufferSlot::FREE;
+            }
+        }
 
         // Update the SurfaceTexture state.
         mCurrentTexture = buf;
-        mCurrentTextureBuf = mEGLSlots[buf].mGraphicBuffer;
-        mCurrentCrop = item.mCrop;
-        mCurrentTransform = item.mTransform;
-        mCurrentScalingMode = item.mScalingMode;
-        mCurrentTimestamp = item.mTimestamp;
+        mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
+        mCurrentCrop = mSlots[buf].mCrop;
+        mCurrentTransform = mSlots[buf].mTransform;
+        mCurrentScalingMode = mSlots[buf].mScalingMode;
+        mCurrentTimestamp = mSlots[buf].mTimestamp;
         computeCurrentTransformMatrix();
 
         // Now that we've passed the point at which failures can happen,
         // it's safe to remove the buffer from the front of the queue.
-
+        mQueue.erase(front);
+        mDequeueCondition.signal();
     } else {
         // We always bind the texture even if we don't update its contents.
         glBindTexture(mTexTarget, mTexName);
@@ -310,7 +299,7 @@
         }
     }
 
-    sp<GraphicBuffer>& buf(mCurrentTextureBuf);
+    sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer);
     float tx, ty, sx, sy;
     if (!mCurrentCrop.isEmpty()) {
         // In order to prevent bilinear sampling at the of the crop rectangle we
@@ -382,7 +371,7 @@
         const sp<FrameAvailableListener>& listener) {
     ST_LOGV("setFrameAvailableListener");
     Mutex::Autolock lock(mMutex);
-    BufferQueue::setFrameAvailableListener(listener);
+    mFrameAvailableListener = listener;
 }
 
 EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
@@ -423,33 +412,22 @@
 
 bool SurfaceTexture::isSynchronousMode() const {
     Mutex::Autolock lock(mMutex);
-    return BufferQueue::isSynchronousMode();
+    return mSynchronousMode;
 }
 
+
+
 void SurfaceTexture::abandon() {
     Mutex::Autolock lock(mMutex);
+    mQueue.clear();
     mAbandoned = true;
     mCurrentTextureBuf.clear();
-
-    // destroy all egl buffers
-    for (int i =0; i < NUM_BUFFER_SLOTS; i++) {
-        mEGLSlots[i].mGraphicBuffer = 0;
-        if (mEGLSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
-            eglDestroyImageKHR(mEGLSlots[i].mEglDisplay,
-                    mEGLSlots[i].mEglImage);
-            mEGLSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
-            mEGLSlots[i].mEglDisplay = EGL_NO_DISPLAY;
-        }
-    }
-
-    // disconnect from the BufferQueue
-    BufferQueue::consumerDisconnect();
+    freeAllBuffersLocked();
+    mDequeueCondition.signal();
 }
 
 void SurfaceTexture::setName(const String8& name) {
-    Mutex::Autolock _l(mMutex);
     mName = name;
-    BufferQueue::setConsumerName(name);
 }
 
 void SurfaceTexture::dump(String8& result) const
@@ -462,19 +440,68 @@
         char* buffer, size_t SIZE) const
 {
     Mutex::Autolock _l(mMutex);
-    snprintf(buffer, SIZE, "%smTexName=%d\n", prefix, mTexName);
+    snprintf(buffer, SIZE,
+            "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
+            "mPixelFormat=%d, mTexName=%d\n",
+            prefix, mBufferCount, mSynchronousMode, mDefaultWidth,
+            mDefaultHeight, mPixelFormat, mTexName);
     result.append(buffer);
 
+    String8 fifo;
+    int fifoSize = 0;
+    Fifo::const_iterator i(mQueue.begin());
+    while (i != mQueue.end()) {
+        snprintf(buffer, SIZE, "%02d ", *i++);
+        fifoSize++;
+        fifo.append(buffer);
+    }
+
     snprintf(buffer, SIZE,
-            "%snext   : {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n"
-            ,prefix, mCurrentCrop.left,
+            "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n"
+            "%snext   : {crop=[%d,%d,%d,%d], transform=0x%02x, FIFO(%d)={%s}}\n"
+            ,
+            prefix, mCurrentCrop.left,
             mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
-            mCurrentTransform, mCurrentTexture
+            mCurrentTransform, mCurrentTexture,
+            prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right,
+            mNextCrop.bottom, mNextTransform, fifoSize, fifo.string()
     );
     result.append(buffer);
 
+    struct {
+        const char * operator()(int state) const {
+            switch (state) {
+                case BufferSlot::DEQUEUED: return "DEQUEUED";
+                case BufferSlot::QUEUED: return "QUEUED";
+                case BufferSlot::FREE: return "FREE";
+                default: return "Unknown";
+            }
+        }
+    } stateName;
 
-    BufferQueue::dump(result, prefix, buffer, SIZE);
+    for (int i=0 ; i<mBufferCount ; i++) {
+        const BufferSlot& slot(mSlots[i]);
+        snprintf(buffer, SIZE,
+                "%s%s[%02d] "
+                "state=%-8s, crop=[%d,%d,%d,%d], "
+                "transform=0x%02x, timestamp=%lld",
+                prefix, (i==mCurrentTexture)?">":" ", i,
+                stateName(slot.mBufferState),
+                slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
+                slot.mCrop.bottom, slot.mTransform, slot.mTimestamp
+        );
+        result.append(buffer);
+
+        const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
+        if (buf != NULL) {
+            snprintf(buffer, SIZE,
+                    ", %p [%4ux%4u:%4u,%3X]",
+                    buf->handle, buf->width, buf->height, buf->stride,
+                    buf->format);
+            result.append(buffer);
+        }
+        result.append("\n");
+    }
 }
 
 static void mtxMul(float out[16], const float a[16], const float b[16]) {