在 Qt 中直接使用 drmModeObjectSetProperty
设置 Plane 的 zpos
值需要结合 Linux DRM/KMS API 和 Qt 的底层窗口系统(如 eglfs
平台插件)。以下是详细步骤和代码示例:
1. 原理说明
-
DRM/KMS 基础:
-
Plane:负责图层合成(如 Overlay、Primary、Cursor Plane)。
-
zpos 属性:控制 Plane 的层级顺序(值越大,显示越靠前)。
-
-
Qt 与 DRM:Qt 的
eglfs
平台插件默认使用 DRM/KMS 渲染,但未直接暴露 Plane 控制接口,需通过 libdrm 直接操作。
2. 准备工作
2.1 添加依赖
确保项目包含 libdrm 头文件和库:
# 安装 libdrm 开发包(Debian/Ubuntu)
sudo apt-get install libdrm-dev
在 .pro
文件中链接库:
qmake
LIBS += -ldrm
2.2 权限配置
确保应用程序有权访问 /dev/dri/card*
设备:
sudo usermod -aG video your_username # 将用户加入 video 组
3. 完整示例
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <xf86drm.h>
#include <xf86drmMode.h>int main(int argc, char *argv[]) {QGuiApplication app(argc, argv);// 1. 打开 DRM 设备int drm_fd = openDrmDevice();if (drm_fd < 0) {qFatal("Failed to open DRM device");}// 2. 获取 Plane 资源drmModePlaneResPtr plane_res = drmModeGetPlaneResources(drm_fd);if (!plane_res) {close(drm_fd);qFatal("Failed to get plane resources");}// 3. 遍历所有 Plane,查找可设置 zpos 的 Planefor (uint32_t i = 0; i < plane_res->count_planes; i++) {drmModePlanePtr plane = drmModeGetPlane(drm_fd, plane_res->planes[i]);if (!plane) continue;// 4. 查找 zpos 属性 IDuint32_t zpos_prop_id = findZposPropertyId(drm_fd, plane);if (zpos_prop_id) {// 5. 设置 zpos 值(示例:设置为最大值)if (setPlaneZpos(drm_fd, plane->plane_id, zpos_prop_id, 255)) {qDebug() << "Successfully set zpos for plane" << plane->plane_id;} else {qWarning() << "Failed to set zpos for plane" << plane->plane_id;}}drmModeFreePlane(plane);}// 6. 清理资源drmModeFreePlaneResources(plane_res);close(drm_fd);// 启动 Qt 应用QQmlApplicationEngine engine;engine.load(QUrl(QStringLiteral("qrc:/main.qml")));return app.exec();
}
5. 关键注意事项
-
Qt 平台插件选择:
-
运行应用时指定
eglfs
平台:./your_app -platform eglfs
-
确保 Qt 编译时启用了
eglfs
支持。
-
-
Plane 类型限制:
-
仅支持
DRM_PLANE_TYPE_OVERLAY
或DRM_PLANE_TYPE_PRIMARY
类型的 Plane。 -
通过
drmModeGetPlane
检查plane->possible_crtcs
确认 Plane 是否可用。
-
-
属性兼容性:
-
不同硬件(如 i.MX6、Rockchip、Intel)的 DRM 驱动可能对
zpos
的支持不同,需查阅硬件文档。 -
使用
drmModeGetProperty
检查属性是否可写(prop->flags & DRM_MODE_PROP_RANGE
)。
-
-
时序控制:
-
在 Qt 窗口初始化完成后操作 Plane,避免与 Qt 内部 DRM 调用冲突。
-
若动态调整
zpos
,需通过信号/槽机制在合适的时机触发。
-