Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f3053de authored by Dan Stoza's avatar Dan Stoza
Browse files

BufferQueue: Allow detaching/reattaching buffers

Adds detachBuffer and attachBuffer calls to both the producer and
consumer sides of BufferQueue. Buffers may be detached while dequeued
by the producer or acquired by the consumer, and when attached, enter
the dequeued and acquired states, respectively.

Bug: 13173343
Change-Id: Ic152692b0a94d99e0135b9bfa62747dab2a54220
parent 544b0952
Loading
Loading
Loading
Loading
+54 −3
Original line number Diff line number Diff line
@@ -28,10 +28,43 @@
#include <binder/IBinder.h>

namespace android {
// ----------------------------------------------------------------------------

class BufferQueue : public BnGraphicBufferProducer,
                    public BnGraphicBufferConsumer,
// BQProducer and BQConsumer are thin shim classes to allow methods with the
// same signature in both IGraphicBufferProducer and IGraphicBufferConsumer.
// This will stop being an issue when we deprecate creating BufferQueues
// directly (as opposed to using the *Producer and *Consumer interfaces).
class BQProducer : public BnGraphicBufferProducer {
public:
    virtual status_t detachProducerBuffer(int slot) = 0;
    virtual status_t attachProducerBuffer(int* slot,
            const sp<GraphicBuffer>& buffer) = 0;

    virtual status_t detachBuffer(int slot) {
        return detachProducerBuffer(slot);
    }

    virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer) {
        return attachProducerBuffer(slot, buffer);
    }
};

class BQConsumer : public BnGraphicBufferConsumer {
public:
    virtual status_t detachConsumerBuffer(int slot) = 0;
    virtual status_t attachConsumerBuffer(int* slot,
            const sp<GraphicBuffer>& buffer) = 0;

    virtual status_t detachBuffer(int slot) {
        return detachConsumerBuffer(slot);
    }

    virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer) {
        return attachConsumerBuffer(slot, buffer);
    }
};

class BufferQueue : public BQProducer,
                    public BQConsumer,
                    private IBinder::DeathRecipient {
public:
    // BufferQueue will keep track of at most this value of buffers.
@@ -73,6 +106,10 @@ public:
        wp<ConsumerListener> mConsumerListener;
    };

    static void createBufferQueue(sp<BnGraphicBufferProducer>* outProducer,
            sp<BnGraphicBufferConsumer>* outConsumer,
            const sp<IGraphicBufferAlloc>& allocator = NULL);

    // BufferQueue manages a pool of gralloc memory slots to be used by
    // producers and consumers. allocator is used to allocate all the
    // needed gralloc buffers.
@@ -157,6 +194,13 @@ public:
    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
            uint32_t width, uint32_t height, uint32_t format, uint32_t usage);

    // See IGraphicBufferProducer::detachBuffer
    virtual status_t detachProducerBuffer(int slot);

    // See IGraphicBufferProducer::attachBuffer
    virtual status_t attachProducerBuffer(int* slot,
            const sp<GraphicBuffer>& buffer);

    // queueBuffer returns a filled buffer to the BufferQueue.
    //
    // Additional data is provided in the QueueBufferInput struct.  Notably,
@@ -223,6 +267,13 @@ public:
    // is CLOCK_MONOTONIC.
    virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen);

    // See IGraphicBufferConsumer::detachBuffer
    virtual status_t detachConsumerBuffer(int slot);

    // See IGraphicBufferConsumer::attachBuffer
    virtual status_t attachConsumerBuffer(int* slot,
            const sp<GraphicBuffer>& buffer);

    // 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
+6 −0
Original line number Diff line number Diff line
@@ -49,6 +49,12 @@ public:
    virtual status_t acquireBuffer(BufferItem* outBuffer,
            nsecs_t expectedPresent);

    // See IGraphicBufferConsumer::detachBuffer
    virtual status_t detachBuffer(int slot);

    // See IGraphicBufferConsumer::attachBuffer
    virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer);

    // 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
