BufferQueue机制 - 安卓R

本文详细介绍了Android系统中BufferQueue的工作原理及其内部实现机制。主要内容包括BufferQueue的基本概念、Buffer的状态流转过程、生产者与消费者的交互流程等。对于理解Android系统的绘图机制具有重要意义。

BufferQueue介绍

BufferQueue

生产者(一般是app):

1.通过queueBuffer方法从BufferQueue拿到一个Buffer

2.绘制Buffer

3.通过dequeueBuffer方法将绘制好的Buffer传给BufferQueue

消费者(一般是SurfaceFlinger):

1.通过acquireBuffer方法从BufferQueue拿到一个绘制好了的Buffer

2.使用Buffer(SurfaceFlinger让Buffer参与图像合成,最终显示到屏幕上)

3.通过releaseBuffer方法将用过的Buffer传给BufferQueue
buffer状态

Buffer一般有4种状态:

1.FREE

2.DEQUEUED

3.QUEUED

4.ACQUIRED

BufferQueue相关重要类

首先看实现者BufferQueueCore的定义(frameworks/native/libs/gui/include/gui/BufferQueueCore.h、frameworks/native/libs/gui/BufferQueueCore.cpp):

class BufferQueueCore : public virtual RefBase {

    friend class BufferQueueProducer;
    friend class BufferQueueConsumer;

public:
    ......

    typedef Vector<BufferItem> Fifo;

    // BufferQueueCore manages a pool of gralloc memory slots to be used by
    // producers and consumers.
    BufferQueueCore();
    virtual ~BufferQueueCore();

private:
    ......

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

    // mFreeSlots contains all of the slots which are FREE and do not currently
    // have a buffer attached.
    std::set<int> mFreeSlots;

    // mFreeBuffers contains all of the slots which are FREE and currently have
    // a buffer attached.
    std::list<int> mFreeBuffers;

    // mUnusedSlots contains all slots that are currently unused. They should be
    // free and not have a buffer attached.
    std::list<int> mUnusedSlots;

    // mActiveBuffers contains all slots which have a non-FREE buffer attached.
    std::set<int> mActiveBuffers;

    ......
}

BufferQueueCore::BufferQueueCore(): ...... {
    int numStartingBuffers = getMaxBufferCountLocked();
    for (int s = 0; s < numStartingBuffers; s++) {
        mFreeSlots.insert(s);
    }
    for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS; s++) {
        mUnusedSlots.push_front(s);
    }
}

这里成员变量mSlots用BufferSlot存储GraphicBuffer,其中BufferSlot定义如下(frameworks/native/libs/gui/include/gui/BufferQueueDefs.h、frameworks/native/libs/gui/include/gui/BufferSlot.h):

namespace android {
    class BufferQueueCore;

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

struct BufferSlot {

    BufferSlot()
    : mGraphicBuffer(nullptr),
      mEglDisplay(EGL_NO_DISPLAY),
      mBufferState(),
      mRequestBufferCalled(false),
      mFrameNumber(0),
      mEglFence(EGL_NO_SYNC_KHR),
      mFence(Fence::NO_FENCE),
      mAcquireCalled(false),
      mNeedsReallocation(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;

    // 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 the buffer was re-allocated without notifying the
    // producer. If so, it needs to set the BUFFER_NEEDS_REALLOCATION flag when
    // dequeued to prevent the producer from using a stale cached buffer.
    bool mNeedsReallocation;
};

记录Buffer状态的BufferState类定义如下(frameworks/native/libs/gui/include/gui/BufferSlot.h):

// BufferState tracks the states in which a buffer slot can be.
struct BufferState {

    // All slots are initially FREE (not dequeued, queued, acquired, or shared).
    BufferState()
    : mDequeueCount(0),
      mQueueCount(0),
      mAcquireCount(0),
      mShared(false) {
    }

    uint32_t mDequeueCount;
    uint32_t mQueueCount;
    uint32_t mAcquireCount;
    bool mShared;

