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

相关推荐
Coffeeee21 小时前
两个例子,帮你快速理解什么是Token
人工智能·程序员·ai编程
文心快码BaiduComate1 天前
从个人提效到组织提效:Comate辅助构建自我进化的AI研发系统
前端·程序员
微信公众号AI创造财富1 天前
VSC++ xc0150002 是 Visual C++ 运行库缺失导致的?
程序员
37手游移动客户端团队1 天前
招聘-高级安卓开发工程师
android·客户端
AskHarries1 天前
企业微信 / Telegram / WhatsApp 接入
程序员
用户41659673693551 天前
WebView 请求异常排查操作手册
android·前端
SamDeepThinking1 天前
一条UPDATE语句在MySQL 8.0中到底加了几把锁?
后端·mysql·程序员
CodeSheep1 天前
他俩只靠写代码,登上了胡润财富榜!
前端·后端·程序员
Kapaseker1 天前
学不动了,入门 Compose Styles API
android·kotlin
To_OC1 天前
从一次栈溢出报错说起,我把递归彻底扒明白了
javascript·算法·程序员