• SurfaceFlinger系列02--BufferQueue和BufferQueueCore


    相关文件:

    frameworks ativeincludeguiBufferQueue.h

    frameworks ativeincludeguiBufferQueueCore.h

    frameworks ativeincludeuiBufferQueueDefs.h

    顾名思义,BufferQueue是用来保存buffer的queue。Android显示系统中为此提供了两个类BufferQueue和BufferQueueCore,从名字上看两个类都是buffer queue相关,但后者似乎是更核心一些,下面来具体分析这两个类之间的关系。

    BufferQueue

    BufferQueue类一开始就定义了几个非常重要的关键属性值。

    • NUM_BUFFER_SLOTS:BufferQueue类定义了一个queue中能够保存的buffer的最大数量NUM_BUFFER_SLOTS,其数量为64,这是android::BufferQueueDefs命令空间中定义的一个静态常量NUM_BUFFER_SLOTS,因此无法在runtime过程中改变此值。
    • INVALID_BUFFER_SLOT:BufferSlot的默认状态,即此BufferSlot还未指向已经存在并且有效的buffer时的状态
    • NO_BUFFER_AVAILABLE:一般dequeueBuffer前要查询BufferQueue中是否有buffer可用,如果没有,则返回NO_BUFFER_AVAILABLE,表示当前BufferQueue中没有pending状态的buffer可用。
    • PRESENT_LATER:dequeueBuffer时,如果此时buffer还没有准备好,则返回PRESENT_LATER,表示此时dequeueBuffer太早了,等会再来dequeue。
    • MAX_MAX_ACQUIRED_BUFFERS:当处于异步模式时,系统要预留2个slot以保证producer和consumer之间的异步关系,因此该值等于NUM_BUFFER_SLOTS-2。

    BufferQueue类中还定义了一个ProxyConsumerListener类,其继承关系如下图所示:

     从继承关系上看,ProxyConsumerListener类是一个Bn端(服务端)的监听类(从类名上看,似乎使用代理模式,这点待进一步研究)。ProxyConsumerListener类是ConsumerListener类的实现,主要用来保存一个指向真正的consumer object的weak引用。ProxyConsumerListener的主要目的是避免BufferQueue对象和consumer对象的循环引用。

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

    ProxyConsumerListener的使用在ConsumerBase类。

    ProxyConsumerListener的实现比较简单,几个函数的功能如下表所示,显然主要是监听一些动作,当这些对应的事件发生后,及时通知另一端。这里显然做数据同步的功能,具体同步的肯定是producer和consumer两端的关系,这一部分内容待补充。

    成员函数

    功能描述

    onDisconnect

    通知远端已经断开链接了

    onFrameAvailable

    通知远端frame已经准备好了

    onFrameReplaced

    通知远端frame被替换了

    onBuffersReleased

    通知远端buffer已经release了

    onSidebandStreamChanged

     

    addAndGetFrameTimestamps

     

    看完ProxyConsumerListener类,BufferQueu就剩下最后一个成员了,也是最重要的一个成员:createBufferQueue函数。

    static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer, sp<IGraphicBufferConsumer>* outConsumer, bool consumerIsSurfaceFlinger = false);

    显然,这个函数是用来创建buffer queue的,其入参即buffer queue的producer和consumer,最后一个参数指明consumer是否为SurfaceFlinger。该函数的使用有两个地方,一个一个在BufferLayer::onFirstRef函数中,一个在SurfaceFlinger:: processDisplayChangesLocked函数中,这里暂时只讲BufferLayer::onFirstRef里面的使用。该函数似乎是给外接屏使用的,这里暂时不深入。

    void BufferLayer::onFirstRef() {
        // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
        sp<IGraphicBufferProducer> producer;
        sp<IGraphicBufferConsumer> consumer;
        BufferQueue::createBufferQueue(&producer, &consumer, true);
        mProducer = new MonitoredProducer(producer, mFlinger, this);
        mConsumer = new BufferLayerConsumer(consumer,
                mFlinger->getRenderEngine(), mTextureName, this);
        mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
        mConsumer->setContentsChangedListener(this);
        mConsumer->setName(mName);
    
        if (mFlinger->isLayerTripleBufferingDisabled()) {
            mProducer->setMaxDequeuedBufferCount(2);
        }
    
        const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
        updateTransformHint(hw);
    }

    BufferLayer::onFirstRef是在上层应用请求SurfaceFlinger创建Layer时调用的,即应用告诉SurfaceFlinger它要创建一个Layer(即APP端的窗口、Native层的Surface),此时SurfaceFlinger就会创建创建对应Layer,并为此Layer创建一个对应的BufferQueue,即应用的一个窗口对应一个BufferQueue。那么显然,这里的producer是指应用端对应的窗口,consumer即指SurfaceFlinger(第三个参数指定的)。BufferLayer::onFirstRef函数这里不深入研究。

    继续看createBufferQueue函数的源代码,删除次要的代码,其主要代码部分如下:

    void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
            sp<IGraphicBufferConsumer>* outConsumer,
            bool consumerIsSurfaceFlinger) {
        ……
        sp<BufferQueueCore> core(new BufferQueueCore());
    
        sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
    
        sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
    
        *outProducer = producer;
        *outConsumer = consumer;
    }

    首先,他调用BufferQueueCore的构建函数创建了一个core对象,显然这是在说,BufferQueueCore才是buffer queue的核心,真正干活的其实是BufferQueueCore这个类,BufferQueue只是个外壳而已。其次分别创建了producer和consumer对象,返回给了对应的Layer,然后BufferLayer将这两个添加了其内部的Consuerm Listener监听器中,这样创建出来的layer就可以与SurfaceFlinger之间进行相关的数据互动操作了,这里不在深入具体细节,后续专门介绍。

    BufferQueueCore

    从前面的分析可以看到,BufferQueue类其实只做了一件事情:创建BufferQueueCore。其他什么事情都没做。那么这个BufferQueueCore肯定是非常重要的了。接下来看BufferQueueCore这个类。

            BufferQueueCore没有复杂的继承关系,直接继承了RefBase类。

            BufferQueueCore定义了当前queue的状态:

    • CURRENTLY_CONNECTED_API:值为-1,表示当前有producer连接到buffer queue
    • NO_CONNECTED_API:值为0,表示当前没有producer连接到buffer queue

    BufferQueueCore

    成员变量

    描述

    mMutex

    被mutable修饰,表明此锁的状态是随时变化的

    mIsAbandoned

    该变量表示buffer queue已经不在继续消费push到其中的image buffer数据,初始化时默认为false,当consumerDisconnect时,被设置成true。

    mConsumerControlledByApp

    表示已经连接的consumer是否被application所控制

    mConsumerName

    该buffer queue对应的consumer的名字,用于在log中标识buffer queue的所有者

    mConsumerListener

    用于向已连接的consumer发送通知消息。默认初始化时为NULL,当consumerConnect或consumerDisconnect时写入有效值。

    mConsumerUsageBits

    包含了consumer想要的flags信息

    mConsumerIsProtected

    表示conumser是否准备处理受保护的buffer

    mConnectedApi

    表示当前连接到buffer queue的producer API,默认为NO_CONNECTED_API,当connect或disconnect时会发生变化

    mConnectedPid

    最后一个成功连接到该buffer queue的进程的pid

    mConnectedProducerListener

    该监听器用于处理onBufferRelease通知消息

    mSlots

    即BufferSlot数组,最大保存NUM_BUFFER_SLOTS个BufferSlot。 mSlots必须与producer侧成镜像状态,这使buffer的所有权在producer和consumer之间进行转换时,可以不用通过Binder来发送GraphicBuffer就能实现。整个数组在初始化时被设置为NULL,当requestBuffer时,才会为slot分配buffer。

    mFreeSlots

    set<int>类型变量,包含所有处于FREE状态的slot序号,这些slot当前并没有与某个buffer关联起来,完全处于FREE状态。

    mFreeBuffers

    list<int>类型变量,包含当前所有处于FREE状态的slot,但是这些slot都已经被关联到了特定的buffer。

    mUnusedSlots

    list<int>类型变量,表示当前所有没有被使用的slot,这些slot都是FREE状态,也没有与buffer相关联。

    mActiveBuffers

    set<int>类型变量,包含当前所有与非FREE状态Buffer关联的slot

    mQueue

    Vector<BufferItem>类型变量,同步模式中使用的FIFO队列

    mDequeueCondition

    在同时模式中,供dequeueBuffer方法使用的一个条件变量

    mDequeueBufferCannotBlock

    表示dequeueBuffer操作是否可以被block。这个标志在producer和consumer被Application所控制的情况下,做connect操作时设置。

    mDefaultBufferFormat

    buffer format的默认格式,如果dequeueBuffer时没有指定buffer format,则使用此变量所设置的format

    mDefaultWidth

    所分配的buffer的默认宽度,在dequeueBuffer中使用,默认为0

    mDefaultHeight

    所分配的buffer的默认高度,在dequeueBuffer中使用,默认为0

    mDefaultBufferDataSpace

    queueBuffer时,如果指定DATA_DATASPACE_UNKNOWN了,则使用此值

    mMaxBufferCount

    指定一次最大分配的buffer数量,可以由consumer进行设置

    mMaxAcquiredBufferCount

    指定consumer端一次最大acquire的buffer数量,默认为1.consumer端可以通过调用setMaxAcquiredBufferCount来改变此值,但也仅限在尚有producer连接到buffer queue时生效,This value is used to derive the value returned for the MIN_UNDEQUEUED_BUFFERS query to the producer.

    mMaxDequeuedBufferCount

    producer端一次最大dequeue的buffer数量,默认为1,producer端可以通过setMaxDequeuedBufferCount函数修改此值。

    mBufferHasBeenQueued

    当一个buffer被queue进buffer queue时,会将此值设置为true。当因某种原因使得所有buffer都被free时,此值会被重置。

    mFrameCounter

    每当queueBuffer或buffer allocation成功时,这个值都会增长

    mTransformHint

    用于优化屏幕旋转

    mSidebandStream

    a handle to the sideband buffer stream

    mIsAllocating

    表示一个producer是否正在分配buffers,当该变量值为true时,producer不应该修改任何FREE状态的slot。当此变量值变成false时,mIsAllocatingCondition会被signaled,表明producer已经分配完buffer。

    mIsAllocatingCondition

    与mIsAllocating配合使用

    mAllowAllocation

    用来决定dequeueBuffer操作时是否可以分配新的buffer

    mBufferAge

    tracks the age of the contents of the most recently dequeued buffer as the number of frames that have elapsed since it was last queued

    mGenerationNumber

    stores the current generation number of the attached producer. Any attempt to attach a buffer with a different generation number will fail.

    mAsyncMode

    指示异步模式是否被开启。在异步模式中,需要分配额外的buffer以保证producer在enqueue buffer时不被blocking。

    mSharedBufferMode

    indicates whether or not shared buffer mode is enabled.

    mAutoRefresh

    若为enabled,表示即使BufferQueue没有通知buffer已经准备好了,consumer也应该自动acquire buffer,

    mSharedBufferSlot

    当sharedBufferMode开启后,该变量用来跟踪哪个slot包含了shared buffer。

    mLastQueuedSlot

    最后一次被queue的buffer的序号

    mUniqueId

    唯一的标识ID

    mSharedBufferCache

    shared buffer的Cached data

  • 相关阅读:
    分页
    用于dbnull的数据转换。因为用convert.to无法转换dbnull类型
    sqldbhelper
    sql 去重
    wcf 双工
    WCF使用泛型方法的问题
    wpf 查找页面的所有TextBox
    WebService流行框架之Axis和CXF
    Hibernate SQL方言 (hibernate.dialect)
    Hibernate联合主键映射
  • 原文地址:https://www.cnblogs.com/tsts/p/10285311.html
Copyright © 2020-2023  润新知