Android 与 Hyprland 的绘图框架:内核共用,合成方式不同
结论:Android 和 Hyprland 画出一帧画面都分三步:应用让 GPU 画进 buffer,合成器把各窗口拼成一帧,KMS 让显示控制器把这一帧送上屏。 内核以下的部件两边共用,包括 KMS 显示驱动、Mali 的 kbase 驱动和 dma-buf。差别都在用户态,集中在三处:
- buffer 怎么分配、怎么传给合成器;
- 合成交给 GPU 还是交给显示控制器的 plane;
- Mali 的用户态驱动以哪种形态加载。
| 情境 | 我们的 SoC 在 Android 上已经完整跑通显示:SurfaceFlinger、HWC、gralloc 和 Android 版 Mali DDK 各管一段。 |
|---|---|
| 冲突 | 同一颗 SoC 要跑 Omarchy 桌面。它的合成器 Hyprland 不用 SurfaceFlinger、HWC 和 gralloc,团队对这套框架不熟。 |
| 问题 | 两套绘图框架各由哪些部件组成?哪些部件能共用,哪些要另做? |
总览:上半部分各走各的,下半部分完全共用
Section titled “总览:上半部分各走各的,下半部分完全共用”下图左右两列一一对应,中间一列是层名。颜色表示部件由谁提供,整个系列的图都用这套配色。
- 应用:Android 应用由 HWUI 通过 Skia 绘制,Wayland 客户端由 Qt、GTK 等工具包绘制。两边都只调用 EGL、GLES 或 Vulkan。
- GPU 用户态驱动:两边都是 Arm 的 Mali DDK,但用户态库不能互换。Android 版链接 bionic,对接 Android 的窗口系统;Linux 版链接 glibc,自带 GBM 和 Wayland 支持。
- buffer 分配与传递:
- Android 由厂商的 gralloc 分配 buffer,经 BLASTBufferQueue 和 Transaction 交给合成器;
- Linux 由 DDK 自带的 GBM 分配 buffer,经 Wayland 的
linux-dmabuf协议交给合成器。 - 两边传的都是 dma-buf,只是接口不同。
- 合成器:SurfaceFlinger 先问 HWC 哪些图层能交给硬件叠加,硬件叠不下的才用 GPU 合成;Hyprland 把所有窗口都用 GPU 合成。
- 送屏:HWC 是厂商写的 HAL,把图层分给多个 plane;Aquamarine 是 Hyprland 自带的库,只用主平面和光标平面。两者最终都调用 KMS 的 atomic 提交。
内核和硬件两层两边完全相同。所以把 SoC 从 Android 迁到 Omarchy,内核驱动做好一次就能两边共用。
文章列表:先讲概念,再分别拆两套框架,最后对照
Section titled “文章列表:先讲概念,再分别拆两套框架,最后对照”| 文章 | 结论 |
|---|---|
| 一帧画面怎么上屏 | GPU 把像素写进 buffer,fence 通知下游什么时候写完,plane 从 buffer 取图,CRTC 把各 plane 混成一帧扫描上屏 |
| Android 绘图框架 | 应用画、SurfaceFlinger 统筹、HWC 分配 plane;GPU 只合成硬件叠不下的图层 |
| Mali DDK 在 Android 里管什么 | DDK 由一个用户态库、一个内核驱动和一份固件组成,只负责渲染;它和 gralloc、HWC 靠 dma-buf 与 fence 衔接 |
| Hyprland 绘图框架 | 一个进程包办合成和送屏,所有窗口都用 GPU 合成,没有 HWC、gralloc 这类独立的 HAL |
| 两套框架对照 | 内核以下做一次两边共用,用户态各做三件;最大的行为差异是合成策略,直接影响功耗 |
| 演进:Android 怎样并回上游 DRM | Android 先在内核外试新做法,验证后合进上游,或改用上游的同类机制;今天两边已经共用一套内核接口 |
只想快速建立全局认识,读第一篇和《两套框架对照》即可。要动手改驱动,再按需读中间三篇。