+14 −0
Original line number Diff line number Diff line
@@ -96,6 +96,12 @@ public:
    virtual status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence, bool async,
            uint32_t width, uint32_t height, uint32_t format, uint32_t usage);

    // See IGraphicBufferProducer::detachBuffer
    virtual status_t detachBuffer(int slot);

    // See IGraphicBufferProducer::attachBuffer
    virtual status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer);

    // queueBuffer returns a filled buffer to the BufferQueue.
    //
    // Additional data is provided in the QueueBufferInput struct.  Notably,
@@ -151,6 +157,14 @@ private:
    // This is required by the IBinder::DeathRecipient interface
    virtual void binderDied(const wp<IBinder>& who);

    // waitForFreeSlotThenRelock finds the oldest slot in the FREE state. It may
    // block if there are no available slots and we are not in non-blocking
    // mode (producer and consumer controlled by the application). If it blocks,
    // it will release mCore->mMutex while blocked so that other operations on
    // the BufferQueue may succeed.
    status_t waitForFreeSlotThenRelock(const char* caller, bool async,
            int* found, status_t* returnFlags) const;

    sp<BufferQueueCore> mCore;

    // This references mCore->mSlots. Lock mCore->mMutex while accessing.
+7 −1
Original line number Diff line number Diff line
@@ -38,7 +38,8 @@ struct BufferSlot {
      mFrameNumber(0),
      mEglFence(EGL_NO_SYNC_KHR),
      mAcquireCalled(false),
      mNeedsCleanupOnRelease(false) {
      mNeedsCleanupOnRelease(false),
      mAttachedByConsumer(false) {
    }

    // mGraphicBuffer points to the buffer allocated for this slot or is NULL
@@ -129,6 +130,11 @@ struct BufferSlot {
    // consumer.  This is set when a buffer in ACQUIRED state is freed.
    // It causes releaseBuffer to return STALE_BUFFER_SLOT.
    bool mNeedsCleanupOnRelease;

    // Indicates whether the buffer was attached on the consumer side.
    // If so, it needs to set the BUFFER_NEEDS_REALLOCATION flag when dequeued
    // to prevent the producer from using a stale cached buffer.
    bool mAttachedByConsumer;
};

} // namespace android
+30 −0
Original line number Diff line number Diff line
@@ -139,6 +139,36 @@ public:
    // * INVALID_OPERATION - too many buffers have been acquired
    virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen) = 0;

    // detachBuffer attempts to remove all ownership of the buffer in the given
    // slot from the buffer queue. If this call succeeds, the slot will be
    // freed, and there will be no way to obtain the buffer from this interface.
    // The freed slot will remain unallocated until either it is selected to
    // hold a freshly allocated buffer in dequeueBuffer or a buffer is attached
    // to the slot. The buffer must have already been acquired.
    //
    // Return of a value other than NO_ERROR means an error has occurred:
    // * BAD_VALUE - the given slot number is invalid, either because it is
    //               out of the range [0, NUM_BUFFER_SLOTS) or because the slot
    //               it refers to is not currently acquired.
    virtual status_t detachBuffer(int slot) = 0;

    // attachBuffer attempts to transfer ownership of a buffer to the buffer
    // queue. If this call succeeds, it will be as if this buffer was acquired
    // from the returned slot number. As such, this call will fail if attaching
    // this buffer would cause too many buffers to be simultaneously acquired.
    //
    // If the buffer is successfully attached, its frameNumber is initialized
    // to 0. This must be passed into the releaseBuffer call or else the buffer
    // will be deallocated as stale.
    //
    // Return of a value other than NO_ERROR means an error has occurred:
    // * BAD_VALUE - outSlot or buffer were NULL
    // * INVALID_OPERATION - cannot attach the buffer because it would cause too
    //                       many buffers to be acquired.
    // * NO_MEMORY - no free slots available
    virtual status_t attachBuffer(int *outSlot,
            const sp<GraphicBuffer>& buffer) = 0;

    // 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
Loading