Removed dependecies between BufferQueue and SurfaceTexture

Refactored SurfaceTexture and BufferQueue such that share
no protected members.  Created an consumer facing interface
for BufferQueue in preparation of connecting SurfaceTexture
and BufferQueue through a binder.

Change-Id: I938e63e085128148c58d0e26c7213b30145c109f
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 5f0013c..a23a328 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -96,6 +96,11 @@
 
 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) :
@@ -108,8 +113,13 @@
 #else
     mUseFenceSync(false),
 #endif
-    mTexTarget(texTarget)
+    mTexTarget(texTarget),
+    mAbandoned(false),
+    mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT)
 {
+    // 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,
@@ -118,28 +128,18 @@
 
 SurfaceTexture::~SurfaceTexture() {
     ST_LOGV("~SurfaceTexture");
-    freeAllBuffersLocked();
+    abandon();
 }
 
 status_t SurfaceTexture::setBufferCountServer(int bufferCount) {
     Mutex::Autolock lock(mMutex);
-    return setBufferCountServerLocked(bufferCount);
+    return BufferQueue::setBufferCountServer(bufferCount);
 }
 
 
 status_t SurfaceTexture::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;
+    return BufferQueue::setDefaultBufferSize(w, h);
 }
 
 status_t SurfaceTexture::updateTexImage() {
@@ -151,23 +151,35 @@
         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 (!mQueue.empty()) {
-        Fifo::iterator front(mQueue.begin());
-        int buf = *front;
+    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;
+        }
 
         // Update the GL texture object.
-        EGLImageKHR image = mSlots[buf].mEglImage;
+        EGLImageKHR image = mEGLSlots[buf].mEglImage;
         EGLDisplay dpy = eglGetCurrentDisplay();
         if (image == EGL_NO_IMAGE_KHR) {
-            if (mSlots[buf].mGraphicBuffer == 0) {
+            if (item.mGraphicBuffer == 0) {
                 ST_LOGE("buffer at slot %d is null", buf);
                 return BAD_VALUE;
             }
-            image = createImage(dpy, mSlots[buf].mGraphicBuffer);
-            mSlots[buf].mEglImage = image;
-            mSlots[buf].mEglDisplay = dpy;
+            image = createImage(dpy, item.mGraphicBuffer);
+            mEGLSlots[buf].mEglImage = image;
+            mEGLSlots[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.
@@ -190,6 +202,8 @@
             failed = true;
         }
         if (failed) {
+            releaseBuffer(buf, mEGLSlots[buf].mEglDisplay,
+                    mEGLSlots[buf].mFence);
             return -EINVAL;
         }
 
@@ -200,40 +214,37 @@
                 if (fence == EGL_NO_SYNC_KHR) {
                     ALOGE("updateTexImage: error creating fence: %#x",
                             eglGetError());
+                    releaseBuffer(buf, mEGLSlots[buf].mEglDisplay,
+                            mEGLSlots[buf].mFence);
                     return -EINVAL;
                 }
                 glFlush();
-                mSlots[mCurrentTexture].mFence = fence;
+                mEGLSlots[mCurrentTexture].mFence = fence;
             }
         }
 
         ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)",
                 mCurrentTexture,
                 mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
-                buf, mSlots[buf].mGraphicBuffer->handle);
+                buf, item.mGraphicBuffer != NULL ? item.mGraphicBuffer->handle : 0);
 
-        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;
-            }
-        }
+        // release old buffer
+        releaseBuffer(mCurrentTexture,
+                mEGLSlots[mCurrentTexture].mEglDisplay,
+                mEGLSlots[mCurrentTexture].mFence);
 
         // Update the SurfaceTexture state.
         mCurrentTexture = buf;
-        mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
-        mCurrentCrop = mSlots[buf].mCrop;
-        mCurrentTransform = mSlots[buf].mTransform;
-        mCurrentScalingMode = mSlots[buf].mScalingMode;
-        mCurrentTimestamp = mSlots[buf].mTimestamp;
+        mCurrentTextureBuf = mEGLSlots[buf].mGraphicBuffer;
+        mCurrentCrop = item.mCrop;
+        mCurrentTransform = item.mTransform;
+        mCurrentScalingMode = item.mScalingMode;
+        mCurrentTimestamp = item.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);
@@ -299,7 +310,7 @@
         }
     }
 
-    sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer);
+    sp<GraphicBuffer>& buf(mCurrentTextureBuf);
     float tx, ty, sx, sy;
     if (!mCurrentCrop.isEmpty()) {
         // In order to prevent bilinear sampling at the of the crop rectangle we
@@ -371,7 +382,7 @@
         const sp<FrameAvailableListener>& listener) {
     ST_LOGV("setFrameAvailableListener");
     Mutex::Autolock lock(mMutex);
-    mFrameAvailableListener = listener;
+    BufferQueue::setFrameAvailableListener(listener);
 }
 
 EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
@@ -412,22 +423,33 @@
 
 bool SurfaceTexture::isSynchronousMode() const {
     Mutex::Autolock lock(mMutex);
-    return mSynchronousMode;
+    return BufferQueue::isSynchronousMode();
 }
 
-
-
 void SurfaceTexture::abandon() {
     Mutex::Autolock lock(mMutex);
-    mQueue.clear();
     mAbandoned = true;
     mCurrentTextureBuf.clear();
-    freeAllBuffersLocked();
-    mDequeueCondition.signal();
+
+    // 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();
 }
 
 void SurfaceTexture::setName(const String8& name) {
+    Mutex::Autolock _l(mMutex);
     mName = name;
+    BufferQueue::setConsumerName(name);
 }
 
 void SurfaceTexture::dump(String8& result) const
@@ -440,68 +462,19 @@
         char* buffer, size_t SIZE) const
 {
     Mutex::Autolock _l(mMutex);
-    snprintf(buffer, SIZE,
-            "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
-            "mPixelFormat=%d, mTexName=%d\n",
-            prefix, mBufferCount, mSynchronousMode, mDefaultWidth,
-            mDefaultHeight, mPixelFormat, mTexName);
+    snprintf(buffer, SIZE, "%smTexName=%d\n", prefix, 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,
-            "%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,
+            "%snext   : {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n"
+            ,prefix, mCurrentCrop.left,
             mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
-            mCurrentTransform, mCurrentTexture,
-            prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right,
-            mNextCrop.bottom, mNextTransform, fifoSize, fifo.string()
+            mCurrentTransform, mCurrentTexture
     );
     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;
 
-    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");
-    }
+    BufferQueue::dump(result, prefix, buffer, SIZE);
 }
 
 static void mtxMul(float out[16], const float a[16], const float b[16]) {