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

Commit c1ef3efe authored by Dan Stoza's avatar Dan Stoza Committed by Android (Google) Code Review
Browse files

Merge "Change BufferQueue into producer/consumer wrapper"

parents 52badfb3 3e96f198
Loading
Loading
Loading
Loading
+8 −271
Original line number Diff line number Diff line
@@ -17,22 +17,15 @@
#ifndef ANDROID_GUI_BUFFERQUEUE_H
#define ANDROID_GUI_BUFFERQUEUE_H

#include <EGL/egl.h>
#include <EGL/eglext.h>

#include <binder/IBinder.h>

#include <gui/BufferQueueProducer.h>
#include <gui/BufferQueueConsumer.h>
#include <gui/IConsumerListener.h>
#include <gui/IGraphicBufferAlloc.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/IGraphicBufferConsumer.h>

#include <ui/Fence.h>
#include <ui/GraphicBuffer.h>
// These are only required to keep other parts of the framework with incomplete
// dependencies building successfully
#include <gui/IGraphicBufferAlloc.h>

#include <utils/String8.h>
#include <utils/Vector.h>
#include <utils/threads.h>
#include <binder/IBinder.h>

namespace android {
// ----------------------------------------------------------------------------
@@ -317,264 +310,8 @@ public:
    virtual void dump(String8& result, const char* prefix) const;

private:
    // The default API number used to indicate no producer client is connected.
    enum { NO_CONNECTED_API = 0 };

    // Aliases for using enums from <IGraphicBufferConsumer.h>
    enum { STALE_BUFFER_SLOT = IGraphicBufferConsumer::STALE_BUFFER_SLOT };

    // freeBufferLocked frees the GraphicBuffer and sync resources for the
    // given slot.
    void freeBufferLocked(int index);

    // freeAllBuffersLocked frees the GraphicBuffer and sync resources for
    // all slots.
    void freeAllBuffersLocked();

    // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
    // that will be used if the producer does not override the buffer slot
    // count.  The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
    // The initial default is 2.
    status_t setDefaultMaxBufferCountLocked(int count);

    // getMinUndequeuedBufferCount returns the minimum number of buffers
    // that must remain in a state other than DEQUEUED.
    // The async parameter tells whether we're in asynchronous mode.
    int getMinUndequeuedBufferCount(bool async) const;

    // getMinBufferCountLocked returns the minimum number of buffers allowed
    // given the current BufferQueue state.
    // The async parameter tells whether we're in asynchronous mode.
    int getMinMaxBufferCountLocked(bool async) const;

