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元宇宙 继续阅读相关文章!

posted on 2022-03-15 13:41  二的次方  阅读(10143)  评论(9编辑  收藏  举报