GUI 系统 —— SurfaceFlinger( 一)

一直想好好整理一下最近的学习成果,也在思考着怎么写才能比较准确的表达出来,或者看看自己是否真的掌握了显示系统 ------ SurfaceFlinger 这块的知识。

这块体系庞大,难度也很高,很容易陷进去看的云里雾里。在平常的工作中,有时候感觉自己理解的也不够透彻,所以这次下决心好好整理一下这块的内容。这块结合读过的《深入理解Android 内核设计思想》以及平台上面很多大佬的博客,来展开描述。

1. OpenGL ES 与 EGL

下面的图中描述了 SurfaceFlinger 与 OpenGL ES 等模块的关系图

我们从下往上看:

  1. Linux 内核提供了统一的 framebuffer 显示驱动,设备节点为 /dev/graphics/fb* 或者 /dev/fb*, 其中 fb0 表示第一个 Monitor, 当前系统实现中只用到了一个显示屏。
  2. Android 的 HAL 层提供了 Gralloc 和 Composer , Gralloc 包括了 fb 和 gralloc 两个设备。
    1. fb : 负责打开内核中的 framebuffer、初始化配置,并提供了 post、setSwapInterval 等操作接口。
    2. gralloc : 管理帧缓冲区的分配和释放。(意味着上层只能通过它来访问帧缓冲区,保证了系统对 framebuffer 的有序使用和统一管理)
    3. Composer: 为厂商自定制"UI合成"提供了接口。直接使用者是 SF 中的 HWComposer (管理 Composer ,同时还负责 Vsync 信号的产生和控制)
  1. FramebufferNativeWindow :将OpenGL 函数库 "本地化",将其与具体平台中的窗口系统建立其关联。
  2. 为 OpenGL ES 配置本地窗口的是 EGL, 更多的是一个接口协议。可以去读取 egl.cfg 这个配置文件,然后根据用户的设定来动态加载 libagl (软件实现) 或者 libhgl(硬件实现)。
  3. DisplayDevices: 描述系统中支持的各种"显示设备"------ 具体有哪些 Display 是由 SF 在 readyToRun 中判断并赋值的。并且在初始化的时候会调用 eglGetDisplay、eglCreateWindowSurface 等接口,并利用 EGL 来完成对 OpenGL ES 环境的搭建。很多模块可以调用 OpenGL ES 提供的 API 的接口(glViewport、glClear、glMatrixMode、glLoadIdentity 等。
  4. OpenGL ES
    1. 配置类:EGL、DisplayHaedware 等
    2. 依赖类:FramebufferNativeWindow
    3. 使用类:使用者也可能是配置者,如 DisplayDevice 既扮演了构建 OpenGL ES 环境的角色,同时也是它的用户。

2. Android 的硬件接口 ------ HAL

HAL 是 android 子系统与 Linux Kernel 驱动之间通信的统一接口。

可以这样理解,HAL 层是连接硬件的抽象接口,它不可能针对某个硬件专门设计,它需要提取出众多设备中的共性,然后实现。同时,它要足够稳定,不能被频繁的改动,使用上面还得灵活。

一般情况下,HAL 接口由硬件厂商提供,手机厂商再拿来加载。

3. Android 终端显示设备的"化身"------ Gralloc 与 Framebuffer

Framebuffer 是内核系统提供的图形硬件的抽象描述,是一块包含屏幕显示信息的缓冲区。它提供的设备文件节点是 /dev/graphics/fb* , fb 按数字序号进行排列,如 fb0、fb1 等。其中第一个 fb0 是主显示屏幕,必须存在。

Android 中的各个子系统通常不会直接使用内核驱动,而是由 HAL 层来间接引用底层架构。

显示系统也同样如此,它借助于 HAL 层来操作帧缓冲区,而完成这一个任务的就是 Gralloc(主角登场),我们在前面也说了 Gralloc 属于 HAL 层。下面我们就来谈谈 Gralloc。

3.1. Gralloc 模块的加载

Gralloc 对应的模块是由 FramebufferNativeWindow 在构造函数中加载的。

hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);

#define GRALLOC_HARDWARE_MODULE_ID "gralloc"

hw_get_module 是上层使用者加载 HAL 库的入口, 然后去在以下路径中查找与ID值匹配的库。

#define HAL_LIBRARY_PATH1 "/system/lib/hw"

#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"

lib 库有以下几种形式:

gralloc.[ro.hardware].so

gralloc.[ro.product.board].so

gralloc.[ro.board.platform].so

gralloc.[ro.arch].so

当上面这些系统属性组成的文件不存在的时候,就使用默认的

gralloc.default.so

最后,这个 default 库是 Android 原生态的实现,源码位置在 hardware/libhardware/modules/gralloc/中。

它主要由 gralloc.cpp、framebuffer.cpp 和 mapper.cpp 三个主要源文件编译生成。

3.2. Gralloc 提供的接口

在第一步 Gralloc 被 HAL 库成功加载后,我们来看一下它所提供的一些重要接口。

Gralloc 是 hw_module_t 的子类。

Gralloc 中,open 接口可以帮助上层使用者打开两种设备。

#define GRALLOC_HARDWARE_FB0 "fb0" // 主屏幕

#define GRALLOC_HARDWARE_GPU0 "gpu0" // 负责图形缓冲区的分配和释放

这两个设备分别由 FramebufferNativeWindow 中的 fbDev 和 grDev 成员变量来管理。

下图为 Gralloc 模块的简图

相关推荐
ac-er88882 小时前
Yii框架中的队列:如何实现异步操作
android·开发语言·php
流氓也是种气质 _Cookie4 小时前
uniapp 在线更新应用
android·uniapp
zhangphil6 小时前
Android ValueAnimator ImageView animate() rotation,Kotlin
android·kotlin
徊忆羽菲6 小时前
CentOS7使用源码安装PHP8教程整理
android
编程、小哥哥7 小时前
python操作mysql
android·python
Couvrir洪荒猛兽8 小时前
Android实训十 数据存储和访问
android
五味香10 小时前
Java学习,List 元素替换
android·java·开发语言·python·学习·golang·kotlin
十二测试录11 小时前
【自动化测试】—— Appium使用保姆教程
android·经验分享·测试工具·程序人生·adb·appium·自动化
Couvrir洪荒猛兽12 小时前
Android实训九 数据存储和访问
android
aloneboyooo12 小时前
Android Studio安装配置
android·ide·android studio