BufferQueueProducer和surface联系

一、Surface::dequeueBuffer申请图形缓冲区(buffer类型为buffer_handle_t handle)

详情参考1:

android graphic(8)—surface申请GraphicBuffer过程_lyf's blog-CSDN博客

详情参考2:

Android SurfaceFlinger 学习之路(七)----创建图形缓冲区GraphicBuffer_STN_LCD的专栏-CSDN博客

总结:

1.surface先调用dequeueBuffer向BufferQueueProducer申请内存,这时会调用GraphicBufferAlloc去分配图形缓冲区,而GraphicBufferAlloc是在surfaceFlinger进程中new出来的,因此缓冲区会存在surfaceFlinger进程中,这时候就需要序列化和反序列化,将该缓冲区内存map到BufferQueue进程中;此调用完dequeueBuffer之后,只拿到了buffermSlots中的下标

2.BufferQueueProducer和surface中有大小相同的mSlots(大小为64),两者一一对应;

3. 由于BufferQueue和Surface不在同一进程,需要用requestBuffer进行内存映射,requestBuffer的核心就是:Surface传一个数组下标,然后去将BufferQueue中对应的数组下标中的GraphicBuffer对象映射到Surface中,然后保存在对应的数组中,这两个数组一一对应

二、Surface::queueBuffer将填充好的buffer入队

    Surface::dequeueBuffer申请缓冲区,在camera result buffer时,会向缓冲区里面填充数据,这时会调用Surface::queueBuffer,也就是入队,等待消费者来拿取该buffer。

Surface::queueBuffer中的重要实现:

{  // 获取buffer在mSlots中的下标,然后进BufferQueueProducer中,去拿实际的

    int i = getSlotFromBufferLocked(buffer);

     status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);

}

BufferQueueProducer::queueBuffer:

{

     // 通过上面传递过来的idx,就可以找到绑定的GraphicBuffer

    const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);

     // 通过

      sp<IConsumerListener> frameAvailableListener;

      frameAvailableListener = mCore->mConsumerListener;

     if (frameAvailableListener != NULL) {

           frameAvailableListener->onFrameAvailable(item);

      }    

}

我们先回过头去看看ImageReader_Init函数:

{

   sp<IGraphicBufferProducer> gbProducer;

    sp<IGraphicBufferConsumer> gbConsumer;

    BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);

    sp<BufferItemConsumer> bufferConsumer;

   bufferConsumer = new BufferItemConsumer(gbConsumer, consumerUsage, maxImages,

            /*controlledByApp*/true);

}

看一下BufferItemConsumer的构造函数:

BufferItemConsumer::BufferItemConsumer(

        const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,

        int bufferCount, bool controlledByApp) :

    ConsumerBase(consumer, controlledByApp){

    status_t err = mConsumer->setConsumerUsageBits(consumerUsage);

    LOG_ALWAYS_FATAL_IF(err != OK,

            "Failed to set consumer usage bits to %#" PRIx64, consumerUsage);

    if (bufferCount != DEFAULT_MAX_BUFFERS) {

        err = mConsumer->setMaxAcquiredBufferCount(bufferCount);

        LOG_ALWAYS_FATAL_IF(err != OK,

                "Failed to set max acquired buffer count to %d", bufferCount);

    }

}

再看看ConsumerBase的构造:

ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :

        mAbandoned(false),

        mConsumer(bufferQueue),

        mPrevFinalReleaseFence(Fence::NO_FENCE) {

    // Choose a name using the PID and a process-unique ID.

    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());

    // ConsumerBase是继承于ConsumerListener的,因此这里的this就是ConsumerBase本身

    wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);

    sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);

    status_t err = mConsumer->consumerConnect(proxy, controlledByApp);

}

其中mConsumer->consumerConnect最终执行BufferQueueConsumer::connect,这个函数里面有一个重要的赋值:mCore->mConsumerListener = consumerListener;

也就是ConsumerBase把自己作为监听,传递给了mCore->mConsumerListener。

现在再看看BufferQueueProducer中执行的frameAvailableListener->onFrameAvailable(item),这里就很清楚了,也就是执行ConsumerBase::onFrameAvailable

void ConsumerBase::onFrameAvailable(const BufferItem& item) {

    CB_LOGV("onFrameAvailable");

    sp<FrameAvailableListener> listener;

    { // scope for the lock

        Mutex::Autolock lock(mFrameAvailableMutex);

        listener = mFrameAvailableListener.promote();

    }

    if (listener != NULL) {

        CB_LOGV("actually calling onFrameAvailable");

        listener->onFrameAvailable(item);

    }

}

问题又来了,ConsumerBase::mFrameAvailableListener又是在何时赋值的?

继续看ImageReader_init函数:

{

    sp<BufferItemConsumer> bufferConsumer;

    bufferConsumer->setFrameAvailableListener(ctx);

}

