BufferQueue: track buffer-queue by instance vs. by reference

Instead of representing the buffer-queue as a vector of buffer
indices, represent them as a vector of BufferItems (copies).
This allows modifying the buffer slots independent of the queued
buffers.

As part of this change, BufferSlot properties that are only
been relevant in the buffer-queue have been removed.

Also, invalid scalingMode in queueBuffer now returns an error.

ConsumerBase has also changed to allow reuse of the same
buffer slots by different buffers.

Change-Id: If2a698fa142b67c69ad41b8eaca6e127eb3ef75b
Signed-off-by: Lajos Molnar <lajos@google.com>
Related-to-bug: 7093648
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 344a93a..6d29edc 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -188,12 +188,16 @@
     return NO_ERROR;
 }
 
-status_t GLConsumer::releaseBufferLocked(int buf, EGLDisplay display,
-       EGLSyncKHR eglFence) {
-    status_t err = ConsumerBase::releaseBufferLocked(buf, display, eglFence);
-
+status_t GLConsumer::releaseBufferLocked(int buf,
+        sp<GraphicBuffer> graphicBuffer,
+        EGLDisplay display, EGLSyncKHR eglFence) {
+    // release the buffer if it hasn't already been discarded by the
+    // BufferQueue. This can happen, for example, when the producer of this
+    // buffer has reallocated the original buffer slot after this buffer
+    // was acquired.
+    status_t err = ConsumerBase::releaseBufferLocked(
+            buf, graphicBuffer, display, eglFence);
     mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
-
     return err;
 }
 
@@ -237,7 +241,10 @@
     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.
-        releaseBufferLocked(buf, mEglDisplay, EGL_NO_SYNC_KHR);
+        // As we are still under lock since acquireBuffer, it is safe to
+        // release by slot.
+        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
+                mEglDisplay, EGL_NO_SYNC_KHR);
         return err;
     }
 
@@ -248,7 +255,8 @@
 
     // release old buffer
     if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
-        status_t status = releaseBufferLocked(mCurrentTexture, mEglDisplay,
+        status_t status = releaseBufferLocked(
+                mCurrentTexture, mCurrentTextureBuf, mEglDisplay,
                 mEglSlots[mCurrentTexture].mEglFence);
         if (status != NO_ERROR && status != BufferQueue::STALE_BUFFER_SLOT) {
             ST_LOGE("releaseAndUpdate: failed to release buffer: %s (%d)",
@@ -334,7 +342,8 @@
 void GLConsumer::setReleaseFence(const sp<Fence>& fence) {
     if (fence->isValid() &&
             mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
-        status_t err = addReleaseFence(mCurrentTexture, fence);
+        status_t err = addReleaseFence(mCurrentTexture,
+                mCurrentTextureBuf, fence);
         if (err != OK) {
             ST_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
                     strerror(-err), err);
@@ -503,7 +512,8 @@
                 return UNKNOWN_ERROR;
             }
             sp<Fence> fence(new Fence(fenceFd));
-            status_t err = addReleaseFenceLocked(mCurrentTexture, fence);
+            status_t err = addReleaseFenceLocked(mCurrentTexture,
+                    mCurrentTextureBuf, fence);
             if (err != OK) {
                 ST_LOGE("syncForReleaseLocked: error adding release fence: "
                         "%s (%d)", strerror(-err), err);