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/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 34264bf..8475a71 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -240,7 +240,8 @@
            mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
            mTimestamp(0),
            mFrameNumber(0),
-           mBuf(INVALID_BUFFER_SLOT) {
+           mBuf(INVALID_BUFFER_SLOT),
+           mAcquireCalled(false) {
              mCrop.makeInvalid();
         }
         // mGraphicBuffer points to the buffer allocated for this slot, or is NULL
@@ -269,6 +270,9 @@
 
         // mFence is a fence that will signal when the buffer is idle.
         sp<Fence> mFence;
+
+        // Indicates whether this buffer has been seen by a consumer yet
+        bool mAcquireCalled;
     };
 
     // The following public functions are the consumer-facing interface
@@ -285,7 +289,7 @@
     // releaseBuffer releases a buffer slot from the consumer back to the
     // BufferQueue.  This may be done while the buffer's contents are still
     // being accessed.  The fence will signal when the buffer is no longer
-    // in use.
+    // in use. frameNumber is used to indentify the exact buffer returned.
     //
     // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free
     // any references to the just-released buffer that it might have, as if it
@@ -294,7 +298,8 @@
     //
     // Note that the dependencies on EGL will be removed once we switch to using
     // the Android HW Sync HAL.
-    status_t releaseBuffer(int buf, EGLDisplay display, EGLSyncKHR fence,
+    status_t releaseBuffer(int buf, uint64_t frameNumber,
+            EGLDisplay display, EGLSyncKHR fence,
             const sp<Fence>& releaseFence);
 
     // consumerConnect connects a consumer to the BufferQueue.  Only one
@@ -410,20 +415,20 @@
     // connected, mDequeueCondition must be broadcast.
     int getMaxBufferCountLocked() const;
 
+    // stillTracking returns true iff the buffer item is still being tracked
+    // in one of the slots.
+    bool stillTracking(const BufferItem *item) const;
+
     struct BufferSlot {
 
         BufferSlot()
         : mEglDisplay(EGL_NO_DISPLAY),
           mBufferState(BufferSlot::FREE),
           mRequestBufferCalled(false),
-          mTransform(0),
-          mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
-          mTimestamp(0),
           mFrameNumber(0),
           mEglFence(EGL_NO_SYNC_KHR),
           mAcquireCalled(false),
           mNeedsCleanupOnRelease(false) {
-            mCrop.makeInvalid();
         }
 
         // mGraphicBuffer points to the buffer allocated for this slot or is NULL
@@ -482,21 +487,6 @@
         // needed but useful for debugging and catching producer bugs.
         bool mRequestBufferCalled;
 
-        // mCrop is the current crop rectangle for this buffer slot.
-        Rect mCrop;
-
-        // mTransform is the current transform flags for this buffer slot.
-        // (example: NATIVE_WINDOW_TRANSFORM_ROT_90)
-        uint32_t mTransform;
-
-        // mScalingMode is the current scaling mode for this buffer slot.
-        // (example: NATIVE_WINDOW_SCALING_MODE_FREEZE)
-        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.  This
         // is used to dequeue buffers in LRU order (useful because buffers
         // may be released before their release fence is signaled).
@@ -592,7 +582,7 @@
     mutable Condition mDequeueCondition;
 
     // mQueue is a FIFO of queued buffers used in synchronous mode
-    typedef Vector<int> Fifo;
+    typedef Vector<BufferItem> Fifo;
     Fifo mQueue;
 
     // mAbandoned indicates that the BufferQueue will no longer be used to
@@ -613,7 +603,7 @@
     mutable Mutex mMutex;
 
     // mFrameCounter is the free running counter, incremented on every
-    // successful queueBuffer call.
+    // successful queueBuffer call, and buffer allocation.
     uint64_t mFrameCounter;
 
     // mBufferHasBeenQueued is true once a buffer has been queued.  It is
diff --git a/include/gui/ConsumerBase.h b/include/gui/ConsumerBase.h
index 6250d8f..1d51bc9 100644
--- a/include/gui/ConsumerBase.h
+++ b/include/gui/ConsumerBase.h
@@ -160,17 +160,23 @@
     // Derived classes should override this method to perform any cleanup that
     // must take place when a buffer is released back to the BufferQueue.  If
     // it is overridden the derived class's implementation must call
-    // ConsumerBase::releaseBufferLocked.
-    virtual status_t releaseBufferLocked(int buf, EGLDisplay display,
-           EGLSyncKHR eglFence);
+    // ConsumerBase::releaseBufferLocked.e
+    virtual status_t releaseBufferLocked(int slot,
+            const sp<GraphicBuffer> graphicBuffer,
+            EGLDisplay display, EGLSyncKHR eglFence);
+
+    // returns true iff the slot still has the graphicBuffer in it.
+    bool stillTracking(int slot, const sp<GraphicBuffer> graphicBuffer);
 
     // addReleaseFence* adds the sync points associated with a fence to the set
     // of sync points that must be reached before the buffer in the given slot
     // may be used after the slot has been released.  This should be called by
     // derived classes each time some asynchronous work is kicked off that
     // references the buffer.
-    status_t addReleaseFence(int slot, const sp<Fence>& fence);
-    status_t addReleaseFenceLocked(int slot, const sp<Fence>& fence);
+    status_t addReleaseFence(int slot,
+            const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence);
+    status_t addReleaseFenceLocked(int slot,
+            const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence);
 
     // Slot contains the information and object references that
     // ConsumerBase maintains about a BufferQueue buffer slot.
@@ -184,6 +190,9 @@
         // overwritten. The buffer can be dequeued before the fence signals;
         // the producer is responsible for delaying writes until it signals.
         sp<Fence> mFence;
+
+        // the frame number of the last acquired frame for this slot
+        uint64_t mFrameNumber;
     };
 
     // mSlots stores the buffers that have been allocated by the BufferQueue
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index 1e88927..031684e 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -241,11 +241,13 @@
 
     // 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);
+    virtual status_t releaseBufferLocked(int slot,
+            const sp<GraphicBuffer> graphicBuffer,
+            EGLDisplay display, EGLSyncKHR eglFence);
 
-    status_t releaseBufferLocked(int buf, EGLSyncKHR eglFence) {
-        return releaseBufferLocked(buf, mEglDisplay, eglFence);
+    status_t releaseBufferLocked(int slot,
+            const sp<GraphicBuffer> graphicBuffer, EGLSyncKHR eglFence) {
+        return releaseBufferLocked(slot, graphicBuffer, mEglDisplay, eglFence);
     }
 
     static bool isExternalFormat(uint32_t format);