    // A buffer can be in one of five states, represented as below:
    //
    //         | mShared | mDequeueCount | mQueueCount | mAcquireCount |
    // --------|---------|---------------|-------------|---------------|
    // FREE    |  false  |       0       |      0      |       0       |
    // DEQUEUED|  false  |       1       |      0      |       0       |
    // QUEUED  |  false  |       0       |      1      |       0       |
    // ACQUIRED|  false  |       0       |      0      |       1       |
    // SHARED  |  true   |      any      |     any     |      any      |
    //
    // FREE indicates that the buffer is available to be dequeued by the
    // producer. The slot is "owned" by BufferQueue. It transitions to DEQUEUED
    // when dequeueBuffer is called.
    //
    // 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 release fence is signaled.
    // The slot is "owned" by the producer. It can transition to QUEUED (via
    // queueBuffer or attachBuffer) or back to FREE (via cancelBuffer or
    // detachBuffer).
    //
    // 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).
    //
    // 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
    // acquire fence is signaled. The slot is "owned" by the consumer. It
    // transitions to FREE when releaseBuffer (or detachBuffer) is called. A
    // detached buffer can also enter the ACQUIRED state via attachBuffer.
    //
    // SHARED indicates that this buffer is being used in shared buffer
    // mode. It can be in any combination of the other states at the same time,
    // except for FREE (since that excludes being in any other state). It can
    // also be dequeued, queued, or acquired multiple times.

    inline bool isFree() const {
        return !isAcquired() && !isDequeued() && !isQueued();
    }

    inline bool isDequeued() const {
        return mDequeueCount > 0;
    }

    inline bool isQueued() const {
        return mQueueCount > 0;
    }

    inline bool isAcquired() const {
        return mAcquireCount > 0;
    }

    inline bool isShared() const {
        return mShared;
    }

    inline void reset() {
        *this = BufferState();
    }

    const char* string() const;

    inline void dequeue() {
        mDequeueCount++;
    }

    inline void detachProducer() {
        if (mDequeueCount > 0) {
            mDequeueCount--;
        }
    }

    inline void attachProducer() {
        mDequeueCount++;
    }

    inline void queue() {
        if (mDequeueCount > 0) {
            mDequeueCount--;
        }
        mQueueCount++;
    }

    inline void cancel() {
        if (mDequeueCount > 0) {
            mDequeueCount--;
        }
    }

    inline void freeQueued() {
        if (mQueueCount > 0) {
            mQueueCount--;
        }
    }

    inline void acquire() {
        if (mQueueCount > 0) {
            mQueueCount--;
        }
        mAcquireCount++;
    }

    inline void acquireNotInQueue() {
        mAcquireCount++;
    }

    inline void release() {
        if (mAcquireCount > 0) {
            mAcquireCount--;
        }
    }

    inline void detachConsumer() {
        if (mAcquireCount > 0) {
            mAcquireCount--;
        }
    }

