Android 12(S) 图像显示系统 - BufferQueue的工作流程(九)


题外话

Covid-19疫情的强烈反弹,小区里检测出了无症状感染者。小区封闭管理,我也不得不居家办公了。既然这么大把的时间可以光明正大的宅家里,自然要好好利用,八个字 == 努力工作,好好学习


 

一、前言


这篇文章中,将详细讲解 生产者 -- 图形缓冲队列 -- 消费者 这个模型的的具体工作流程。我们还是从我们的demo运行流程着手。

可以再回头看看 Android 12(S) 图像显示系统 - 示例应用(二)

在demo示例中,我们获取buffer --> 填充数据 --> 送出显示的代码如下所示(做了简化):

        // 9. dequeue a buffer
        ANativeWindowBuffer *nativeBuffer = nullptr;
        int hwcFD = -1;
        err = nativeWindow->dequeueBuffer(nativeWindow, &nativeBuffer, &hwcFD);

        // 10. make sure really control the dequeued buffer
        sp<Fence> hwcFence(new Fence(hwcFD));
        int waitResult = hwcFence->waitForever("dequeueBuffer_EmptyNative");
        // 11. fill buffer
        sp<GraphicBuffer> buf(GraphicBuffer::from(nativeBuffer));
        uint8_t* img = nullptr;
        err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
        fillRGBA8Buffer(img);
        err = buf->unlock();

        // 13. queue the buffer to display
        int gpuFD = -1;
        err = nativeWindow->queueBuffer(nativeWindow, buf->getNativeBuffer(), gpuFD);

获取图形缓冲区调用流程:

==> ANativeWindow::dequeueBuffer 

==> Surface::hook_dequeueBuffer

==> Surface::dequeueBuffer

==> BufferQueueProducer::dequeueBuffer

填充数据后返还图形缓冲区的调用流程:

==> ANativeWindow::queueBuffer

==> Surface::hook_queueBuffer

==> Surface::queueBuffer

==> BufferQueueProducer::queueBuffer

前面文章讲解中提到,BLASTBufferQueue中创建Surface对象时,初始化其成员mGraphicBufferProducer,这个就是指向了一个GraphicBufferProducer对象。

当然,demo作为客户端仅仅是展示了生产者的工作,那消费者的工作又是如何的呢?

先用一张流程图概述一下:

 

上图基本展示了BufferQueue的工作逻辑以及Buffer的流转过程和状态变化情况。


上图描述的流程我再重复唠叨一遍:

  1. Producer准备绘图时,调用dequeueBuffer向BufferQueue请求一块buffer;
  2. BufferQueue收到dequeueBuffer的请求后会去自己的BufferSlot队列中寻找一个FREE状态的,然后返回它的index;
  3. Producer拿到可用的buffer后就可以准备填充数据了;
  4. Producer填充数据完毕,调用queueBuffer将bffer再返还给BufferQueue;
  5. BufferQueue收到queueBuffer请求后,将指定的buffer包装为BufferItem对象,放入mQueue,并通知Consumer来消费;
  6. Consumer收到 frame available的通知后,调用acquireBuffer,获取一个buffer;
  7. Consumer拿到buffer进行消费,一般是指SurfaceFlinger做渲染显示;
  8. Consumer完成处理,调用releaseBuffer把buffer返还给BufferQueue,这个buffer之后就可以再次在新的循环中使用了。

另外一点请留意各个函数调用后,对应的BufferSlot(GraphicBuffer)的状态变化。一般是这样的:

FREE -> DEQUEUED -> QUEUED -> ACQUIRED -> FREE


 

二、生产者-Producer的相关逻辑


代码位置 :/frameworks/native/libs/gui/BufferQueueProducer.cpp

 

 

关注公众号 Android元宇宙 继续阅读相关文章!

posted on 2022-03-21 08:50  二的次方  阅读(7304)  评论(7编辑  收藏  举报