Gralloc模块分析
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gralloc模块分析相关的知识,希望对你有一定的参考价值。
参考技术A Linux内核提供了统一的framebuffer显示驱动。Framebuffer是内核系统提供的图形硬件的抽象描述,称为buffer是因为它也占用了系统存储空间的一部分,是一块包含屏幕显示信息的缓冲区。Framebuffer借助于Linux文件系统向上层应用提供了统一而高效的操作接口,让用户空间运行的程序比较容易地适配多种显示设备。android系统中,每个显示屏被抽象为一个帧缓冲区,注册到FrameBuffer模块中,并在/dev/graphics目录下创建对应的fbX设备,framebuffer提供的设备节点为/dev/graphics/fb或者/dev/fb,Android系统在硬件抽象层中提供了一个Gralloc模块,封装了对帧缓冲区的所有访问操作。用户空间的应用程序在使用帧缓冲区之间,首先要加载Gralloc模块,并且获得一个gralloc设备和一个fb设备。有了gralloc设备之后,用户空间中的应用程序就可以申请分配一块图形缓冲区,并且将这块图形缓冲区映射到应用程序的地址空间来,以便可以向里面写入要绘制的画面的内容。
Android系统,为了隐藏各厂家自身特定硬件驱动实现细节,在用户空间定义了一套硬件抽象层,各厂商在Android的硬件抽象层实现特定硬件的操作细节,编译成动态库,以库的形式提供给用户使用。
hardware/libhardware/include/hardware/hardware.h 头文件中定义一个代表模块的结构体 (hw_module_t),其中包含模块的版本、名称和作者等元数据。Android系统 会根据这些元数据来找到并正确加载 HAL 模块。
hw_module_t 结构体还包含指向另一个结构体 hw_module_methods_t 的指针,后面这个结构体包含指向相应模块的 open 函数的指针。此 open 函数用于与相关硬件(此 HAL 是其抽象形式)建立通信。每个硬件专用 HAL 通常都会使用该特定硬件的附加信息来扩展通用的 hw_module_t 结构体。例如,在相机 HAL 中,camera_module_t 结构体包含一个 hw_module_t 结构体以及相机专用的其他函数指针:
实现 HAL 并创建模块结构体时,您必须将其命名为 HAL_MODULE_INFO_SYM,以下是 Nexus 9 音频 HAL 的示例:
设备是产品硬件的抽象表示。例如,一个音频模块可能包含主音频设备、USB 音频设备或蓝牙 A2DP 音频设备。
设备由 hw_device_t 结构体表示。与模块类似,每类设备都定义了一个通用 hw_device_t 的详细版本,其中包含指向特定硬件功能的函数指针。例如,audio_hw_device_t 结构体类型会包含指向音频设备操作的函数指针:
参数为模块的ID,最终会返回一个hw_module_t的结构体保存在参数module中。
每个硬件抽象层模块都必须定义HAL_MODULE_INFO_SYM符号,并且有自己唯一的ID。
hw_get_module会遍历规定的几个目录来查找名称对应的动态库,找到库的路径后,会调用load函数使用dlopen打开找到的库,并依据HAL_MODULE_INFO_SYM_AS_STR(其值为HMI)获取到hw_module_t(即HAL_MODULE_INFO_SYM)结构体指针。以及把dlopen返回的handle保存在hw_module_t中,而hw_module_t HMI 结构是一个全局结构。
每个硬件抽象层必须有自己的ID以及HAL_MODULE_INFO_SYM符号,Gralloc也不例外
hw_get_module硬件加载方法根据gralloc的ID, 查找到gralloc模块定义的HAL_MODULE_INFO_SYM并返回给hw_module_t结构,但是HAL_MODULE_INFO_SYM是private_module_t结构类型,如何赋值呢?
private_module_t负责管理显示驱动framebuffer相关的信息,包括framebuffer的fd, 有多少个缓存,系统帧缓冲区使用情况,动态可变的信息,固定属性的信息,显示屏的宽高,刷新率等信息。
private_module_t 第一个变量是gralloc_module_t结构。
gralloc_module_t 负责管理gralloc模块相关的操作,其第一个是属性是硬件抽象层规定的hw_module_t结构,其他都是关于gralloc模块图像buffer处理的相关操作方法。
hw_module_t结构如下:
硬件抽象层hw_module_t结构描述了硬件抽象层库相关的信息。如版本号,id, 名称,相关的操作方法等。
其中还定义了模块的打开模块的操作方法open.
根据以上的三个结构我们可以画出结构图如下:
回到上面问题,为什么private_module_t可以赋值给hw_module_t呢?这样看就很简单了,private_module_t的第一个变量就是gralloc_module_t, 而gralloc_module_t的数据第一个元素就是hw_module_t。private_module_t的首地址和hw_module_t的首地址是一样的,所以可以直接赋值过去。
除了hw_module_t的数据结构外,gralloc模块还定义了两种设备相关的数据结构:
1: framebuffer_device_t 用来描述系统帧缓冲区的信息
2:alloc_device_t 用于描述图像分配相关的信息
从上一节数据结构分析的过程中可知,设备打开的方法是在hw_module_t结构中定义的,定义打开的方法为
gralloc_device_open方法用来打开设备
参数hw_module_t为硬件抽象层加载得到的结构体
name 为打开目标设备的类型,分为两种
参数hw_device_t为打开的设备保存的结构,返回给调用者
分别分析下打开两种设备的过程
gralloc_device_open根据参数的不同来打开不同的设备,打开设备GRALLOC_HARDWARE_FB0,调用了fb_device_open方法
这个函数创建了一个fb_context_t的数据结构, 并对其进行初始化,fb_context_t的device变量就是framebuffer_device_t,用来描述fb设备的。
同时还注册了操作fb设备的几个函数, 其中fb_post函数比较关键,负责将图形缓冲区的内容渲染到Framebuffer的显存中。
然后使用mapFrameBuffer函数来获取帧缓冲区的信息,然后将信息保存到framebuffer_device_t结构中,并将fb设备映射到当前进程。
再看下mapFrameBuffer做了什么操作?
mapFrameBuffer函数做了几件事情
1:打开fb设备,获取fb驱动的相关信息
2:设置fb的 yres_virtual为双缓冲大小
3:计算像素密度
4:计算双缓冲大小,并将其映射到当前进程,将缓冲区起始地址宝尊在framebuffer_device_t的base属性中。
至此FB设备打开过程就分析完了,FB设备打开过程做了什么事情?
打开fb设备,根据fb设备初始化相关的显示信息,并把fb设备显存映射到当前进程方便访问,同时还注册了几个操作fb设备的方法。
gralloc设备使用结构体alloc_device_t来描述。结构体alloc_device_t有两个成员函数alloc和free,分别用来分配和释放图形缓冲区。
首先创建了一个gralloc_context_t的上下文,gralloc_context_t的device就是alloc_device_t, 对其进行初始化 ,同时注册了几个操作alloc_device_t设备的函数, gralloc_alloc和gralloc_free用于分配和释放图形缓冲区。
分析了两种设备打开的过程, 但是什么时候会打开这两种设备呢?
1:FB设备打开时机
FB设备打开时机实在HWCompser构造函数中打开的,说明HWCompser会操作fb设备,渲染图像缓冲区到显示缓冲区, 具体在分析HWCompser的时候在进行分析。
2:gralloc设备打开时机
gralloc设备用于管理GraphicBuffer图形缓冲区,是在GraphicBufferAllocator中打开的,GraphicBufferAllocator负责图形缓冲区的分配和释放。后续在做详细分析
文章参考: Android图形显示之硬件抽象层Gralloc
以上是关于Gralloc模块分析的主要内容,如果未能解决你的问题,请参考以下文章