1. glxinfo 与 eglinfo 命令有什么关系
| 工具 | 接口层 | 运行环境(显示系统) | 典型场景 |
|---|---|---|---|
glxinfo |
GLX (OpenGL + 强绑定X11) | X11(老牌窗口系统依赖GLX) | 传统桌面(PC / Xorg) |
eglinfo |
EGL (窗口系统无关接口) | Wayland / DRM / FB / X11 | 嵌入式 / Wayland / 无窗口系统 |
glxinfo用于测试 GLX + OpenGL(桌面GL),glxinfo | grep -E 'vendor|OpenGL|llvmpipe输出 vendor: Mesa / llvmpipe → 结论:GLX → software rendering(CPU)。eglinfo用于测试 EGL 实现 + GLES(OpenGL ES) 驱动,eglinfo | grep -E 'vendor|OpenGL输出 OpenGL ES vendor: Vivante → 结论:EGL → Vivante GPU(真硬件)
2. OpenGL ,GLX与EGL什么关系?
-
OpenGL 是跨平台图形渲染API,只负责画出2D/3D图形,通过调用如
glDrawArrays(...) glBindTexture(...)等接口,可以实现画三角,贴纹理等。但他本身不知道画完该显示到哪个拆给你看,不懂如何处理键盘鼠标等系统事件。 -
GLX 和 EGL 是接口,OpenGL与OpenGL ES是渲染API。前者为后者在显示平台上创建上下文环境。
-
GLX → 只能配 OpenGL(桌面GL)渲染到X11。
-
EGL → 可以配:OpenGL ES(主流嵌入式)或 OpenGL(桌面也支持)渲染到跨平台(Wayland / DRM / X11)。
-
GLX 是一套API规范(接口标准),只负责给 X11 窗口提供 OpenGL 上下文和帧缓冲交换。glx 有接口函数如:
glXCreateContext() glXSwapBuffers() -
EGL 是比 GLX 新的一套API规范,
eglCreateContext() eglSwapBuffers(),相比于GLX 是 X11 专用版本,而EGL 是跨平台通用版本。EGL 本身只是一份由 Khronos Group 维护的 API 规范(标准)。在 Linux 下,具体的实现(也就是.so动态链接库)确实是由各硬件厂商或开源社区提供的。比如 NVIDIA 提供专有的libEGL_nvidia.so,AMD/Intel 依赖开源的 Mesa (libEGL_mesa.so)。它们对外的函数签名完全一致,但底层的 GPU 指令翻译完全不同。 -
在实际代码中,GLX/EGL 与 OpenGL 的API函数绝对是混着用的,是分工协作的平行关系 。GLX/EGL 负责"搭舞台和建画室这些山下文基础设置(初始化)",OpenGL 负责"在舞台上画画(渲染)。EGL/GLX 负责生命周期管理:创建/销毁上下文、绑定窗口、同步帧率(V-Sync)、交换前后缓冲区。OpenGL 负责纯图形计算:顶点处理、着色器执行、光栅化。
EGL / GLX(接口层)
↓
Wayland / X11 / DRM / FB(显示系统)
↓
GPU Driver / Kernel
| 名称 | |
|---|---|
| X11(显示系统) | 老牌窗口系统,架构复杂,依赖 GLX X11有两种客户端库:Xlib 与 xcb ,他们是用来访问 X11 的工具 GLX → 更常搭配 Xlib,EGL → 可以搭配 XCB |
| Xwayland | "运行在 Wayland 上的迷你 X11 服务器,给只能识别x11的老程序用。 |
| Wayland(协议) | X11 的替代品,简单,compositor(合成器)直接控制显示。( Wayland 是协议(protocol),weston / mutter / kwin 是实现(compositor)) |
| DRM(内核层) | Linux 内核里的显示/显卡驱动层,不提供窗口系统,用户态通过 libdrm / gbm 使用,没有 DRM,就没有 GPU 显示 |
| FB | 最原始的显示方式(/dev/fb0),直接把像素写进一块内存,简单性能差,基本被 DRM 替代 |
如何看我当前的显示系统使用的X11还是Wayland还是DRM,有没有可能他们三个共存?
| 情况 | 说明 |
|---|---|
$DISPLAY 有值(如 :0) |
✅ X11 |
$WAYLAND_DISPLAY 有值 |
✅ Wayland |
| 两个都没有 | ✅ DRM/GBM(无窗口系统 |
2.1 如何证明我支持哪种平台?
2.1.1 验证 Wayland 能力(平台级)
echo $WAYLAND_DISPLAY # 看看有没有
unset DISPLAY # 阻断客户端直连 Xwayland的路径,只能走 Wayland
glmark2-es2-wayland # 展示3D渲染的马
成功显示:✅ 证明:Wayland + EGL + GPU 全链路 OK
2.1.2 验证 X11 能力(通过 Xwayland)
目标:证明板子能运行 X11 client
bash
apt install x11-apps
root@imx8mpfrdm:~# echo $WAYLAND_DISPLAY
wayland-0
root@imx8mpfrdm:~# unset WAYLAND_DISPLAY # 切断"客户端直连 Wayland"的路径,并没有关闭 Wayland(weston 仍在运行)
root@imx8mpfrdm:~# echo $WAYLAND_DISPLAY
root@imx8mpfrdm:~# ls /tmp/.X11-unix/
X0
root@imx8mpfrdm:~# xdpyinfo | grep version
version number: 11.0
X.Org version: 24.1.6
root@imx8mpfrdm:~# xeyes # 成功弹出眼睛框框
成功显示:X11 socket + server 完整可用(Xwayland)
结论:我的程序支持:
- 能跑 X11(走 Xwayland)
- 能跑 Wayland(直接)
- 能跑 DRM(纯嵌入式)
3. OpenGL 与 RHI 什么关系?
OpenGL 是什么?跨平台图形渲染API,只负责 "如何画图形" (顶点处理、着色器执行、纹理映射等)。但OpenGL是第一代高级抽象 API(1992 年诞生),Vulkan 和 Metal 属于第二代低开销 API(2014--2015 年推出),它们通过 更低的 CPU 开销 和 更精细的 GPU 控制 解决了 OpenGL 的固有瓶颈,OpenGL正在逐步被Vulkan 和 Metal取代。
RHI 是什么?Qt6 引入的位于Qt的内部抽象层,他将OpenGL/Vulkan/Metal 等图形 API做了封装,最终让Qt场景图无需关心底层用的是 OpenGL 还是 Vulkan,而自动选择最优后端。(Windows → 默认 Direct3D 12 ;macOS/iOS → 默认 Metal ;Linux/Android → 默认 Vulkan )在 Qt6中通过环境变量**QT_QUICK_BACKEND**来设置支持哪种渲染策略。只有个有效值,①默认设置为rhi,启用 RHI 渲染,由 RHI 选择具体图形 API。②software,纯 CPU 软件渲染(无 GPU 加速),性能极低,仅用于调试或无 GPU 环境。
RHI 的本质作用
- Qt 内部的"翻译层" :
- 当你用 QML 写
Rectangle { color: "blue" }时,Qt 的场景图会生成渲染指令,但不直接调用 OpenGL。 - RHI 会自动将这些指令翻译成 OpenGL/Vulkan/Metal 的调用,开发者无需修改代码。
- 当你用 QML 写
- 核心价值 :
- 解耦 Qt 与图形 API:Qt 6 不再硬编码依赖 OpenGL(Apple 已废弃它),而是通过 RHI 无缝切换 Vulkan/Metal。
- 统一资源管理:RHI 封装了 GPU 资源(纹理/缓冲区)的创建/释放逻辑,避免 OpenGL 的状态机陷阱。
#mermaid-svg-swgs9XDuDuoPBBa4{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-swgs9XDuDuoPBBa4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-swgs9XDuDuoPBBa4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-swgs9XDuDuoPBBa4 .error-icon{fill:#552222;}#mermaid-svg-swgs9XDuDuoPBBa4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-swgs9XDuDuoPBBa4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-swgs9XDuDuoPBBa4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-swgs9XDuDuoPBBa4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-swgs9XDuDuoPBBa4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-swgs9XDuDuoPBBa4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-swgs9XDuDuoPBBa4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-swgs9XDuDuoPBBa4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-swgs9XDuDuoPBBa4 .marker.cross{stroke:#333333;}#mermaid-svg-swgs9XDuDuoPBBa4 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-swgs9XDuDuoPBBa4 p{margin:0;}#mermaid-svg-swgs9XDuDuoPBBa4 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-swgs9XDuDuoPBBa4 .cluster-label text{fill:#333;}#mermaid-svg-swgs9XDuDuoPBBa4 .cluster-label span{color:#333;}#mermaid-svg-swgs9XDuDuoPBBa4 .cluster-label span p{background-color:transparent;}#mermaid-svg-swgs9XDuDuoPBBa4 .label text,#mermaid-svg-swgs9XDuDuoPBBa4 span{fill:#333;color:#333;}#mermaid-svg-swgs9XDuDuoPBBa4 .node rect,#mermaid-svg-swgs9XDuDuoPBBa4 .node circle,#mermaid-svg-swgs9XDuDuoPBBa4 .node ellipse,#mermaid-svg-swgs9XDuDuoPBBa4 .node polygon,#mermaid-svg-swgs9XDuDuoPBBa4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-swgs9XDuDuoPBBa4 .rough-node .label text,#mermaid-svg-swgs9XDuDuoPBBa4 .node .label text,#mermaid-svg-swgs9XDuDuoPBBa4 .image-shape .label,#mermaid-svg-swgs9XDuDuoPBBa4 .icon-shape .label{text-anchor:middle;}#mermaid-svg-swgs9XDuDuoPBBa4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-swgs9XDuDuoPBBa4 .rough-node .label,#mermaid-svg-swgs9XDuDuoPBBa4 .node .label,#mermaid-svg-swgs9XDuDuoPBBa4 .image-shape .label,#mermaid-svg-swgs9XDuDuoPBBa4 .icon-shape .label{text-align:center;}#mermaid-svg-swgs9XDuDuoPBBa4 .node.clickable{cursor:pointer;}#mermaid-svg-swgs9XDuDuoPBBa4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-swgs9XDuDuoPBBa4 .arrowheadPath{fill:#333333;}#mermaid-svg-swgs9XDuDuoPBBa4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-swgs9XDuDuoPBBa4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-swgs9XDuDuoPBBa4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-swgs9XDuDuoPBBa4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-swgs9XDuDuoPBBa4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-swgs9XDuDuoPBBa4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-swgs9XDuDuoPBBa4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-swgs9XDuDuoPBBa4 .cluster text{fill:#333;}#mermaid-svg-swgs9XDuDuoPBBa4 .cluster span{color:#333;}#mermaid-svg-swgs9XDuDuoPBBa4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-swgs9XDuDuoPBBa4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-swgs9XDuDuoPBBa4 rect.text{fill:none;stroke-width:0;}#mermaid-svg-swgs9XDuDuoPBBa4 .icon-shape,#mermaid-svg-swgs9XDuDuoPBBa4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-swgs9XDuDuoPBBa4 .icon-shape p,#mermaid-svg-swgs9XDuDuoPBBa4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-swgs9XDuDuoPBBa4 .icon-shape .label rect,#mermaid-svg-swgs9XDuDuoPBBa4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-swgs9XDuDuoPBBa4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-swgs9XDuDuoPBBa4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-swgs9XDuDuoPBBa4 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} QML 代码
Qt Quick
场景图 QSGNode 树
RHI 渲染指令
QPA 平台插件
XCB / X11
Wayland
EGLFS
OpenGL/Vulkan surface
GPU 驱动
当 QT_QUICK_BACKEND 是RHI 模式时,可以通过 QSG_RHI_BACKEND 指定RHI 使用的具体图形 API:
| 值 | 适用平台 | 说明 |
|---|---|---|
vulkan |
Linux/Android/Windows | 启用 Vulkan 后端 |
metal |
macOS/iOS | 启用 Metal 后端 |
d3d11 |
Windows | 启用 Direct3D 11 后端 |
d3d12 |
Windows | 启用 Direct3D 12 后端 |
opengl |
不推荐 | 启用 OpenGL 后端(仅当 Vulkan/Metal 不可用时回退) |
RHI 与窗口系统是平行协作关系:
- RHI 负责 "画什么"(渲染指令)。
- QPA(XCB/Wayland/EGLFS)负责 "画到哪"(提供渲染目标)。
更换窗口系统不影响 RHI 工作:
- 在 Wayland 上运行 Qt Quick 应用时,RHI 仍会默认使用 Vulkan(Linux)或 Metal(macOS),不行会回退到OpenGL。
- 在 EGLFS(嵌入式无窗口系统)上,RHI 通过
EGL直接与 GPU 交互,无需 X11/Wayland。
3.1 Qt 会选择 EGL 还是 GLX?
这个问题本身就有毛病,Qt不会自动选择,如果设置了Qt为RHI模式,RHI负责自动选择渲染后端。
Qt图形路径分三层决策:① 选择 QPA 平台插件(决定窗口系统)② 在该平台插件下选择 GL backend(GLX / EGL)③ 创建 OpenGL / GLES 上下文。下面我们看每一步分别怎么做的。
3.1.1 第一步:QPA 平台插件如何选择
QPA = Qt Platform Abstraction ,本质是Qt和操作系统/窗口系统之间的适配层,常见 QPA 插件包括:
| 插件 | 对应系统 |
|---|---|
| wayland | Wayland compositor(weston) |
| xcb | X11 / Xwayland |
| eglfs( eglfs = Qt + EGL + DRM 的"直出模式") | 直接 DRM/KMS(不经过窗口系统) |
| linuxfb | framebuffer |
| 自动检测 | 优先 Wayland(若 WAYLAND_DISPLAY 存在且插件可用),否则回退 X11 |
优先级如下(Qt 只有在 qtwayland 插件可用且初始化成功 时才会走 Wayland;否则仍可能走 xcb(含 Xwayland)):
1. QT_QPA_PLATFORM(环境变量)如:QT_QPA_PLATFORM=wayland QT_QPA_PLATFORM=xcb
2. QApplication 参数 -platform 如:./my_qt_app -platform wayland ./my_qt_app -platform xcb
3. 编译默认 / 自动检测(自动加载策略:Wayland > X11)
3.1.2 第二步:QPA 插件内部决定 EGL/GLX(非 RHI 决策)
当设置QT_QUICK_BACKEND=rhi时,RHI 不参与 EGL/GLX 选择 ,这是 QPA 插件的内部实现细节。 仅当 RHI 选择 OpenGL 作为后端时 ,QPA 插件才会调用 EGL/GLX。若 RHI 选择 Vulkan,则完全跳过 EGL/GLX(直接使用 Vulkan WSI)。
| QPA 平台插件 | 窗口系统 | 必须使用的窗口集成层 | 原因 |
|---|---|---|---|
wayland |
Wayland | EGL | Wayland 协议强制要求 EGL 创建 OpenGL 上下文(无 GLX 选项)。 |
xcb |
X11/Xwayland | GLX(默认)或 EGL | X11 历史兼容 GLX;可通过 QT_XCB_GL_INTEGRATION=xcb_egl 强制 EGL。 |
eglfs |
DRM/KMS 直出 | EGL | 无窗口系统,直接通过 EGL 绑定 DRM(无 GLX 可能)。 |
GBM是通用缓冲区管理器,GBM是用户态分配GPU/显示buffer的库。是EGL的下游工具库(libgbm.so 等等),跟Wayland不属于同一层。GBM就做一件事:分配显卡能用的 buffer。在 无 X11 无 Wayland的时候,可以选择 EGL+GBM+DRM 的模式。所以引出了两种模式(只有两种吗?):
-
模式1:EGL → GBM(管buffer)→ DRM
-
模式2:EGL → Wayland(weston) → compositor(管buffer)→ DRM
Wayland:定义"怎么说话"
compositor:负责"干活显示"
GBM:负责"分配显存buffer"
EGL:负责"OpenGL上下文"