    inline void attachConsumer() {
        mAcquireCount++;
    }
};

BufferSlot中存储的GraphicBuffer定义如下(frameworks/native/libs/ui/include/ui/GraphicBuffer.h):

class GraphicBuffer
    : public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase>,
      public Flattenable<GraphicBuffer>
{
    friend class Flattenable<GraphicBuffer>;
public:

    enum {
        USAGE_SW_READ_NEVER     = GRALLOC_USAGE_SW_READ_NEVER,
        USAGE_SW_READ_RARELY    = GRALLOC_USAGE_SW_READ_RARELY,
        USAGE_SW_READ_OFTEN     = GRALLOC_USAGE_SW_READ_OFTEN,
        USAGE_SW_READ_MASK      = GRALLOC_USAGE_SW_READ_MASK,

        USAGE_SW_WRITE_NEVER    = GRALLOC_USAGE_SW_WRITE_NEVER,
        USAGE_SW_WRITE_RARELY   = GRALLOC_USAGE_SW_WRITE_RARELY,
        USAGE_SW_WRITE_OFTEN    = GRALLOC_USAGE_SW_WRITE_OFTEN,
        USAGE_SW_WRITE_MASK     = GRALLOC_USAGE_SW_WRITE_MASK,

        USAGE_SOFTWARE_MASK     = USAGE_SW_READ_MASK|USAGE_SW_WRITE_MASK,

        USAGE_PROTECTED         = GRALLOC_USAGE_PROTECTED,

        USAGE_HW_TEXTURE        = GRALLOC_USAGE_HW_TEXTURE,
        USAGE_HW_RENDER         = GRALLOC_USAGE_HW_RENDER,
        USAGE_HW_2D             = GRALLOC_USAGE_HW_2D,
        USAGE_HW_COMPOSER       = GRALLOC_USAGE_HW_COMPOSER,
        USAGE_HW_VIDEO_ENCODER  = GRALLOC_USAGE_HW_VIDEO_ENCODER,
        USAGE_HW_MASK           = GRALLOC_USAGE_HW_MASK,

        USAGE_CURSOR            = GRALLOC_USAGE_CURSOR,
    };

    static sp<GraphicBuffer> from(ANativeWindowBuffer *);

    static GraphicBuffer* fromAHardwareBuffer(AHardwareBuffer*);
    static GraphicBuffer const* fromAHardwareBuffer(AHardwareBuffer const*);
    AHardwareBuffer* toAHardwareBuffer();
    AHardwareBuffer const* toAHardwareBuffer() const;

    // Create a GraphicBuffer to be unflatten'ed into or be reallocated.
    GraphicBuffer();

    // Create a GraphicBuffer by allocating and managing a buffer internally.
    // This function is privileged.  See reallocate for details.
    GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
            uint32_t inLayerCount, uint64_t inUsage,
            std::string requestorName = "<Unknown>");

    // Create a GraphicBuffer from an existing handle.
    enum HandleWrapMethod : uint8_t {
        // Wrap and use the handle directly.  It assumes the handle has been
        // registered and never fails.  The handle must have a longer lifetime
        // than this wrapping GraphicBuffer.
        //
        // This can be used when, for example, you want to wrap a handle that
        // is already managed by another GraphicBuffer.
        WRAP_HANDLE,

        // Take ownership of the handle and use it directly.  It assumes the
        // handle has been registered and never fails.
        //
        // This can be used to manage an already registered handle with
        // GraphicBuffer.
        TAKE_HANDLE,

        // Take onwership of an unregistered handle and use it directly.  It
        // can fail when the buffer does not register.  There is no ownership
        // transfer on failures.
        //
        // This can be used to, for example, create a GraphicBuffer from a
        // handle returned by Parcel::readNativeHandle.
        TAKE_UNREGISTERED_HANDLE,

        // Make a clone of the handle and use the cloned handle.  It can fail
        // when cloning fails or when the buffer does not register.  There is
        // never ownership transfer.
        //
        // This can be used to create a GraphicBuffer from a handle that
        // cannot be used directly, such as one from hidl_handle.
        CLONE_HANDLE,
    };
    GraphicBuffer(const native_handle_t* inHandle, HandleWrapMethod method, uint32_t inWidth,
                  uint32_t inHeight, PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage,
                  uint32_t inStride);

