Android12(S)图形显示系统-BufferQueue/BLASTBufferQueue之初识(六)

博客 动态
0 203
羽尘
羽尘 2022-03-15 14:56:50
悬赏:0 积分 收藏

Android 12(S) 图形显示系统 - BufferQueue/BLASTBufferQueue之初识(六)

讲解Andrioid图形系统中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.cppsp<Surface> SurfaceControl::getSurface(){    Mutex::Autolock _l(mLock);    if (mSurfaceData == nullptr) {        return generateSurfaceLocked();    }    return mSurfaceData;}

其中 mSurfaceData定义如下:

* /frameworks/native/libs/gui/include/gui/SurfaceControl.hmutable 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了。

 

BLASTBufferQueue的构建

先看其构造函数的代码:

BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp<SurfaceControl>& surface,                                   int width, int height, int32_t format)      : mSurfaceControl(surface),        mSize(width, height),        mRequestedSize(mSize),        mFormat(format),        mNextTransaction(nullptr) {    createBufferQueue(&mProducer, &mConsumer);    // since the adapter is in the client process, set dequeue timeout    // explicitly so that dequeueBuffer will block    mProducer->setDequeueTimeout(std::numeric_limits<int64_t>::max());    // safe default, most producers are expected to override this    mProducer->setMaxDequeuedBufferCount(2);    mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,                                                      GraphicBuffer::USAGE_HW_COMPOSER |                                                              GraphicBuffer::USAGE_HW_TEXTURE,                                                      1, false);    static int32_t id = 0;    mName = name + "#" + std::to_string(id);    auto consumerName = mName + "(BLAST Consumer)" + std::to_string(id);    mQueuedBufferTrace = "QueuedBuffer - " + mName + "BLAST#" + std::to_string(id);    id++;    mBufferItemConsumer->setName(String8(consumerName.c_str()));    mBufferItemConsumer->setFrameAvailableListener(this);    mBufferItemConsumer->setBufferFreedListener(this);    mBufferItemConsumer->setDefaultBufferSize(mSize.width, mSize.height);    mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format));    mBufferItemConsumer->setBlastBufferQueue(this);    ComposerService::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);    mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);    mTransformHint = mSurfaceControl->getTransformHint();    mBufferItemConsumer->setTransformHint(mTransformHint);    SurfaceComposerClient::Transaction()            .setFlags(surface, layer_state_t::eEnableBackpressure,                      layer_state_t::eEnableBackpressure)            .setApplyToken(mApplyToken)            .apply();    mNumAcquired = 0;    mNumFrameAvailable = 0;    BQA_LOGV("BLASTBufferQueue created width=%d height=%d format=%d mTransformHint=%d", width,             height, format, mTransformHint);}

可以看到构造函数中主要是去创建BufferQueue并初始化生成者mProducer和消费者mConsumer这两个变量,然后进行了一些参数和Listener的设置

createBufferQueue

* /frameworks/native/libs/gui/BLASTBufferQueue.cpp// Similar to BufferQueue::createBufferQueue but creates an adapter specific bufferqueue producer.// This BQP allows invoking client specified ProducerListeners and invoke them asynchronously,// emulating one way binder call behavior. Without this, if the listener calls back into the queue,// we can deadlock.void BLASTBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,                                         sp<IGraphicBufferConsumer>* outConsumer) {    LOG_ALWAYS_FATAL_IF(outProducer == nullptr, "BLASTBufferQueue: outProducer must not be NULL");    LOG_ALWAYS_FATAL_IF(outConsumer == nullptr, "BLASTBufferQueue: outConsumer must not be NULL");    sp<BufferQueueCore> core(new BufferQueueCore());    LOG_ALWAYS_FATAL_IF(core == nullptr, "BLASTBufferQueue: failed to create BufferQueueCore");    sp<IGraphicBufferProducer> producer(new BBQBufferQueueProducer(core));    LOG_ALWAYS_FATAL_IF(producer == nullptr,                        "BLASTBufferQueue: failed to create BBQBufferQueueProducer");    sp<BufferQueueConsumer> consumer(new BufferQueueConsumer(core));    consumer->setAllowExtraAcquire(true);    LOG_ALWAYS_FATAL_IF(consumer == nullptr,                        "BLASTBufferQueue: failed to create BufferQueueConsumer");    *outProducer = producer;    *outConsumer = consumer;}

创建BufferQueueCore

创建BBQBufferQueueProducer

创建BufferQueueConsumer

 

再来看一张类图,BufferQueue相关类的关系,先有个初步的印象

BLASTBufferQueue::getSurface

sp<Surface> BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {    std::unique_lock _lock{mMutex};    sp<IBinder> scHandle = nullptr;    if (includeSurfaceControlHandle && mSurfaceControl) {        scHandle = mSurfaceControl->getHandle();    }    return new BBQSurface(mProducer, true, scHandle, this);}

BLASTBufferQueue::getSurface方法中会去创建一个BBQSurface, 这个类继承自Surface,其中保存了对应layer的handle

class BBQSurface : public Surface {  ......}

 


 

需要理理/想想

我们初步可以看到一些概念:
    一个BLASTBufferQueue(BufferQueue)对应一个Layer,一个BufferQueue中有多个Buffer,一般是2个或者3个。
    一个BLASTBufferQueue(BufferQueue)有一个Producer,一个Consumer
    结合前面的分析,一个Surface和一个Layer也是一一对应的,和窗口也是一一对应的。

可见,BLASTBufferQueue(BufferQueue)就是两个连接纽带,连接着Producer和Consumer。

 

Android 12之前的版本是在SurfaceFlinger的BufferLayer中去创建BufferQueue,而Android 12把这个逻辑从SurfaceFlinger移出来了,而是在BLASTBufferQueue中去创建BufferQueue。BLASTBufferQueue会关联到特定的layer,并与SurfaceFlinger交互来和layer建立联系。

 

3 小结

这一篇文章中,我们顺着示例应用的逻辑,引入了BufferQueue的概念,介绍了什么时候,如何创建了BufferQueue。

 

 


必读:

Android 12(S) 图形显示系统 - 开篇

 


我盯着你!

 

posted @ 2022-03-15 13:41 二的次方 阅读(0) 评论(1) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员