跳转到内容

Android 与 Hyprland 的绘图框架:内核共用,合成方式不同

结论:Android 和 Hyprland 画出一帧画面都分三步:应用让 GPU 画进 buffer,合成器把各窗口拼成一帧,KMS 让显示控制器把这一帧送上屏。 内核以下的部件两边共用,包括 KMS 显示驱动、Mali 的 kbase 驱动和 dma-buf。差别都在用户态,集中在三处:

  1. buffer 怎么分配、怎么传给合成器;
  2. 合成交给 GPU 还是交给显示控制器的 plane;
  3. Mali 的用户态驱动以哪种形态加载。
情境我们的 SoC 在 Android 上已经完整跑通显示:SurfaceFlinger、HWC、gralloc 和 Android 版 Mali DDK 各管一段。
冲突同一颗 SoC 要跑 Omarchy 桌面。它的合成器 Hyprland 不用 SurfaceFlinger、HWC 和 gralloc,团队对这套框架不熟。
问题两套绘图框架各由哪些部件组成?哪些部件能共用,哪些要另做?

总览:上半部分各走各的,下半部分完全共用

Section titled “总览:上半部分各走各的,下半部分完全共用”

下图左右两列一一对应,中间一列是层名。颜色表示部件由谁提供,整个系列的图都用这套配色。

总览:Android 与 Hyprland 绘图框架的五层对照

  1. 应用:Android 应用由 HWUI 通过 Skia 绘制,Wayland 客户端由 Qt、GTK 等工具包绘制。两边都只调用 EGL、GLES 或 Vulkan。
  2. GPU 用户态驱动:两边都是 Arm 的 Mali DDK,但用户态库不能互换。Android 版链接 bionic,对接 Android 的窗口系统;Linux 版链接 glibc,自带 GBM 和 Wayland 支持。
  3. buffer 分配与传递:
    • Android 由厂商的 gralloc 分配 buffer,经 BLASTBufferQueue 和 Transaction 交给合成器;
    • Linux 由 DDK 自带的 GBM 分配 buffer,经 Wayland 的 linux-dmabuf 协议交给合成器。
    • 两边传的都是 dma-buf,只是接口不同。
  4. 合成器:SurfaceFlinger 先问 HWC 哪些图层能交给硬件叠加,硬件叠不下的才用 GPU 合成;Hyprland 把所有窗口都用 GPU 合成。
  5. 送屏: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 怎样并回上游 DRMAndroid 先在内核外试新做法,验证后合进上游,或改用上游的同类机制;今天两边已经共用一套内核接口

只想快速建立全局认识,读第一篇和《两套框架对照》即可。要动手改驱动,再按需读中间三篇。