    // These functions are deprecated because they only take 32 bits of usage
    GraphicBuffer(const native_handle_t* inHandle, HandleWrapMethod method, uint32_t inWidth,
                  uint32_t inHeight, PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage,
                  uint32_t inStride)
          : GraphicBuffer(inHandle, method, inWidth, inHeight, inFormat, inLayerCount,
                          static_cast<uint64_t>(inUsage), inStride) {}
    GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
            uint32_t inLayerCount, uint32_t inUsage, uint32_t inStride,
            native_handle_t* inHandle, bool keepOwnership);
    GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
            uint32_t inUsage, std::string requestorName = "<Unknown>");

    // return status
    status_t initCheck() const;

    uint32_t getWidth() const           { return static_cast<uint32_t>(width); }
    uint32_t getHeight() const          { return static_cast<uint32_t>(height); }
    uint32_t getStride() const          { return static_cast<uint32_t>(stride); }
    uint64_t getUsage() const           { return usage; }
    PixelFormat getPixelFormat() const  { return format; }
    uint32_t getLayerCount() const      { return static_cast<uint32_t>(layerCount); }
    Rect getBounds() const              { return Rect(width, height); }
    uint64_t getId() const              { return mId; }

    uint32_t getGenerationNumber() const { return mGenerationNumber; }
    void setGenerationNumber(uint32_t generation) {
        mGenerationNumber = generation;
    }

    // This function is privileged.  It requires access to the allocator
    // device or service, which usually involves adding suitable selinux
    // rules.
    status_t reallocate(uint32_t inWidth, uint32_t inHeight,
            PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage);

    bool needsReallocation(uint32_t inWidth, uint32_t inHeight,
            PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage);

    // For the following two lock functions, if bytesPerStride or bytesPerPixel
    // are unknown or variable, -1 will be returned
    status_t lock(uint32_t inUsage, void** vaddr, int32_t* outBytesPerPixel = nullptr,
                  int32_t* outBytesPerStride = nullptr);
    status_t lock(uint32_t inUsage, const Rect& rect, void** vaddr,
                  int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr);
    // For HAL_PIXEL_FORMAT_YCbCr_420_888
    status_t lockYCbCr(uint32_t inUsage, android_ycbcr *ycbcr);
    status_t lockYCbCr(uint32_t inUsage, const Rect& rect,
            android_ycbcr *ycbcr);
    status_t unlock();
    // For the following three lockAsync functions, if bytesPerStride or bytesPerPixel
    // are unknown or variable, -1 will be returned
    status_t lockAsync(uint32_t inUsage, void** vaddr, int fenceFd,
                       int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr);
    status_t lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr, int fenceFd,
                       int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr);
    status_t lockAsync(uint64_t inProducerUsage, uint64_t inConsumerUsage, const Rect& rect,
                       void** vaddr, int fenceFd, int32_t* outBytesPerPixel = nullptr,
                       int32_t* outBytesPerStride = nullptr);
    status_t lockAsyncYCbCr(uint32_t inUsage, android_ycbcr *ycbcr,
            int fenceFd);
    status_t lockAsyncYCbCr(uint32_t inUsage, const Rect& rect,
            android_ycbcr *ycbcr, int fenceFd);
    status_t unlockAsync(int *fenceFd);

    status_t isSupported(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
                         uint32_t inLayerCount, uint64_t inUsage, bool* outSupported) const;

    ANativeWindowBuffer* getNativeBuffer() const;

    // for debugging
    static void dumpAllocationsToSystemLog();

    // Flattenable protocol
    size_t getFlattenedSize() const;
    size_t getFdCount() const;
    status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
    status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);

    GraphicBufferMapper::Version getBufferMapperVersion() const {
        return mBufferMapper.getMapperVersion();
    }

    void addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context);

private:
    ~GraphicBuffer();

    enum {
        ownNone   = 0,
        ownHandle = 1,
        ownData   = 2,
    };

    inline const GraphicBufferMapper& getBufferMapper() const {
        return mBufferMapper;
    }
    inline GraphicBufferMapper& getBufferMapper() {
        return mBufferMapper;
    }
    uint8_t mOwner;

