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 模块的简图

相关推荐
数据猎手小k2 小时前
AndroidLab:一个系统化的Android代理框架,包含操作环境和可复现的基准测试,支持大型语言模型和多模态模型。
android·人工智能·机器学习·语言模型
你的小103 小时前
JavaWeb项目-----博客系统
android
风和先行3 小时前
adb 命令查看设备存储占用情况
android·adb
AaVictory.4 小时前
Android 开发 Java中 list实现 按照时间格式 yyyy-MM-dd HH:mm 顺序
android·java·list
似霰5 小时前
安卓智能指针sp、wp、RefBase浅析
android·c++·binder
大风起兮云飞扬丶5 小时前
Android——网络请求
android
干一行,爱一行5 小时前
android camera data -> surface 显示
android
断墨先生5 小时前
uniapp—android原生插件开发(3Android真机调试)
android·uni-app
无极程序员7 小时前
PHP常量
android·ide·android studio
萌面小侠Plus8 小时前
Android笔记(三十三):封装设备性能级别判断工具——低端机还是高端机
android·性能优化·kotlin·工具类·低端机