Android 12(S) 圖像顯示系統 - BufferQueue/BLASTBufferQueue之初識(六)


題外話

你有沒有聽見,心里有一聲咆哮,那一聲咆哮,它好像在說:我就是要從后面追上去!

寫文章真的好痛苦,特別是自己對這方面的知識也一知半解就更加痛苦了。這已經是這個系列的第六篇了,很多次都想放棄了,但最終還是堅持下來了,因為我真的好像搞懂這一塊。


1 前言

前面一篇文章中,我們已經介紹了createSurface的流程,也在SurfaceFlinger中去創建了圖層layer,但一直沒有看到buffer queue的蹤影。其實,據我觀察 Android 12 將BufferQueue的相關邏輯移出了SurfaceFlinger。這一篇文章中我們就會跟隨之前寫的應用的代碼邏輯,看看BufferQueue的相關邏輯是如何引入的?又是如何工作的?

2 創建BufferQueue/BLASTBufferQueue

接着從我們的示例應用講起,代碼在文章:Android 12(S) 圖形顯示系統 - 示例應用(二)

創建native surface后接下下就是要准備去繪圖了,流程就走到了 drawNativeSurface()這個方法中,先看內容:

int drawNativeSurface(sp<NativeSurfaceWrapper> nativeSurface) {
    status_t err = NO_ERROR;
    int countFrame = 0;
    ANativeWindowBuffer *nativeBuffer = nullptr;
    ANativeWindow* nativeWindow = nativeSurface->getSurface().get();
    
    ...
  
}

drawNativeSurface這個方法中首先去調用了我們定義的NativeSurfaceWrapper::getSurface方法:

sp<ANativeWindow> NativeSurfaceWrapper::getSurface() const {
    sp<ANativeWindow> anw = mSurfaceControl->getSurface();
    return anw;
}

getSurface方法中,mSurfaceControl就是上一篇中Android 12(S) 圖形顯示系統 - createSurface的流程(五)創建得到的,它封裝了SurfaceFlinger創建的BufferStateLayer的信息。接着來到了SurfaceControl::getSurface()

* /frameworks/native/libs/gui/SurfaceControl.cpp

sp<Surface> SurfaceControl::getSurface()
{
    Mutex::Autolock _l(mLock);
    if (mSurfaceData == nullptr) {
        return generateSurfaceLocked();
    }
    return mSurfaceData;
}

其中 mSurfaceData定義如下:

* /frameworks/native/libs/gui/include/gui/SurfaceControl.h

mutable sp<Surface>         mSurfaceData;

因為 SurfaceControl::getSurface() 第一次被調用,此時 mSurfaceData為null,進而會執行 SurfaceControl::generateSurfaceLocked()

sp<Surface> SurfaceControl::generateSurfaceLocked()
{
    uint32_t ignore;
    auto flags = mCreateFlags & (ISurfaceComposerClient::eCursorWindow |
                                 ISurfaceComposerClient::eOpaque);
    mBbqChild = mClient->createSurface(String8("bbq-wrapper"), 0, 0, mFormat,
                                       flags, mHandle, {}, &ignore);
    mBbq = sp<BLASTBufferQueue>::make("bbq-adapter", mBbqChild, mWidth, mHeight, mFormat);

    // This surface is always consumed by SurfaceFlinger, so the
    // producerControlledByApp value doesn't matter; using false.
    mSurfaceData = mBbq->getSurface(true);

    return mSurfaceData;
}

看到了沒,我們念念不忘,朝思暮想 ,魂牽夢繞的BufferQueue的邏輯 ==> BLASTBufferQueue  <== 終於千呼萬喚始出來!!!


class SurfaceControl : public RefBase
    ...
private:
    sp<SurfaceComposerClient>   mClient;                 // 應用創建的SurfaceComposerClient對象指針,里面封裝了和SurfaceFlinger通信的Binder客戶端
    sp<IBinder>                 mHandle;                 // 應用中顯式創建的layer handle,這是個BufferStateLayer 它作為parent
    sp<IGraphicBufferProducer>  mGraphicBufferProducer;  // 這個貌似沒有實際用了?
    mutable Mutex               mLock;
    mutable sp<Surface>         mSurfaceData;            // 
    mutable sp<BLASTBufferQueue> mBbq;                   // BLASTBufferQueue對象實例
    mutable sp<SurfaceControl> mBbqChild;                // child layer,它會和mBbq相關聯
    int32_t mLayerId;                                    // layer id
    uint32_t mTransformHint;                             // 方向
    uint32_t mWidth;                                     // surface 寬
    uint32_t mHeight;                                    // surface 高
    PixelFormat mFormat;
    uint32_t mCreateFlags;                               // createSurface的標志信息
};

SurfaceControl中一些成員和類圖,下圖可能並不完全准確

 

 

我們看看generateSurfaceLocked都干了什么:

♦ mCreateFlags是一個uint32_t類型的變量,表示createSurface的一些屬性標識,這個值其實就是我們調用surfaceComposerClient->createSurface時new SurfaceControl傳遞下來的

mClient,類型是sp<SurfaceComposerClient>   這個值也是我們調用surfaceComposerClient->createSurface時new SurfaceControl傳遞下來的

♦ mClient->createSurface 流程和我們上一章的流程是一樣的,傳遞的參數有點差異

   >> surface/layer的名字為“bbq-wrapper”

   >> 待創建的surface/layer設置其parent是mHandle所指向的layer,,mHandle也即是我們應用中顯示創建的那個名字為"NativeSFDemo"的layer

新創建的這個 child surface 或叫做 child layer的信息同樣被封裝到一個SurfceControl對象中,保存在 mBbqChild


我們在Android 12(S) 圖形顯示系統 - 示例應用(二)文章最后曾留下一個問題,看到這里你是不是就明白了🤩


 

主角登場

mBbq = sp<BLASTBufferQueue>::make("bbq-adapter", mBbqChild, mWidth, mHeight, mFormat);

♦ 創建一個BLASTBufferQueue對象,保存在mBbq中

♦ 最后調用BLASTBufferQueue::getSurface函數,返回一個sp<Surface>給應用,之后應用就可以通過這個Surface操做BufferQueue了。

 

關注公眾號 Android元宇宙 繼續閱讀相關文章!


免責聲明!

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



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