SurfaceFlinger系列02--BufferQueue和BufferQueueCore


相關文件:

frameworks\native\include\gui\BufferQueue.h

frameworks\native\include\gui\BufferQueueCore.h

frameworks\native\include\ui\BufferQueueDefs.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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM