BufferQueue 是 Android 中所有图形处理操作的核心。它的作用很简单:将生成图形数据缓冲区的一方(生产者)连接到接受数据以显示或进一步处理的一方(消费者)。几乎所有在系统中移动图形数据缓冲区的内容都依赖于 BufferQueue。
Android 定义了一个类 BufferQueue
,用于创建 BufferQueue、生产者和消费者。该类定义(位于frameworks/native/include/gui/BufferQueue.h
)如下:
BufferQueue
定义了一个类 ProxyConsumerListener
用于方便 ConsumerListener
的 IPC,它会把所有对它的调用,都转发给实际的 consumer 对象。
BufferQueue
类只有一个静态成员函数 createBufferQueue()
用于创建 BufferQueue,该函数定义(位于 frameworks/native/libs/gui/BufferQueueCore.cpp
)如下:
createBufferQueue()
函数基于 IGraphicBufferAlloc
创建 BufferQueueCore
,并基于后者创建 BufferQueueProducer
和 BufferQueueConsumer
返回给调用者。Android 图形系统的核心在 BufferQueue,BufferQueue 的核心则在 BufferQueueCore
类,而不是 BufferQueue
类。
图形缓冲区分配器 IGraphicBufferAlloc
BufferQueueConsumer
管理的图形缓冲区均由 BufferQueueProducer
通过 IGraphicBufferAlloc
分配。创建 BufferQueue 时,传入的 allocator 通常为空值,此时 BufferQueueCore
通过如下方式(位于
frameworks/native/libs/gui/BufferQueueCore.cpp
)获得 IGraphicBufferAlloc
:
BufferQueueCore
的 IGraphicBufferAlloc
来自于 ComposerService
。ComposerService
定义(位于frameworks/native/include/private/gui/ComposerService.h
)如下:
ComposerService
类本身仅仅持有到 composer service,如 SurfaceFlinger 的连接,即 ISurfaceComposer
。如果远程服务挂掉了,这个类通过 Binder 的 linkToDeath 机制得到通知,并将重新建立连接。
ComposerService
类的成员函数定义(位于 frameworks/native/libs/gui/SurfaceComposerClient.cpp
)如下:
实际的 composer service 是 SurfaceFlinger。SurfaceFlinger 中是这样创建 IGraphicBufferAlloc
的(配置使用 HWC2 的情况,位于frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
):
IGraphicBufferAlloc
实际为 GraphicBufferAlloc
,该类定义(位于 frameworks/native/include/gui/GraphicBufferAlloc.h
)如下:
GraphicBufferAlloc
继承自 BnGraphicBufferAlloc
,后者定义(位于 frameworks/native/include/gui/IGraphicBufferAlloc.h
)如下:
GraphicBufferAlloc
只有一个成员函数,该函数定义(frameworks/native/libs/gui/GraphicBufferAlloc.cpp
)如下:
BufferQueueCore
为 GraphicBuffer
的容器,IGraphicBufferAlloc
仅仅用于创建 GraphicBuffer
对象。但对于实际的图形内存块的管理,还不在 IGraphicBufferAlloc
这一层。
图形缓冲区 GraphicBuffer
GraphicBuffer
类是更底层 操作系统/硬件 层图形内存块的封装,该类的定义如下:
ANativeObjectBase
模板的声明(位于 frameworks/native/include/ui/ANativeObjectBase.h
)是这样的:
以此来看,GraphicBuffer
也将继承 ANativeWindowBuffer
。ANativeWindowBuffer
定义(位于 system/core/include/system/window.h
)如下:
这个结构体描述了更底层 操作系统/硬件 层图形内存块的信息,包括图形内存块的句柄 handle
,图像的宽度、高度,像素格式等。图形内存块的句柄类型 buffer_handle_t
为 const native_handle_t*
的别名,native_handle_t
定义(位于 system/core/include/cutils/native_handle.h
)如下:
可以看到 GraphicBuffer
类的主要职责主要有三块:
- 主要通过继承自
ANativeWindowBuffer
结构体的成员,来描述图形内存块的信息。 - 分配释放图形内存块。这主要通过
initSize()
/reallocate()
/free_handle()
等操作完成。 - 分配的图形内存块未必已经映射到应用程序的虚拟地址空间了。应用程序要想像访问普通内存那样访问图形内存块,还需要通过
lockXXX
操作将图形内存块映射到应用程序进程的虚拟地址空间内。应用程序在把图形内存块还回去的时候则需要unlockXXX
操作。
此外 GraphicBuffer
的 mInitCheck
用于记录图形缓冲区的状态;mGenerationNumber
用于记录 generation number;mId
用于标识图形缓冲区,它通过如下方式计算得到:
mID 通过进程的 PID 和一个不断递增的整数计算获得。
GraphicBuffer
依赖于 GraphicBufferAllocator
完成图形内存块的分配和释放,依赖于 GraphicBufferMapper
执行图形内存块的 lock/unlock 操作。
GraphicBuffer
的图形内存块分配和释放操作实现(位于 frameworks/native/libs/ui/GraphicBuffer.cpp
)如下:
GraphicBuffer
的图形内存块的 lock/unlock 操作实现(位于 frameworks/native/libs/ui/GraphicBuffer.cpp
)如下:
这些操作基本上都是比较直接的委托。
GraphicBufferAllocator 和 GraphicBufferMapper
GraphicBufferAllocator
和 GraphicBufferMapper
则依赖于 Gralloc1::Loader
和
Gralloc1::Device
完成图形内存的分配释放和 lock
/ unlock
操作,其中 Gralloc1::Loader
用于加载 HAL 层的 gralloc 模块并创建 Gralloc1::Device
,Gralloc1::Device
则用于执行最终的图形内存的分配释放和 lock
/ unlock
操作。
GraphicBufferAllocator
类定义(位于 frameworks/native/include/ui/GraphicBufferAllocator.h
)如下:
GraphicBufferAllocator
主要定义了分配图形内存块的 allocate()
和释放图形内存块的 free()
两个函数,这两个函数的实现(位于 frameworks/native/libs/ui/GraphicBufferAllocator.cpp
)如下:
GraphicBufferAllocator
分配图形内存块时,步骤如下:
- 通过
Gralloc1::Device
创建Gralloc1::Descriptor
,并为其设置要分配的图形内存块的规格,包括图像的长和宽,图像的像素格式,图形内存块的使用场景,其中图形内存块的使用场景参数主要用于性能优化。 - 以
Gralloc1::Descriptor
、图形内存块的标识 ID,和图形内存块句柄的指针作为参数,通过Gralloc1::Device
的allocate()
分配图形内存块,分配的结果通过图形内存块句柄的指针返回。 - 分配完成之后,可以通过
Gralloc1::Device
图形内存块的步进,即单行像素数据占用的内存字节数。底层可能为了性能优化,内存对齐等,分配的内存块可能大于保存实际图像所需要的大小。 - 对分配结果做记录。
GraphicBufferAllocator
维护一个图形内存块句柄到图形内存块规格的映射。
GraphicBufferAllocator
释放图形内存块时的步骤则基本相反:
- 通过
Gralloc1::Device
释放图形内存块句柄。 - 移除分配记录。
GraphicBufferMapper
类提供了对图形内存块的 lock / unlock 操作。该类定义(位于 frameworks/native/include/ui/GraphicBufferMapper.h
)如下:
GraphicBufferMapper
通过 Gralloc1::Device
提供对图形内存块的 lock / unlock 操作,这些操作的定义(位于 frameworks/native/libs/ui/GraphicBufferMapper.cpp
)如下:
lock 时,需要以 Rect
的形式给 GraphicBufferMapper
传入 lock 的区域,这个区域会被做一个转换。GraphicBufferMapper
通过 Gralloc1::Device
执行 lock 操作。并将 lock 的结果,也就是映射到应用程序进程的虚拟地址空间的图形内存块的地址通过传入的 vaddr
返回给调用者。
像素数据格式有 RGB 和 YUV 之分,在 lock YUV 图形内存块时,如果设备支持 GRALLOC1_CAPABILITY_ON_ADAPTER
,会直接通过 Gralloc1::Device
完成操作;否则,通过 Gralloc1::Device
的 lockFlex()
完成操作。
这里的 fence 是什么,用来做什么的?
打赏
Done.
Android OpenGL 图形系统分析系列文章
在 Android 中使用 OpenGL
Android 图形驱动初始化
EGL Context 创建
Android 图形系统之图形缓冲区分配
Android 图形系统之gralloc