private:
    friend class Surface;
    friend class BpSurface;
    friend class BnSurface;
    friend class LightRefBase<GraphicBuffer>;
    GraphicBuffer(const GraphicBuffer& rhs);
    GraphicBuffer& operator = (const GraphicBuffer& rhs);
    const GraphicBuffer& operator = (const GraphicBuffer& rhs) const;

    status_t initWithSize(uint32_t inWidth, uint32_t inHeight,
            PixelFormat inFormat, uint32_t inLayerCount,
            uint64_t inUsage, std::string requestorName);

    status_t initWithHandle(const native_handle_t* inHandle, HandleWrapMethod method,
                            uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
                            uint32_t inLayerCount, uint64_t inUsage, uint32_t inStride);

    void free_handle();

    GraphicBufferMapper& mBufferMapper;
    ssize_t mInitCheck;

    // numbers of fds/ints in native_handle_t to flatten
    uint32_t mTransportNumFds;
    uint32_t mTransportNumInts;

    uint64_t mId;

    // Unused, but removing this may break GSI.
    int32_t mBufferId = -1;

    // Stores the generation number of this buffer. If this number does not
    // match the BufferQueue's internal generation number (set through
    // IGBP::setGenerationNumber), attempts to attach the buffer will fail.
    uint32_t mGenerationNumber;

    // Send a callback when a GraphicBuffer dies.
    //
    // This is used for BufferStateLayer caching. GraphicBuffers are refcounted per process. When
    // A GraphicBuffer doesn't have any more sp<> in a process, it is destroyed. This causes
    // problems when trying to implicitcly cache across process boundaries. Ideally, both sides
    // of the cache would hold onto wp<> references. When an app dropped its sp<>, the GraphicBuffer
    // would be destroyed. Unfortunately, when SurfaceFlinger has only a wp<> reference to the
    // GraphicBuffer, it immediately goes out of scope in the SurfaceFlinger process. SurfaceFlinger
    // must hold onto a sp<> to the buffer. When the GraphicBuffer goes out of scope in the app's
    // process, the client side cache will get this callback. It erases the buffer from its cache
    // and informs SurfaceFlinger that it should drop its strong pointer reference to the buffer.
    std::vector<std::pair<GraphicBufferDeathCallback, void* /*mDeathCallbackContext*/>>
            mDeathCallbacks;
};

接下来看BufferQueue的定义(frameworks/native/libs/gui/include/gui/BufferQueue.h、frameworks/native/libs/gui/BufferQueue.cpp):

class BufferQueue {
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 = BufferQueueDefs::NUM_BUFFER_SLOTS };  // 64
    // Used as a placeholder slot# when the value isn't pointing to an existing buffer.
    enum { INVALID_BUFFER_SLOT = BufferItem::INVALID_BUFFER_SLOT };  // -1
    // Alias to <IGraphicBufferConsumer.h> -- please scope from there in future code!
    enum {
        NO_BUFFER_AVAILABLE = IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
        PRESENT_LATER = IGraphicBufferConsumer::PRESENT_LATER,
    };

    // When in async mode 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 };

    // for backward source compatibility
    typedef ::android::ConsumerListener ConsumerListener;

    // ProxyConsumerListener is a ConsumerListener implementation that keeps a weak
    // reference to the actual consumer object.  It forwards all calls to that
    // consumer object so long as it exists.
    //
    // This class exists to avoid having a circular reference between the
    // BufferQueue object and the consumer object.  The reason this can't be a weak
    // reference in the BufferQueue class is because we're planning to expose the
    // consumer side of a BufferQueue as a binder interface, which doesn't support
    // weak references.
    class ProxyConsumerListener : public BnConsumerListener {
    public:
        explicit ProxyConsumerListener(const wp<ConsumerListener>& consumerListener);
        ~ProxyConsumerListener() override;
        void onDisconnect() override;
        void onFrameAvailable(const BufferItem& item) override;
        void onFrameReplaced(const BufferItem& item) override;
        void onBuffersReleased() override;
        void onSidebandStreamChanged() override;
        void onFrameDequeued(const uint64_t bufferId) override;
        void onFrameCancelled(const uint64_t bufferId) override;
        void onFrameDetached(const uint64_t bufferID) override;
        void addAndGetFrameTimestamps(
                const NewFrameEventsEntry* newTimestamps,
                FrameEventHistoryDelta* outDelta) override;
    private:
        // mConsumerListener is a weak reference to the IConsumerListener.  This is
        // the raison d'etre of ProxyConsumerListener.
        wp<ConsumerListener> mConsumerListener;
    };

    // 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.
    static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
            sp<IGraphicBufferConsumer>* outConsumer,
            bool consumerIsSurfaceFlinger = false);

