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);