    // getMaxBufferCountLocked returns the maximum number of buffers that can
    // be allocated at once.  This value depends upon the following member
    // variables:
    //
    //      mDequeueBufferCannotBlock
    //      mMaxAcquiredBufferCount
    //      mDefaultMaxBufferCount
    //      mOverrideMaxBufferCount
    //      async parameter
    //
    // Any time one of these member variables is changed while a producer is
    // connected, mDequeueCondition must be broadcast.
    int getMaxBufferCountLocked(bool async) 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),
          mFrameNumber(0),
          mEglFence(EGL_NO_SYNC_KHR),
          mAcquireCalled(false),
          mNeedsCleanupOnRelease(false) {
        }

        // mGraphicBuffer points to the buffer allocated for this slot or is NULL
        // if no buffer has been allocated.
        sp<GraphicBuffer> mGraphicBuffer;

        // mEglDisplay is the EGLDisplay used to create EGLSyncKHR objects.
        EGLDisplay mEglDisplay;

        // BufferState represents the different states in which a buffer slot
        // can be.  All slots are initially FREE.
        enum BufferState {
            // FREE indicates that the buffer is available to be dequeued
            // by the producer.  The buffer may be in use by the consumer for
            // a finite time, so the buffer must not be modified until the
            // associated fence is signaled.
            //
            // The slot is "owned" by BufferQueue.  It transitions to DEQUEUED
            // when dequeueBuffer is called.
            FREE = 0,

            // DEQUEUED indicates that the buffer has been dequeued by the
            // producer, but has not yet been queued or canceled.  The
            // producer may modify the buffer's contents as soon as the
            // associated ready fence is signaled.
            //
            // The slot is "owned" by the producer.  It can transition to
            // QUEUED (via queueBuffer) or back to FREE (via cancelBuffer).
            DEQUEUED = 1,

            // QUEUED indicates that the buffer has been filled by the
            // producer and queued for use by the consumer.  The buffer
            // contents may continue to be modified for a finite time, so
            // the contents must not be accessed until the associated fence
            // is signaled.
            //
            // The slot is "owned" by BufferQueue.  It can transition to
            // ACQUIRED (via acquireBuffer) or to FREE (if another buffer is
            // queued in asynchronous mode).
            QUEUED = 2,

            // ACQUIRED indicates that the buffer has been acquired by the
            // consumer.  As with QUEUED, the contents must not be accessed
            // by the consumer until the fence is signaled.
            //
            // The slot is "owned" by the consumer.  It transitions to FREE
            // when releaseBuffer is called.
            ACQUIRED = 3
        };

        // mBufferState is the current state of this buffer slot.
        BufferState mBufferState;

        // mRequestBufferCalled is used for validating that the producer did
        // call requestBuffer() when told to do so. Technically this is not
        // needed but useful for debugging and catching producer bugs.
        bool mRequestBufferCalled;

        // 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).
        uint64_t mFrameNumber;

        // mEglFence is the EGL sync object that must signal before the buffer
        // associated with this buffer slot may be dequeued. It is initialized
        // to EGL_NO_SYNC_KHR when the buffer is created and may be set to a
        // new sync object in releaseBuffer.  (This is deprecated in favor of
        // mFence, below.)
        EGLSyncKHR mEglFence;

        // mFence is a fence which will signal when work initiated by the
        // previous owner of the buffer is finished. When the buffer is FREE,
        // the fence indicates when the consumer has finished reading
        // from the buffer, or when the producer has finished writing if it
        // called cancelBuffer after queueing some writes. When the buffer is
        // QUEUED, it indicates when the producer has finished filling the
        // buffer. When the buffer is DEQUEUED or ACQUIRED, the fence has been
        // passed to the consumer or producer along with ownership of the
        // buffer, and mFence is set to NO_FENCE.
        sp<Fence> mFence;

        // Indicates whether this buffer has been seen by a consumer yet
        bool mAcquireCalled;

        // Indicates whether this buffer needs to be cleaned up by the
        // consumer.  This is set when a buffer in ACQUIRED state is freed.
        // It causes releaseBuffer to return STALE_BUFFER_SLOT.
        bool mNeedsCleanupOnRelease;
    };

    // mSlots is the array of buffer slots that must be mirrored on the
    // producer side. This allows buffer ownership to be transferred between
    // the producer and consumer without sending a GraphicBuffer over binder.
    // The entire array is initialized to NULL at construction time, and
    // buffers are allocated for a slot when requestBuffer is called with
    // that slot's index.
    BufferSlot mSlots[NUM_BUFFER_SLOTS];

    // mDefaultWidth holds the default width of allocated buffers. It is used
    // in dequeueBuffer() if a width and height of zero is specified.
    uint32_t mDefaultWidth;

    // mDefaultHeight holds the default height of allocated buffers. It is used
    // in dequeueBuffer() if a width and height of zero is specified.
    uint32_t mDefaultHeight;

    // mMaxAcquiredBufferCount is the number of buffers that the consumer may
    // acquire at one time.  It defaults to 1 and can be changed by the
    // consumer via the setMaxAcquiredBufferCount method, but this may only be
    // done when no producer is connected to the BufferQueue.
    //
    // This value is used to derive the value returned for the
    // MIN_UNDEQUEUED_BUFFERS query by the producer.
    int mMaxAcquiredBufferCount;

    // mDefaultMaxBufferCount is the default limit on the number of buffers
    // that will be allocated at one time.  This default limit is set by the
    // consumer.  The limit (as opposed to the default limit) may be
    // overridden by the producer.
    int mDefaultMaxBufferCount;

    // mOverrideMaxBufferCount is the limit on the number of buffers that will
    // be allocated at one time. This value is set by the image producer by
    // calling setBufferCount. The default is zero, which means the producer
    // doesn't care about the number of buffers in the pool. In that case
    // mDefaultMaxBufferCount is used as the limit.
    int mOverrideMaxBufferCount;

    // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
    // allocate new GraphicBuffer objects.
    sp<IGraphicBufferAlloc> mGraphicBufferAlloc;

    // mConsumerListener is used to notify the connected consumer of
    // asynchronous events that it may wish to react to.  It is initially set
    // to NULL and is written by consumerConnect and consumerDisconnect.
    sp<IConsumerListener> mConsumerListener;

    // mConsumerControlledByApp whether the connected consumer is controlled by the
    // application.
    bool mConsumerControlledByApp;

    // mDequeueBufferCannotBlock whether dequeueBuffer() isn't allowed to block.
    // this flag is set during connect() when both consumer and producer are controlled
    // by the application.
    bool mDequeueBufferCannotBlock;

    // mUseAsyncBuffer whether an extra buffer is used in async mode to prevent
    // dequeueBuffer() from ever blocking.
    bool mUseAsyncBuffer;

    // mConnectedApi indicates the producer API that is currently connected
    // to this BufferQueue.  It defaults to NO_CONNECTED_API (= 0), and gets
    // updated by the connect and disconnect methods.
    int mConnectedApi;

    // mDequeueCondition condition used for dequeueBuffer in synchronous mode
    mutable Condition mDequeueCondition;

    // mQueue is a FIFO of queued buffers used in synchronous mode
    typedef Vector<BufferItem> Fifo;
    Fifo mQueue;

    // mAbandoned indicates that the BufferQueue will no longer be used to
    // consume image buffers pushed to it using the IGraphicBufferProducer
    // interface.  It is initialized to false, and set to true in the
    // consumerDisconnect method.  A BufferQueue that has been abandoned will
    // return the NO_INIT error from all IGraphicBufferProducer methods
    // capable of returning an error.
    bool mAbandoned;

    // mConsumerName is a string used to identify the BufferQueue in log
    // messages.  It is set by the setConsumerName method.
    String8 mConsumerName;

    // mMutex is the mutex used to prevent concurrent access to the member
    // variables of BufferQueue objects. It must be locked whenever the
    // member variables are accessed.
    mutable Mutex mMutex;

    // mFrameCounter is the free running counter, incremented on every
    // successful queueBuffer call, and buffer allocation.
    uint64_t mFrameCounter;

    // mBufferHasBeenQueued is true once a buffer has been queued.  It is
    // reset when something causes all buffers to be freed (e.g. changing the
    // buffer count).
    bool mBufferHasBeenQueued;

    // mDefaultBufferFormat can be set so it will override
    // the buffer format when it isn't specified in dequeueBuffer
    uint32_t mDefaultBufferFormat;

    // mConsumerUsageBits contains flags the consumer wants for GraphicBuffers
    uint32_t mConsumerUsageBits;

    // mTransformHint is used to optimize for screen rotations
    uint32_t mTransformHint;

    // mConnectedProducerToken is used to set a binder death notification on the producer
    sp<IBinder> mConnectedProducerToken;
    sp<BufferQueueProducer> mProducer;
    sp<BufferQueueConsumer> mConsumer;
};