#ifndef NO_BUFFERHUB
    // Creates an IGraphicBufferProducer and IGraphicBufferConsumer pair backed by BufferHub.
    static void createBufferHubQueue(sp<IGraphicBufferProducer>* outProducer,
                                     sp<IGraphicBufferConsumer>* outConsumer);
#endif

    BufferQueue() = delete; // Create through createBufferQueue
};

void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
        sp<IGraphicBufferConsumer>* outConsumer,
        bool consumerIsSurfaceFlinger) {
    LOG_ALWAYS_FATAL_IF(outProducer == nullptr,
            "BufferQueue: outProducer must not be NULL");
    LOG_ALWAYS_FATAL_IF(outConsumer == nullptr,
            "BufferQueue: outConsumer must not be NULL");

    sp<BufferQueueCore> core(new BufferQueueCore());
    LOG_ALWAYS_FATAL_IF(core == nullptr,
            "BufferQueue: failed to create BufferQueueCore");

    sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
    LOG_ALWAYS_FATAL_IF(producer == nullptr,
            "BufferQueue: failed to create BufferQueueProducer");

    sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
    LOG_ALWAYS_FATAL_IF(consumer == nullptr,
            "BufferQueue: failed to create BufferQueueConsumer");

    *outProducer = producer;
    *outConsumer = consumer;
}

通过createBufferQueue方法得到一个BufferQueueProducer和一个BufferQueueConsumer,并且创建了一个BufferQueueCore传给了他们。

Buffer状态转移流程

生产者通过dequeueBuffer拿到slot(frameworks/native/libs/gui/BufferQueueProducer.cpp):

status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* outFence,
                                            uint32_t width, uint32_t height, PixelFormat format,
                                            uint64_t usage, uint64_t* outBufferAge,
                                            FrameEventHistoryDelta* outTimestamps) {
    ......
    { // Autolock scope
        std::unique_lock<std::mutex> lock(mCore->mMutex);
        ......
        int found = BufferItem::INVALID_BUFFER_SLOT;
        while (found == BufferItem::INVALID_BUFFER_SLOT) {
            status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue, lock, &found);  // 找可用的FreeSlot
            ......
        }

        const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
        ......
        if (mCore->mSharedBufferSlot != found) {
            mCore->mActiveBuffers.insert(found);
        }
        *outSlot = found;
        ......
        mSlots[found].mBufferState.dequeue();  // Buffer的状态变为DEQUEUED
        ......
        if (!(returnFlags & BUFFER_NEEDS_REALLOCATION)) {
            if (mCore->mConsumerListener != nullptr) {
                mCore->mConsumerListener->onFrameDequeued(mSlots[*outSlot].mGraphicBuffer->getId());
            }
        }
    } // Autolock scope
    ......
    return returnFlags;
}

再通过requestBuffer拿到buffer(frameworks/native/libs/gui/BufferQueueProducer.cpp):

status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
    ......
    std::lock_guard<std::mutex> lock(mCore->mMutex);
    ......
    mSlots[slot].mRequestBufferCalled = true;
    *buf = mSlots[slot].mGraphicBuffer;
    return NO_ERROR;
}

buffer绘制完成后,要调用queueBuffer了(frameworks/native/libs/gui/BufferQueueProducer.cpp):

status_t BufferQueueProducer::queueBuffer(int slot,
        const QueueBufferInput &input, QueueBufferOutput *output) {
    ......
    { // Autolock scope
        std::lock_guard<std::mutex> lock(mCore->mMutex);
        ......
        const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
        ......
        mSlots[slot].mBufferState.queue();  // Buffer的状态变成QUEUED
        ......
        output->bufferReplaced = false;
        if (mCore->mQueue.empty()) {
            // When the queue is empty, we can ignore mDequeueBufferCannotBlock
            // and simply queue this buffer
            mCore->mQueue.push_back(item);
            frameAvailableListener = mCore->mConsumerListener;
        } else {
            // When the queue is not empty, we need to look at the last buffer
            // in the queue to see if we need to replace it
            const BufferItem& last = mCore->mQueue.itemAt(
                    mCore->mQueue.size() - 1);
            if (last.mIsDroppable) {
                ......
            } else {
                mCore->mQueue.push_back(item);
                frameAvailableListener = mCore->mConsumerListener;
            }
        }
        ......
    } // Autolock scope
    ......
    { // scope for the lock
        std::unique_lock<std::mutex> lock(mCallbackMutex);
        ......
        if (frameAvailableListener != nullptr) {
            frameAvailableListener->onFrameAvailable(item);
        } else if (frameReplacedListener != nullptr) {
            frameReplacedListener->onFrameReplaced(item);
        }
        ......
    }

    // Wait without lock held
    if (connectedApi == NATIVE_WINDOW_API_EGL) {
        // Waiting here allows for two full buffers to be queued but not a
        // third. In the event that frames take varying time, this makes a
        // small trade-off in favor of latency rather than throughput.
        lastQueuedFence->waitForever("Throttling EGL Production");
    }

    return NO_ERROR;
}

消费者调用acquireBuffer拿到buffer(frameworks/native/libs/gui/BufferQueueConsumer.cpp):

status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
        nsecs_t expectedPresent, uint64_t maxFrameNumber) {
    ......
    {
        std::unique_lock<std::mutex> lock(mCore->mMutex);
        ......
        // In asynchronous mode the list is guaranteed to be one buffer deep,
        // while in synchronous mode we use the oldest buffer.
        if (mCore->mQueue.empty() && !sharedBufferAvailable) {
            return NO_BUFFER_AVAILABLE;
        }

        BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());

        // If expectedPresent is specified, we may not want to return a buffer yet.
        // If it's specified and there's more than one buffer queued, we may want
        // to drop a buffer.
        // Skip this if we're in shared buffer mode and the queue is empty,
        // since in that case we'll just return the shared buffer.
        if (expectedPresent != 0 && !mCore->mQueue.empty()) {
            ......
        }

        int slot = BufferQueueCore::INVALID_BUFFER_SLOT;

        if (sharedBufferAvailable && mCore->mQueue.empty()) {
            ......
        } else {
            slot = front->mSlot;
            *outBuffer = *front;
        }
        ......
        if (!outBuffer->mIsStale) {
            mSlots[slot].mAcquireCalled = true;
            // Don't decrease the queue count if the BufferItem wasn't
            // previously in the queue. This happens in shared buffer mode when
            // the queue is empty and the BufferItem is created above.
            if (mCore->mQueue.empty()) {
                mSlots[slot].mBufferState.acquireNotInQueue();
            } else {
                mSlots[slot].mBufferState.acquire();  // Buffer状态变为ACQUIRED
            }
            mSlots[slot].mFence = Fence::NO_FENCE;
        }
        ......
        mCore->mQueue.erase(front);
        ......
    }

    if (listener != nullptr) {
        for (int i = 0; i < numDroppedBuffers; ++i) {
            listener->onBufferReleased();
        }
    }

    return NO_ERROR;
}

buffer消费完毕后,要调用releaseBuffer了(frameworks/native/libs/gui/BufferQueueConsumer.cpp):

status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
        const sp<Fence>& releaseFence, EGLDisplay eglDisplay,
        EGLSyncKHR eglFence) {
    ......
    { // Autolock scope
        std::lock_guard<std::mutex> lock(mCore->mMutex);
        ......
        mSlots[slot].mEglDisplay = eglDisplay;
        mSlots[slot].mEglFence = eglFence;
        mSlots[slot].mFence = releaseFence;
        mSlots[slot].mBufferState.release();  // Buffer状态变成FREE
        ......
        // Don't put the shared buffer on the free list.
        if (!mSlots[slot].mBufferState.isShared()) {
            mCore->mActiveBuffers.erase(slot);
            mCore->mFreeBuffers.push_back(slot);
        }
        ......
    } // Autolock scope

    // Call back without lock held
    if (listener != nullptr) {
        listener->onBufferReleased();
    }

    return NO_ERROR;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SSSxCCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值