美文网首页
BufferQueue分析:Buffer队列

BufferQueue分析:Buffer队列

作者: 泡面先生_Jack | 来源:发表于2020-01-04 17:43 被阅读0次

    Buffer队列的创建

    从Suface创建流程中分析可以,创建每一个Layer的时候,在Layer初始化的时候会为当前Layer创建一个BufferQueue队列,用于App端的Surface和SurfaceFlinger端的Layer间图像传递。

        // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
        sp<IGraphicBufferProducer> producer;
        sp<IGraphicBufferConsumer> consumer;
        BufferQueue::createBufferQueue(&producer, &consumer);
        mProducer = new MonitoredProducer(producer, mFlinger);
        mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);
        mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
        mSurfaceFlingerConsumer->setContentsChangedListener(this);
        mSurfaceFlingerConsumer->setName(mName);
    

    这段代码在Surface创建流程中已经分析过了
    1:BufferQueue创建了一个的生产者和一个消费者
    2:生产者被封装到了MonitoredProducer中,传递了App端,由Surface持有其代理
    3:消费这被封装到了SurfaceFlingerComsumer中,设置Layer为内容变换监听者,当有新的Buffer到来,Layer进行处理。

    先看下如何创建Buffer队列

        sp<IGraphicBufferProducer> producer;
        sp<IGraphicBufferConsumer> consumer;
        BufferQueue::createBufferQueue(&producer, &consumer);
    

    初始化一个producer指针和一个consumer指针作为出参给创建BufferQueue的函数。创建好BufferQueue之后,会将BufferQueue的生产者和消费者分别保存在这两个变量中。

    void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
            sp<IGraphicBufferConsumer>* outConsumer,
            const sp<IGraphicBufferAlloc>& allocator) {
        //创建一个BufferQueueCore对象
        sp<BufferQueueCore> core(new BufferQueueCore(allocator));
        //创建一个BufferQueueProducer
        sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core));
        //创建一个BufferQueueConsumer
        sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
    
        //将创建的producer和consumer分别保存在出参中
        *outProducer = producer;
        *outConsumer = consumer;
    }
    

    createBufferQueue是BufferQueue的静态函数,该函数中首先创建了一个BufferQueueCore对象,然后再以该对象作为参数创建了BufferQueueProducer和BufferQueueConsumer。

    BufferQueueCore定义

    class BufferQueueCore : public virtual RefBase {
        friend class BufferQueueProducer;
        friend class BufferQueueConsumer;
    
    public:
      
        typedef Vector<BufferItem> Fifo;
    
    
    private:
        sp<IGraphicBufferAlloc> mAllocator;
    
        // mMutex 用于同步producer和consumer对BufferQueueCore中变量的访问
        mutable Mutex mMutex;
    
        // mIsAbandoned 表示BufferQueue是否还能处理生产者传递的图像
        bool mIsAbandoned;
    
        // mConsumerName 用来在日志中表示唯一的BufferQueue
        String8 mConsumerName;
    
        // mConsumerListener 用于通知已经连接的Consumer有新Buffer到来
        sp<IConsumerListener> mConsumerListener;
    
        // mConnectedApi 表示生产者是否已经连接到BufferQueue
        int mConnectedApi;
    
        // mConnectedProducerToken 用于通知生产者BufferQueue是否已经死亡
        sp<IProducerListener> mConnectedProducerListener;
    
        // mSlots 是一个大小为64的bufferSlot数组,每个BufferSlot描述了一个GraphicBuffer与其相关的属性
        BufferQueueDefs::SlotsType mSlots;
    
        // mQueue is a FIFO of queued buffers used in synchronous mode.
        Fifo mQueue;
    
        // mFreeSlots 表示所有的FREE状态的BufferSlot, 这个BufferSlot还没有分配GraphicBuffer缓冲区
        std::set<int> mFreeSlots;
    
        // mFreeBuffers 表示所有的FREE状态的BufferSlot, 这个BufferSlot已经分配了GraphicBuffer缓冲区
        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 所有包含有使用状态GraphicBuffer的slot.
        std::set<int> mActiveBuffers;
    
        // mDequeueCondition 用于dequeuebuffer的同步
        mutable Condition mDequeueCondition;
    
    
        // mDefaultBufferFormat BufferQueue分配的GraphicBuffer的默认format
        PixelFormat mDefaultBufferFormat;
    
        // mDefaultWidth BufferQueue分配的GraphicBuffer的默认width
        uint32_t mDefaultWidth;
    
        // mDefaultHeight BufferQueue分配的GraphicBuffer的默认height
        uint32_t mDefaultHeight;
    
        // mDefaultBufferDataSpace BufferQueue分配的GraphicBuffer的默认DataSpace
        android_dataspace mDefaultBufferDataSpace;
    
        // mMaxBufferCount BufferQueue可以分配的GraphicBuffer的最大数量. 可以被consumer设置.
        int mMaxBufferCount;
    
        // mMaxAcquiredBufferCount Consumer一次可以acquire Buffer的最大数量,默认为1
        int mMaxAcquiredBufferCount;
    
        // mMaxDequeuedBufferCount Producer一次可以dqueue Buffer的最大数量,默认为1
        int mMaxDequeuedBufferCount;
    
        // mBufferHasBeenQueued 当有buffer queue到队列中时设置为true, 当释放掉所有buffer的时候设置为false
        bool mBufferHasBeenQueued;
    
        // mFrameCounter 每当队列中queuebuffer的之后 +1
        uint64_t mFrameCounter;
    
        // mTransformHint screen rotations标志.
        uint32_t mTransformHint;
    
        // mSidebandStream is a handle to the sideband buffer stream
        sp<NativeHandle> mSidebandStream;
    
        // mIsAllocating 表明生产者是否正在请求Gralloc分配GraphicBuffer
        bool mIsAllocating;
    
        // mAllowAllocation 表明 dequeueBuffer 是否允许请求Gralloc分配新的GraphicBuffer
        bool mAllowAllocation;
    
    
        // mAsyncMode 是否启用异步模式:生产者将graphicBuffer入队的时候不会block
        bool mAsyncMode;
    
        // mSharedBufferMode 是否启用share模式
        bool mSharedBufferMode;
    
        // ShareBufferMode情况下,即使producer没有通知有新的Buffer可用,consumer也会去获取Buffer
        bool mAutoRefresh;
    
        // 上一次queue buffer的slot
        int mLastQueuedSlot;
    
        const uint64_t mUniqueId;
    
    }; // class BufferQueueCore
    

    BufferQueueCore是BufferQueue的核心,定义了Buffer队列一些基本的属性,BufferQueueProducer和BufferQueueConsumer持有同一个BufferQueueCore对象,所以生产者和消费者都可以访问BufferQueue定义的属性。
    BufferQueue中定义了一些关键的熟悉

    1:BufferQueueDefs::SlotsType mSlots;

    mSlots是一个大小为64的BufferSlot数组,表示一个Buffer队列中最多可以有64个Buffer。BufferSlot是一个GraphicBuffer的封装类,定义了和GraphicBuffer相关的一些属性。
    如:GraphicBuffer指针,指向一个Gralloc分配的GraphicBuffer。
    BufferState, 描述了当前slot位置Buffer的状态。BufferState定义的状态分为以下几种:

      1. FREE:当前这个BufferSlot的所有者为BufferQueue,当前状态可以被Producer调用dequeue方法从队列中取出。当Producer调用dequeue方法获取这个BufferSlot之后,状态会切换成DEQUEUED。
      1. DEQUEUED:当前BufferSlot被Producer从队列中dequeue出来,但是此时Producer仍然不能填充或者修改Buffer内容,直到上一个使用Buffer的消费者发出释放Buffer的Fence信号之后才可以。此时Buffer归生产者所有。当生产者填充完成调用queue方法将其放入队列之后会切换为QUEUED状态,或者调用取消重新切换为FREE状态。
      1. QUEUED:此时Buffer被生产者调用queue方法放入队列,归BufferQueue所属。此时这个slot描述的Buffer可以被Consumer取走。
      1. ACQUIRED:Buffer被Consumer调用acquire方法从队列取走之后,状态变为ACQUIRED状态,此时Consumer并不可访问Buffer的内容,直到收到相关的Fence信号才可以。

    2:其他Slot列表

    set<int> mFreeSlots -- 表示mSlots中处于FREE状态的BufferSlot,而且此时BufferSlot还没有分配真正的GraphicBuffer

    list<int> mFreeBuffers -- 表示mSlots中处于FREE状态的BufferSlot, 且此BufferSlot已经分配了真正的GraphicBuffer。

    set<int> mActiveBuffers -- 表示mSlots所有有GraphicBuffer且不属于FREE状态的slot。

    BufferQueueCore中其他的属性也已经在注释中解释过了,不在一一分析。

    BufferQueueProducer定义

    
    class BufferQueueProducer : public BnGraphicBufferProducer,
                                private IBinder::DeathRecipient {
    ...
        virtual status_t dequeueBuffer(int* outSlot, sp<Fence>* outFence, uint32_t width,
                                       uint32_t height, PixelFormat format, uint64_t usage,
                                       uint64_t* outBufferAge,
                                       FrameEventHistoryDelta* outTimestamps) override;
        virtual status_t queueBuffer(int slot,
                const QueueBufferInput& input, QueueBufferOutput* output);
        virtual status_t cancelBuffer(int slot, const sp<Fence>& fence);
        virtual status_t connect(const sp<IProducerListener>& listener,
                int api, bool producerControlledByApp, QueueBufferOutput* output);
    
        // See IGraphicBufferProducer::disconnect
        virtual status_t disconnect(int api, DisconnectMode mode = DisconnectMode::Api);
    
        sp<BufferQueueCore> mCore;
    
        // This references mCore->mSlots. Lock mCore->mMutex while accessing.
        BufferQueueDefs::SlotsType& mSlots;
    }
    

    BufferQueueProducer定义只取了部分内容,有个BufferQueueCore的指针,指向BufferQueueCore对象。还定义了一个引用类型的SlotsType, 和BufferQueueCore中mSlots指向的是同一个mSlots数组对象。
    此外,还定义了Producer常用的几个方法
    dequeueBuffer: 从BufferQueue中申请新的Buffer
    queueBuffer: 将填充好内容的Buffer放入BufferQueue队列
    connect: Producer从BufferQueue申请Buffer或者放入填充好的Buffer,必须先调用connect连接到BufferQueue队列上
    disconnect: Producer不在对BufferQueue操作的时候,调用disconnect和BufferQueue队列断开连接。

    BufferQueueConsumer定义

    class BufferQueueConsumer : public BnGraphicBufferConsumer {
        virtual status_t acquireBuffer(BufferItem* outBuffer,
                nsecs_t expectedPresent, uint64_t maxFrameNumber = 0) override;
        virtual status_t releaseBuffer(int slot, uint64_t frameNumber,
                const sp<Fence>& releaseFence, EGLDisplay display,
                EGLSyncKHR fence);
       virtual status_t connect(const sp<IConsumerListener>& consumerListener,
                bool controlledByApp);
       virtual status_t disconnect();
    
       sp<BufferQueueCore> mCore;
    
       // This references mCore->mSlots. Lock mCore->mMutex while accessing.
       BufferQueueDefs::SlotsType& mSlots;
    }
    

    BufferQueueConsumer定义也只取了部分内容,和Producer定义基本类似。同样也有一个BufferQueueCore的指针指向BufferQueueCore对象,也定义了一个引用类型的SlotsType,和BufferQueueCore的mSlote指向了同一个mSlots数组对象,大小为64。
    acquireBuffer: 从BufferQueue队列中获取填充好内容,等待显示的Buffer,这些Buffer是生产者放入队列中的。
    releaseBuffer:当Consumer处理完Buffer后,释放Buffer,这样Producer可以重新从队列中申请填充。
    connect: Consumer想要从BufferQueue获取Buffer来处理,必须先调用connect连接到BufferQueue队列上
    disconnect: Consumer不在对BufferQueue操作的时候,调用disconnect和BufferQueue队列断开连接。

    总结

    BufferQueue队列简单的分析基本完成了,从BufferQueue的创建已经BufferQueue,BufferQueueProducer和BufferQueueConsumer的定义可以简单了解BufferQueue队列的内容。


    BufferQueue

    BufferQueueCore定义了Buffer队列的核心内容,保存有一个默认大小为64的BufferSlot数组,表示队列中最多可以有64个图像Buffer,但是我们可以自己定义大小,Layer初始化的时候目前设置为Buffer的数量为3,以前版本是2,这就是Android所说的UI双缓存或者三缓存,也就是时候一个窗口Surface到Layer之间有几个Buffer在其间进行传递,双缓存就是一个在Surface端绘制一个在Layer端显示。BufferQueueProducer和BufferQueueConsumer同时持有BufferQueueCore的对象。

    BufferQueueProducer继承自IBufferQueueProducer的Bn端,可以在进程间调用。dequeuebuffer,从队列中申请Buffer, 当填充完内容后,调用queuebuffer将Buffer入队。

    BufferQueueConsumer继承自IBufferQueueConsumer的Bn端,可以在进程间调用,acquirebuffer从队列中取得填充好的buffer,处理完成后调用releasebuffer释放buffer为FREE状态后重新回到队列。

    相关文章

      网友评论

          本文标题:BufferQueue分析:Buffer队列

          本文链接:https://www.haomeiwen.com/subject/qjomoctx.html