// ----------------------------------------------------------------------------
+27 −3
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>

#include <gui/BufferQueueCore.h>
#include <gui/BufferQueueDefs.h>
#include <gui/IGraphicBufferConsumer.h>

namespace android {
@@ -136,10 +136,34 @@ public:
    // dump our state in a String
    virtual void dump(String8& result, const char* prefix) const;

    // Functions required for backwards compatibility.
    // These will be modified/renamed in IGraphicBufferConsumer and will be
    // removed from this class at that time. See b/13306289.

    virtual status_t releaseBuffer(int buf, uint64_t frameNumber,
            EGLDisplay display, EGLSyncKHR fence,
            const sp<Fence>& releaseFence) {
        return releaseBuffer(buf, frameNumber, releaseFence, display, fence);
    }

    virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
            bool controlledByApp) {
        return connect(consumer, controlledByApp);
    }

    virtual status_t consumerDisconnect() { return disconnect(); }

    // End functions required for backwards compatibility

private:
    sp<BufferQueueCore> mCore;
    BufferQueueCore::SlotsType& mSlots;
    String8 mConsumerName; // Cached from mCore. Updated on setConsumerName.

    // This references mCore->mSlots. Lock mCore->mMutex while accessing.
    BufferQueueDefs::SlotsType& mSlots;

    // This is a cached copy of the name stored in the BufferQueueCore.
    // It's updated during setConsumerName.
    String8 mConsumerName;

}; // class BufferQueueConsumer

+125 −8
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#ifndef ANDROID_GUI_BUFFERQUEUECORE_H
#define ANDROID_GUI_BUFFERQUEUECORE_H

#include <gui/BufferQueueDefs.h>
#include <gui/BufferSlot.h>

