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的流转过程和状态变化情况。
上图描述的流程我再重复唠叨一遍:
- Producer准备绘图时,调用dequeueBuffer向BufferQueue请求一块buffer;
- BufferQueue收到dequeueBuffer的请求后会去自己的BufferSlot队列中寻找一个FREE状态的,然后返回它的index;
- Producer拿到可用的buffer后就可以准备填充数据了;
- Producer填充数据完毕,调用queueBuffer将bffer再返还给BufferQueue;
- BufferQueue收到queueBuffer请求后,将指定的buffer包装为BufferItem对象,放入mQueue,并通知Consumer来消费;
- Consumer收到 frame available的通知后,调用acquireBuffer,获取一个buffer;
- Consumer拿到buffer进行消费,一般是指SurfaceFlinger做渲染显示;
- Consumer完成处理,调用releaseBuffer把buffer返还给BufferQueue,这个buffer之后就可以再次在新的循环中使用了。
另外一点请留意各个函数调用后,对应的BufferSlot(GraphicBuffer)的状态变化。一般是这样的:
FREE -> DEQUEUED -> QUEUED -> ACQUIRED -> FREE
二、生产者-Producer的相关逻辑
代码位置 :/frameworks/native/libs/gui/BufferQueueProducer.cpp