BufferConsumer中没有实现setFrameAvailableListener方法,那直接看其父类中该方法ConsumerBase::setFrameAvailableListener的实现:

void ConsumerBase::setFrameAvailableListener(

        const wp<FrameAvailableListener>& listener) {

    CB_LOGV("setFrameAvailableListener");

    Mutex::Autolock lock(mFrameAvailableMutex);

    mFrameAvailableListener = listener;

}

综上,BufferQueueProducer::queueBuffer会将绘制完毕的buffer进行入队操作(mSlots中相应位置),再将该slot状态变成QUEUE,然后告诉监听类(ImageReader_initnew出来的JNIImageReaderContext)该buffer已经准备好了,可以取出来消费了。我们发现BufferQueueProducer和surface之间并没有实际的buffer传递,而是在传递GraphicBuffer handle,这是共享内存的一个优点,可以大大降低传输延迟。我们只要知道GraphicBuffer在BufferQueueProducer::mSlots的下标,就能找到绑定的GraphicBuffer。

三、GraphicBuffer就是常说的图形缓存区,在surfaceFlinger进程中申请的,因为GraphicBuffer对象在new时,会用GraphicBufferAllocate

GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,

        PixelFormat inFormat, uint32_t inLayerCount, uint64_t usage, std::string requestorName)

    : GraphicBuffer() {

    mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount,

            usage, std::move(requestorName));

}

status_t GraphicBuffer::initWithSize(uint32_t inWidth, uint32_t inHeight,

        PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage,

        std::string requestorName)

{

    GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();

    uint32_t outStride = 0;

    status_t err = allocator.allocate(inWidth, inHeight, inFormat, inLayerCount,

            inUsage, &handle, &outStride, mId,

            std::move(requestorName));

    if (err == NO_ERROR) {

        mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);

        width = static_cast<int>(inWidth);

        height = static_cast<int>(inHeight);

        format = inFormat;

        layerCount = inLayerCount;

        usage = inUsage;

        usage_deprecated = int(usage);

        stride = static_cast<int>(outStride);

    }

    return err;

}

这里会通过get方法先获取到GraphicBufferAllocator(单例)对象,然后用其allocate方法来申请一段内存。GraphicBufferAllocator是在SurfaceFlingernew出来的。

先看下GraphicBufferAllocator构造函数:

GraphicBufferAllocator::GraphicBufferAllocator() : mMapper(GraphicBufferMapper::getInstance()) {

     mAllocator = std::make_unique<const Gralloc3Allocator>(

            reinterpret_cast<const Gralloc3Mapper&>(mMapper.getGrallocMapper()));

    if (mAllocator->isLoaded()) {

        return;

    }

    mAllocator = std::make_unique<const Gralloc2Allocator>(

            reinterpret_cast<const Gralloc2Mapper&>(mMapper.getGrallocMapper()));

    if (mAllocator->isLoaded()) {

        return;

    }

    LOG_ALWAYS_FATAL("gralloc-allocator is missing");

}

这里面又创建了另一个核心类GraphicBufferMapper,用作映射内存,这也是个单例类,然后根据版本创建GrallocAllocator对象,只要一个对象创建成功就返回,看下GrallocAllocator的构造:

Gralloc3Allocator::Gralloc3Allocator(const Gralloc3Mapper& mapper) : mMapper(mapper) {

    mAllocator = IAllocator::getService();

    if (mAllocator == nullptr) {

        ALOGW("allocator 3.x is not supported");

        return;

    }

}

IAllocator这就是HIDL接口3.0版本

using android::hardware::graphics::allocator::V3_0::IAllocator;

好了,调用完GraphicBufferAllocator的构造后,mAllocator和mMapper对象都有了。回过头去看GraphicBufferAllocator::allocate方法的实现:

status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height, PixelFormat format,

                                          uint32_t layerCount, uint64_t usage,

                                          buffer_handle_t* handle, uint32_t* stride,

                                          std::string requestorName) {

    return allocateHelper(width, height, format, layerCount, usage, handle, stride, requestorName,

                          true);

}

status_t GraphicBufferAllocator::allocateHelper(uint32_t width, uint32_t height, PixelFormat format,

                                                uint32_t layerCount, uint64_t usage,

                                                buffer_handle_t* handle, uint32_t* stride,

                                                std::string requestorName, bool importBuffer) {

                   

                   status_t error = mAllocator->allocate(requestorName, width, height, format, layerCount, usage,

                                          1, stride, handle, importBuffer);

                   ……

}

接下来就是用Gralloc3Allocator去分配图形缓冲区了。这里就不再往下进行分析了,至少我们知道:

Gralloc3Allocator用于分配内存;

GraphicBufferMapper用于映射内存;

详情参考:https://blog.csdn.net/qq_34211365/article/details/106782063

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值