图形子系统是Linux系统中比较复杂的子系统之一,这篇文章会逐步解释其涉及到的相关模块。我们先通过下面这张架构图对图形子系统有个大概的认知,在看完后面的知识后,再返过来加深理解。
图形硬件:内存
首先我们的图形数据会存储在哪里?
- Framebuffers 是内存中用来放像素的区域。
- 内存的位置取决于下面的情况:系统内存还是专用的图形内存,是分页管理的还是连续的内存?
- 存储时采用什么的格式,如何修改,是否采用压缩格式?
系统如何访问显存?
- 内存访问有DMA,IOMMU硬件设备。
- Linux系统有高速缓冲cache或者总线映射来访问内存。
图形硬件:显示
如何将内存中的数据显示到屏幕?这里包含一系列的流程:
- 首先会进行像素混合,对各平面/图层的混合操作包含旋转、缩放、格式化等。
- 其次定时器生成,拥有一张已经合成好的图片之后,需要通过正确的时序将图片发送出给显示器,为了兼容老的CRT显示器,常常叫做CRTC。
- 然后是接口层,像素以正确的时序发送后,会到达显示协议控制器(Display Protocol Controller),像素会以某个协议(HDMI)编码,并且该接口层会负责物理链路上信号的发送和接受,如HDMI的TMDS。
- 再然后是转码,为了链接不同的显示接口,通常还会有一个桥接装置用来做编码的转换。此步骤可选。
- 最后是显示,通过不同线缆连接到各种显示器
图形硬件:GPU渲染
如何根据几何体产生像素?
- GPUs负责渲染3D和2D图像。
- GPUs的渲染功能通常包括带有着色器的可编程的渲染管线,专用的矢量/SIMD指令集,纹理缓存和映射单元,移动平台上的Tiled Framebuffer功能。
- 需要有各种Shader(GLSL,HLSL)的编译器。
- GPUs除了可编程的着色阶段外,还允许通过命令配置一些特性。
图形APIs:Linux 内核
Linux内核提供了对底层硬件功能的低级访问。其中包含一些内核子系统和用户态API。
- Fbdev 是老的用来管理显卡的Framebuffer,缺失了很多现代GPU的功能支持。
- DRM是Linux中的现代图形子系统。其中包括KMS(Kernel Mode Setting),GEM(Graphics Execution Manager)。KMS是为了让显卡正常工作,提供设置模式(屏幕分辨率、颜色深度和刷新率等)。GEM则负责Buffer的管理(分配,共享,同步等)。
- libdrm则在用户态封装了DRM的系统调用。
图形APIs:用户态显示
帮助应用显示内容,这里面包含低级的显示服务APIs:
- X11是很古老的显示服务器协议,它是网络协议,存在很多问题。与之相关的低级库包括xlib, xcb。
- Wayland是现代通信协议,在安全性方面很出色。这个协议包括libwayland-{display, server} 。
高级的图形库、工具集包括:
- Qt, GTK, EFL这些widget-based 工具集。
- SDL(Simple Direct Media Layer)是一套开源的跨平台多媒体开发库。
图形APIs:用户态2D渲染
给用户提供2D的渲染操作,这其中包括一些我们常用的库:
- 基本的向量绘制库Cairo,Skia。
- 字体渲染引擎Freetype和Harfbuzz。
- 像素操作库如Pixman(像素处理的底层软件库,提供图像合成和梯形光栅化等功能),FFmpeg swscale(图像数据格式转换及图片的缩放),GMIC(实用的GIMP插件,包含一个完整的图像处理工具箱)。
- UI渲染会包括一些图形工具集合,还有ImGUI(immediate mode gui,没有状态很难做布局,动画等)。
图形APIs:用户态3D渲染
提供高级访问3D渲染,这其中包括一些标准的APIs:
- OpenGL(ES) 功能强大基于状态的图形API,它使用GLSL作为着色器语言。
- EGL本地窗口系统的集成API,GBM是一个极简的API,它提供了一种为与Mesa相关的图形渲染缓冲区分配机制,基于DRM的EGL。
- Vulkan是下一代图形API,使用SPIR-V作为着色器的中间描述语言。
OpenGL虽然被广泛使用,但是没有开源。Mesa3D是类OpenGL的开源实现,使用DRM。
总结
Linux的图形子系统确实比较复杂,上面只是简单列出了其中的模块及相关功能,大家可以根据自己的兴趣对每个子模块做深入学习。