#include <utils/Condition.h>
@@ -54,22 +55,17 @@ class BufferQueueCore : public virtual RefBase {
    friend class BufferQueueConsumer;

public:
    // BufferQueue will keep track of at most this value of buffers. Attempts
    // at runtime to increase the number of buffers past this will fail.
    enum { NUM_BUFFER_SLOTS = 32 };

    // Used as a placeholder slot number when the value isn't pointing to an
    // existing buffer.
    enum { INVALID_BUFFER_SLOT = -1 }; // TODO: Extract from IGBC::BufferItem

    // We reserve two slots in order to guarantee that the producer and
    // consumer can run asynchronously.
    enum { MAX_MAX_ACQUIRED_BUFFERS = NUM_BUFFER_SLOTS - 2 };
    enum { MAX_MAX_ACQUIRED_BUFFERS = BufferQueueDefs::NUM_BUFFER_SLOTS - 2 };

    // The default API number used to indicate that no producer is connected
    enum { NO_CONNECTED_API = 0 };

    typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];
    typedef Vector<BufferItem> Fifo;

    // BufferQueueCore manages a pool of gralloc memory slots to be used by
@@ -79,38 +75,159 @@ public:
    virtual ~BufferQueueCore();

private:
    // Dump our state in a string
    void dump(String8& result, const char* prefix) const;

    // getMinUndequeuedBufferCountLocked returns the minimum number of buffers
    // that must remain in a state other than DEQUEUED. The async parameter
    // tells whether we're in asynchronous mode.
    int getMinUndequeuedBufferCountLocked(bool async) const;

    // getMinMaxBufferCountLocked returns the minimum number of buffers allowed
    // given the current BufferQueue state. The async parameter tells whether
    // we're in asynchonous mode.
    int getMinMaxBufferCountLocked(bool async) const;

    // getMaxBufferCountLocked returns the maximum number of buffers that can be
    // allocated at once. This value depends on the following member variables:
    //
    //     mDequeueBufferCannotBlock
    //     mMaxAcquiredBufferCount
    //     mDefaultMaxBufferCount
    //     mOverrideMaxBufferCount
    //     async parameter
    //
    // Any time one of these member variables is changed while a producer is
    // connected, mDequeueCondition must be broadcast.
    int getMaxBufferCountLocked(bool async) const;

    // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
    // that will be used if the producer does not override the buffer slot
    // count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. The
    // initial default is 2.
    status_t setDefaultMaxBufferCountLocked(int count);

    // freeBufferLocked frees the GraphicBuffer and sync resources for the
    // given slot.
    void freeBufferLocked(int slot);

    // freeAllBuffersLocked frees the GraphicBuffer and sync resources for
    // all slots.
    void freeAllBuffersLocked();

    // stillTracking returns true iff the buffer item is still being tracked
    // in one of the slots.
    bool stillTracking(const BufferItem* item) const;

    const sp<IGraphicBufferAlloc>& mAllocator;
    // mAllocator is the connection to SurfaceFlinger that is used to allocate
    // new GraphicBuffer objects.
    sp<IGraphicBufferAlloc> mAllocator;

    // mMutex is the mutex used to prevent concurrent access to the member
    // variables of BufferQueueCore objects. It must be locked whenever any
    // member variable is accessed.
    mutable Mutex mMutex;

    // mIsAbandoned indicates that the BufferQueue will no longer be used to
    // consume image buffers pushed to it using the IGraphicBufferProducer
    // interface. It is initialized to false, and set to true in the
    // consumerDisconnect method. A BufferQueue that is abandoned will return
    // the NO_INIT error from all IGraphicBufferProducer methods capable of
    // returning an error.
    bool mIsAbandoned;

    // mConsumerControlledByApp indicates whether the connected consumer is
    // controlled by the application.
    bool mConsumerControlledByApp;

    // mConsumerName is a string used to identify the BufferQueue in log
    // messages. It is set by the IGraphicBufferConsumer::setConsumerName
    // method.
    String8 mConsumerName;

    // mConsumerListener is used to notify the connected consumer of
    // asynchronous events that it may wish to react to. It is initially
    // set to NULL and is written by consumerConnect and consumerDisconnect.
    sp<IConsumerListener> mConsumerListener;

    // mConsumerUsageBits contains flags that the consumer wants for
    // GraphicBuffers.
    uint32_t mConsumerUsageBits;

    // mConnectedApi indicates the producer API that is currently connected
    // to this BufferQueue. It defaults to NO_CONNECTED_API, and gets updated
    // by the connect and disconnect methods.
    int mConnectedApi;

    // mConnectedProducerToken is used to set a binder death notification on
    // the producer.
    sp<IBinder> mConnectedProducerToken;
    BufferSlot mSlots[NUM_BUFFER_SLOTS];

    // mSlots is an array of buffer slots that must be mirrored on the producer
    // side. This allows buffer ownership to be transferred between the producer
    // and consumer without sending a GraphicBuffer over Binder. The entire
    // array is initialized to NULL at construction time, and buffers are
    // allocated for a slot when requestBuffer is called with that slot's index.
    BufferQueueDefs::SlotsType mSlots;

    // mQueue is a FIFO of queued buffers used in synchronous mode.
    Fifo mQueue;

    // mOverrideMaxBufferCount is the limit on the number of buffers that will
    // be allocated at one time. This value is set by the producer by calling
    // setBufferCount. The default is 0, which means that the producer doesn't
    // care about the number of buffers in the pool. In that case,
    // mDefaultMaxBufferCount is used as the limit.
    int mOverrideMaxBufferCount;

    // mDequeueCondition is a condition variable used for dequeueBuffer in
    // synchronous mode.
    mutable Condition mDequeueCondition;

    // mUseAsyncBuffer indicates whether an extra buffer is used in async mode
    // to prevent dequeueBuffer from blocking.
    bool mUseAsyncBuffer;

    // mDequeueBufferCannotBlock indicates whether dequeueBuffer is allowed to
    // block. This flag is set during connect when both the producer and
    // consumer are controlled by the application.
    bool mDequeueBufferCannotBlock;

    // mDefaultBufferFormat can be set so it will override the buffer format
    // when it isn't specified in dequeueBuffer.
    uint32_t mDefaultBufferFormat;

    // mDefaultWidth holds the default width of allocated buffers. It is used
    // in dequeueBuffer if a width and height of 0 are specified.
    int mDefaultWidth;

    // mDefaultHeight holds the default height of allocated buffers. It is used
    // in dequeueBuffer if a width and height of 0 are specified.
    int mDefaultHeight;

    // mDefaultMaxBufferCount is the default limit on the number of buffers that
    // will be allocated at one time. This default limit is set by the consumer.
    // The limit (as opposed to the default limit) may be overriden by the
    // producer.
    int mDefaultMaxBufferCount;

    // mMaxAcquiredBufferCount is the number of buffers that the consumer may
    // acquire at one time. It defaults to 1, and can be changed by the consumer
    // via setMaxAcquiredBufferCount, but this may only be done while no
    // producer is connected to the BufferQueue. This value is used to derive
    // the value returned for the MIN_UNDEQUEUED_BUFFERS query to the producer.
    int mMaxAcquiredBufferCount;

    // mBufferHasBeenQueued is true once a buffer has been queued. It is reset
    // when something causes all buffers to be freed (e.g., changing the buffer
    // count).
    bool mBufferHasBeenQueued;

    // mFrameCounter is the free running counter, incremented on every
    // successful queueBuffer call and buffer allocation.
    uint64_t mFrameCounter;

    // mTransformHint is used to optimize for screen rotations.
    uint32_t mTransformHint;

}; // class BufferQueueCore
+35 −0
Original line number Diff line number Diff line
/*
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_GUI_BUFFERQUEUECOREDEFS_H
#define ANDROID_GUI_BUFFERQUEUECOREDEFS_H

#include <gui/BufferSlot.h>

namespace android {
    class BufferQueueCore;

    namespace BufferQueueDefs {
        // BufferQueue will keep track of at most this value of buffers.
        // Attempts at runtime to increase the number of buffers past this
        // will fail.
        enum { NUM_BUFFER_SLOTS = 32 };

        typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];
    } // namespace BufferQueueDefs
} // namespace android

#endif
+6 −3
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
#ifndef ANDROID_GUI_BUFFERQUEUEPRODUCER_H
#define ANDROID_GUI_BUFFERQUEUEPRODUCER_H

#include <gui/BufferQueueCore.h>
#include <gui/BufferQueueDefs.h>
#include <gui/IGraphicBufferProducer.h>

namespace android {
@@ -26,8 +26,9 @@ class BufferSlot;

class BufferQueueProducer : public BnGraphicBufferProducer,
                            private IBinder::DeathRecipient {

public:
    friend class BufferQueue; // Needed to access binderDied

    BufferQueueProducer(const sp<BufferQueueCore>& core);
    virtual ~BufferQueueProducer();

@@ -151,7 +152,9 @@ private:
    virtual void binderDied(const wp<IBinder>& who);

    sp<BufferQueueCore> mCore;
    BufferQueueCore::SlotsType& mSlots;

    // This references mCore->mSlots. Lock mCore->mMutex while accessing.
    BufferQueueDefs::SlotsType& mSlots;

    // This is a cached copy of the name stored in the BufferQueueCore.
    // It's updated during connect and dequeueBuffer (which should catch
Loading