架构总览
核心实现使用 C++20 的资源所有权与容器设施,但安装的头文件保持 C ABI。公共 DTO 采用显式八字节布局,跨边界的 FD、超时与状态计数一律使用定宽类型;线上协议为 mirage-display-v1.2,不会因实现语言迁移而改变消息格式,旧 v1.1 端点会被拒绝。
MirageWallpaper 的 Linux 版本由“直接占有 X11 桌面”改为“协议驱动的离屏渲染”:渲染器导出 DMA-BUF 帧,桌面环境集成负责在 DE 自有的壁纸表面上显示,并把指针输入回传给渲染器。
X11 仍然受支持,但本仓库既不会创建、也不会管理裸的 X11 桌面窗口。Plasma X11、Plasma Wayland 等会话变体由各自的 DE 适配器通过 DE 提供的接口处理。
MirageQt 与渲染器之间的 JSON 标准输入通道继续负责暂停、音量、帧率与用户属性等壁纸控制,不属于本显示协议的一部分。
SceneWallpaper / WebWallpaper / VideoWallpaper 生产者 | DMA-BUF + 显式同步 | v 嵌入式 md_broker 路由核心(MirageQt 内) | $XDG_RUNTIME_DIR/mirage-wallpaper/display-v1.sock | v libmirage-display / | \ KDE Plasma GNOME Shell layer-shell X11/Wayland X11/Wayland Wayland onlybroker 只转发协议报文与文件描述符。像素数据留在 GPU 显存,从不经过 broker 拷贝。一个 broker 就能提供稳定的发现、多输出路由,以及在渲染器或桌面壳层重启后的自动恢复;稳定输出标识取代了过去的屏幕索引约定。
| 模块 | 职责 |
|---|---|
src/codec |
报文编解码与 SCM_RIGHTS 传输(magic、头校验、FD 精确计数) |
src/protocol |
各消息的编解码与 UTF-8 校验(golden 向量与解析边界) |
src/display |
消费端库:握手、缓冲池、帧、显式同步、指针与窗口状态上报 |
src/producer |
生产端库:握手、缓冲出借、帧提交、同步对象管理 |
src/broker |
路由核心:同 UID 校验、输出路由、格式协商、多消费者扇出 |
src/sync |
DRM syncobj 扇出、释放信号与 sync_file 桥接 |
src/common |
内部共享设施:工具、Unix 网络、出站队列、公共握手、DRM ABI |
gpu/egl |
EGL_EXT_image_dma_buf_import 导入与原生 fence 同步 |
gpu/vulkan |
外部内存 FD 导入、DRM 修饰符枚举、relay/blit 回退与导出 |
adapters/kde |
Plasma 6 壁纸插件:Qt Quick 显示项(OpenGL/EGL、Vulkan) |
examples |
headless 消费者与 mock broker,用于协议仿真与调试 |
tests |
编解码、协议、会话、路由、生产者、同步与 GPU 单元测试 |
消费者与生产者的连接、握手状态机与出站队列在 src/common 中共享,两个角色只保留注册报文的差异,避免出现三份近似的实现。
- 显示端(DE 适配器)连接 broker,用
REGISTER_OUTPUT注册稳定输出标识、逻辑桌面坐标和 DRM render node,随后上报CONSUMER_CAPS(格式、修饰符、UUID、输入能力)。 - 渲染端连接 broker,用
REGISTER_PRODUCER上报输出标识、DRM 渲染节点与支持的(fourcc, plane_count, modifier)元组。 - broker 为同一稳定标识建立路由,取格式交集协商,向生产者下发带消费者 GPU 身份的
OUTPUT_CONFIG。 - 生产者按
OUTPUT_CONFIG创建 GPU 资源,发送PRODUCER_GPU_BOUND确认身份;broker 确认一致后才接受带代际编号的OFFER_BUFFERS(DMA-BUF FD 随报文送达)。 - broker 向已绑定且兼容的每个显示端转发
BIND_BUFFERS;帧提交经PRODUCER_FRAME→FRAME_READY转发,携带 acquire sync_file 与 release syncobj,多显示端时用 syncobj 扇出保证每个消费者独立释放。 - 显示端采样完成后置位 release syncobj;全部显示端解绑(
UNBIND→UNBIND_DONE)后,broker 才允许生产者退役该代际并创建新代际。 - 显示端通过
POINTER_*与WINDOW_STATE回传输入与窗口事实,broker 以对应的 producer 侧报文转发给渲染器。
- 缓冲池代际编号在同一连接内不重复;一个缓冲槽最多只有一帧在途。
- 没有可用释放槽时,生产者跳过该渲染帧。
- 池拆除顺序固定为
UNBIND → UNBIND_DONE → 描述符关闭;替换池绝不复用旧代际。 - 回调负载默认是借用的;显式标注的所有权字段(帧的 acquire/release FD)转移归属;断连时库持有的所有描述符都会恰好关闭一次。
- 指针坐标使用输出物理像素、左上角原点;时间戳使用单调微秒时钟。
已实现:
- 协议冻结(XML、编解码、golden 向量与畸形报文测试)
- broker 路由核心(含多消费者扇出、重连与池代际管理)
- 消费端与生产端库(含延迟解绑、指针/窗口状态)
- EGL 导入与原生 fence 同步;Vulkan 多平面导入、relay/blit 回退与导出
- KDE Plasma 适配器(OpenGL/EGL 与 Vulkan 双后端,X11/Wayland 通用)
规划中(仓库内尚无实现):
- GNOME Shell 扩展 + 原生纹理导入助手
- layer-shell 通用消费者(优先 wlroots,其次 Hyprland/Niri)
- 移除 MirageWallpaper 对直接 X11 的所有权(依赖上游渲染器接入)