OpenHarmony图形子系统入门(一) 常见概念扫盲 原创 精华
目的
由于中文圈关于图形子系统的介绍资料太少,且图形系统相对庞大复杂,对新手来说很不友好。本文从新手的角度,在对OpenHarmony 图形子系统进行移植调试的过程中,将自己逐步积累的对图形系统的认识分享出来。本文参考了众多国内外的技术文章以及来自Wiki百科的专业解释,使用通俗的语言对图形系统常见名词进行说明。详细的解释可以查询参考附录文章。
本文的图形系统主要基于OpenHarmony-3.0-LTS 版本。同时也会跟进主线进行后续的探索。旨在帮助大家在进行标准系统(L2)图形子系统移植调试中,对相关概念的快速熟悉及常用的调试方法总结。
总览
本文自下而上,从南到北去熟悉图形系统,直至与北向应用层对接,初步分以下部分:
- 基于DRM的基础显示系统介绍和调试。
- 基于Wayland 协议的图形系统介绍。
- Graphic 子系统封装及与应用层的对接分析。
先放一张总览图,帮助大家理解。我们将硬件和kernel 的组合称为平台,接下来先介绍平台的基础显示系统。
1. DRM 基础显示系统介绍
基本概念:
DRM( Direct Rendering Manager)即直接渲染管理器。它是为了解决多个程序对 Video 硬件资源的协同使用问题而产生的,可以将它简单理解为一个仲裁器的作用。它也解决了原先Linux fbdev 无法满足对基于3D加速GPU的视频硬件控制需求的问题。
DRM 框架向用户空间提供了一组 API,提供了一系列的 ioctl操作,允许用户程序直接访问操纵 GPU以及显示模式的配置。即这两类行为:Graphics Execution Manager (GEM)、Kernel Mode-Setting (KMS)。
前者 GEM 主要是对 FrameBuffer 的管理,如显存的申请释放 (Framebuffer managing) ,显存共享机制 (Memory sharing objects), 及显存同步机制 (Memory synchronization),而后者 KMS 主要是完成显卡配置 (Display mode setting) 。
libdrm
libdrm 是个跨驱动中间件,帮助用户空间程序通过DRI协议与内核DRM Core通讯。即将drm 提供的系列 ioctl 接口进一步封装,方便用户使用。
KMS
KMS 表示 Kernel Mode Setting,是DRM API的一个子部件。用来设置显卡的模式,比如屏幕分辨率、色深、刷新率、显示通路(pipeline)选择等。KMS 也是为了解决多个模块同时进行显卡模式设置容易冲突的问题,将原先的User space Mode setting 移到 Kernel中进行统一管理,并入到DRM module中。另外如果你对fbdev比较熟悉,可以把kms 当成 fbdev的替代。
kms 设备模型:
KMS 将输出设备管理和模型化成一系列抽象的硬件模块,可以在显示控制器的显示输出管道(display output pipeline)中看到 。pipeline 一般是按这样连接的:framebuffer → plane → crtc → encoder → connector → panel。每个模块解释如下:
- crtc (CRT controller) 表示一个扫描输出引擎。Rockchip 这里一般指 vop (Video output processer), 一般一个屏幕对应一个crtc。
- connector 表示 video 信号输出的地方,通常就是屏幕接口,如VGA,HDMI, DP等。
- encoder: 需要将crtc 输出的 video 时序信号编码成对应接口的格式。如TMDS、LVDS等。
- plane 是个内存对象,包含一个将要输出给crtc 的buffer。
- panel 就是指显示屏。
每个模块都有一个ID。如果涉及到kms 详细配置,可以参考相关的文章,这里不细展开。代码可以参考 third_party/libdrm/tests/modetest 或者 third_party/weston/libweston/backend-drm/kms.c。
调试:
系统支持DRM/KMS你就可以完成基础的显示了。比如在我的开发板上输入:
modetest -M rockchip -s 79@67:#0
(命令格式说明: -s <connector_id>@<crtc_id>:#<mode index>),这样就可以显示出一个测试图形。通常用modetest 工具来测试基础的底层显示通路是否正常。
详细的使用可以参考下面链接的文章。
linux DRM/KMS 测试工具 modetest、kmscude、igt-gpu-tools (一)
调试完基本显示通路后,可以开始熟悉compositer了。先介绍一下wayland 协议,及常见名词概念。
2. Wayland
Wayland 是一个新的display server 和client 之间的通讯协议。使用Wayland 协议的 display server 称作 Wayland compositor, 而client 一般就是指与用户交互的应用程序。Wayland compositor 负责将来自各个client 输出的图像合成,输出至屏幕上。它优于老的 X11显示系统,Wayland 协议速度更快更安全,在触屏、HiDPI 和多屏显示上有更好的支持。它允许 client 直接进行渲染,以及调用系统级的内存管理接口。它在server 端进行窗口管理和合成,通过减少上下文切换,显著地降低复杂性和略微的提升性能。
Wayland 协议通讯使用 Unix Domain stream socket。endpoint可通过 $WAYLAND_DISPLAY 环境变量来配置。
关于Wayland 协议的详细文档参考文献[2]:
libwayland-client and libwayland-server
一个Wayland 协议的开源实现将其分为两个C库: libwayland-client 和 libwayland-server。主要职责就是实现互相的 Inter-process communication(IPC),确保协议对象的编组和消息同步。
Surface
一个Surface 用来管理一个矩形像素网格,client 创建它用来显示内容到屏幕上。Client 不知道它的surface 在全局中的显示位置,也无法访问其它client 的 surface。
当一个 client 完成写入 pixels 时,它会将buffer 提交(commit) 至 compositor。当compositor 用完之后,它将 buffer 释放回 client。
Weston
weston 是 Wayland compositor 的一个参考实现。
libweston 致力于将 weston 中可重用的部件封装成库。libweston 提供了大部分枯燥乏味的Wayland 协议实现,以及输入输出系统的接口,这样让只想写新的Wayland 窗口管理器(WM)或者小型桌面环境(DE)的人专注于写WM 部分。
Rendering model
Wayland 协议本身并不包含 rendering API。你可以自由选择如何实现渲染。Wayland遵循直接渲染模型(direct rendering model),渲染可以完全在 Client 端进行, 并将内容直接渲染至一个与 compositor 共享一个buffer 里面。
pixman 是一个底层的软件库用来进行像素处理,如图像合成及栅格化处理等。它主要使用CPU及一些SIMD扩展指令来进行渲染运算。相对于使用GPU速度会慢很多。如果我们想要加入GPU渲染的话,可以通过 egl接口调用一些标准的图形库(如OpenGL, OpenGL ES等)。
Backend
weston compositor 负责将合成后的图像输出至显示屏上,而drm 就可以作为其显示输出的后端。此外还可以选择fbdev、X11等作为其后端。以及最重要的ohos 定义的hdi_backend。
后面我们将对weston compositor 进行深入分析,以及介绍如何编写一个Wayland client。
附参考文献:
[1]Direct Rendering Manager - Wikipedia
[2]Wayland