在 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. 完整示例
cpp
#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 的 Plane
for (uint32_t i = 0; i < plane_res->count_planes; i++) {
drmModePlanePtr plane = drmModeGetPlane(drm_fd, plane_res->planes[i]);
if (!plane) continue;
// 4. 查找 zpos 属性 ID
uint32_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
,需通过信号/槽机制在合适的时机触发。
-