niri 调试选项完全指南:debug 配置块与渲染调试快捷键详解
niri 调试选项完全指南debug 配置块与渲染调试快捷键详解【免费下载链接】niriA scrollable-tiling Wayland compositor.项目地址: https://gitcode.com/GitHub_Trending/ni/niri导读niri 是一个可滚动平铺的 Wayland 合成器其配置文件中隐藏着一组专门用于故障排查与实验的调试选项debug配置块以及三条渲染可视化快捷键。本文基于 docs/wiki/Configuration:-Debug-Options.md 整理逐一讲解全部 21 个调试选项与 3 个调试键绑定的用途、适用场景与配置写法并结合 niri 源码如 niri-config/src/debug.rs、src/backend/tty.rs、src/render_helpers/debug.rs说明其底层实现原理。读完本文你将能够在遇到直通扫描direct scanout、光标闪烁、DRM 设备冲突、窗口聚焦异常、VRR 抖动等疑难问题时快速定位并配置正确的调试开关。⚠️重要警告这些调试选项不受 配置破坏性变更策略 的保护。它们属于仅供调试或存在已知问题的实验性功能不适用于日常使用随时可能发生变更或失效升级 niri 时请保持谨慎。一、所有调试选项一览niri 的调试配置统一放在debug {}配置块中绝大多数是布尔开关Flag少数接受字符串参数如设备路径或渲染预览模式。以下是一个包含全部选项的参考配置可直接对照使用debug { preview-render screencast // preview-render screen-capture enable-overlay-planes disable-cursor-plane disable-direct-scanout restrict-primary-scanout-to-matching-format force-disable-connectors-on-resume render-drm-device /dev/dri/renderD129 ignore-drm-device /dev/dri/renderD128 ignore-drm-device /dev/dri/renderD130 force-pipewire-invalid-modifier dbus-interfaces-in-non-session-instances wait-for-frame-completion-before-queueing emulate-zero-presentation-time disable-resize-throttling disable-transactions keep-laptop-panel-on-when-lid-is-closed disable-monitor-names strict-new-window-focus-policy honor-xdg-activation-with-invalid-serial skip-cursor-only-updates-during-vrr deactivate-unfocused-windows disable-10bit-output }从源码结构看niri-config/src/debug.rs 中的Debug结构体完整对应了上述每一个字段其中render-drm-device与ignore-drm-device使用PathBuf类型preview-render使用PreviewRender枚举Screencast/ScreenCapture其余均为布尔标志。在 niri 配置的多文件合并机制MergeWith下这些选项也可以通过 配置 include 机制 分散写入多个配置文件后合并生效。二、渲染与直通扫描Direct Scanout相关选项preview-render让 niri 以与屏幕录制screencast或屏幕捕获screen capture完全相同的方式渲染显示器画面。也就是说它会把渲染目标从常规的RenderTarget::Output切换为Screencast或ScreenCapture从而在真实屏幕上预览录制/捕获时客户端的实际渲染效果。典型用途预览block-out-from窗口规则Window Rule的实际遮挡效果——因为某些遮挡与裁剪只在录制/捕获模式下才会体现。debug { preview-render screencast // preview-render screen-capture }源码佐证在 src/niri.rs 的渲染入口中当渲染目标为Output且配置了preview_render时会直接将其改写为对应的录制目标if ctx.target RenderTarget::Output { if let Some(preview) self.config.borrow().debug.preview_render { ctx.target match preview { PreviewRender::Screencast RenderTarget::Screencast, PreviewRender::ScreenCapture RenderTarget::ScreenCapture, }; } }enable-overlay-planes允许 niri 在**叠加平面overlay plane**上执行直通扫描。注意主平面primary plane上的直通扫描始终是开启的此选项只额外放开叠加平面。debug { enable-overlay-planes }⚠️ 在部分硬件上某些动画期间开启叠加平面直通扫描可能会导致掉帧这正是它默认关闭的原因。实现上该选项对应 src/backend/tty.rs 中的FrameFlags::ALLOW_OVERLAY_PLANE_SCANOUT标志而 DRM 合成器渲染时正是依据这些FrameFlags决定是否将窗口 buffer 直接提交到硬件平面。disable-cursor-plane禁用光标平面cursor plane此时光标会与画面的其他部分一起合成渲染而不是由硬件光标平面直接呈现。debug { disable-cursor-plane }典型用途绕过特定硬件上的驱动 bug例如某些显卡的光标平面出现撕裂、花屏或闪烁时。源码中对应移除FrameFlags::ALLOW_CURSOR_PLANE_SCANOUT见 src/backend/tty.rs强制光标走普通渲染管线。disable-direct-scanout同时禁用主平面与叠加平面的直通扫描即所有窗口内容一律先经合成器渲染再输出。debug { disable-direct-scanout }源码中会同时移除主平面扫描标志与ALLOW_OVERLAY_PLANE_SCANOUT见 src/backend/tty.rs。此选项可与enable-overlay-planes形成对照实验前者单独测试叠加平面直通后者彻底关闭所有直通扫描。restrict-primary-scanout-to-matching-format将主平面直通扫描**限制为窗口 buffer 格式与合成 swapchain 格式完全一致**的情况。debug { restrict-primary-scanout-to-matching-format }背景与注意事项此标志可以避免在合成模式 ↔ 直通扫描模式切换时发生意料之外的带宽变化项目计划在将来实现告知客户端合成 swapchain 格式的能力后将其设为默认开启就目前而言它可能会阻止某些客户端作者自述如 mpv在特定机器上直通扫描到主平面。skip-cursor-only-updates-during-vrr自 25.08 版本起可用。在**可变刷新率VRR**激活期间跳过由仅光标移动引发的屏幕重绘。debug { skip-cursor-only-updates-during-vrr }典型用途某些游戏不在内部绘制光标移动光标会引发 VRR 刷新率忽高忽低的抖动此选项可以规避这种不稳定的 VRR 波动。已知缺陷当前实现存在问题——如果没有任何内容在驱动重绘例如静止的游戏画面由于光标移动不再触发重绘画面会看起来完全冻结。源码实现在 src/backend/tty.rs 中开启该选项后只要当前输出的帧时钟处于 VRR 状态就会在帧标志中加入FrameFlags::SKIP_CURSOR_ONLY_UPDATES。三、显示器、DRM 设备与输出相关选项force-disable-connectors-on-resume自 26.04 版本起可用。在 niri 恢复运行时TTY 切换或从挂起中唤醒强制禁用所有输出这会导致所有输出执行一次 modeset/黑屏。debug { force-disable-connectors-on-resume }典型用途如果 TTY 切换后 niri 渲染出现花屏或显示器无法点亮可以尝试此标志强制让输出经历一次完整的重新初始化。从源码看该标志在会话恢复逻辑中被读取见 src/backend/tty.rs用于决定恢复时是否强制禁用连接器。render-drm-device覆盖 niri 用于所有渲染的 DRM 设备接受一个渲染节点render node路径作为参数。debug { render-drm-device /dev/dri/renderD129 }典型用途当默认选中的主 GPU 不正确时可用它强制 niri 使用另一块 GPU例如核显/独显切换场景。其字段类型为OptionPathBuf见 niri-config/src/debug.rs。ignore-drm-device自 25.11 版本起可用。列出 niri应忽略的 DRM 设备可以重复指定多次。debug { ignore-drm-device /dev/dri/renderD128 ignore-drm-device /dev/dri/renderD130 }典型用途**GPU 直通GPU passthrough**场景下不希望 niri 打开某个设备时使用。源码中对应ignored_drm_devices: VecPathBuf见 niri-config/src/debug.rs支持追加合并因此你可以在不同配置文件中分别忽略不同设备。disable-monitor-names自 0.1.10 版本起可用。禁用显示器的 make/model/serial 名称效果等同于 niri 无法从 EDID 中读取到这些信息。debug { disable-monitor-names }典型用途规避 0.1.9 与 0.1.10 版本中同时连接两台 make/model/serial 完全相同的显示器时存在的崩溃问题。遇到该崩溃时升级前可用此标志临时绕过。disable-10bit-output自下一个发布版本起可用。默认情况下niri 会优先尝试向显示器输出10-bit 颜色格式失败后再回退到 8-bit。但在某些Intel NVIDIA 混合 GPU组合上这目前可能引发问题屏幕不亮、只显示白色等。debug { disable-10bit-output }在 Smithay 修复该问题之前可以设置此标志禁用 10-bit 输出。源码佐证在 src/backend/tty.rs 创建 DRM 合成器时会根据该标志从SUPPORTED_COLOR_FORMATS_10BIT与SUPPORTED_COLOR_FORMATS两套格式列表中选取实际可用的颜色格式let color_formats if self.config.borrow().debug.disable_10bit_output { SUPPORTED_COLOR_FORMATS[..] } else { SUPPORTED_COLOR_FORMATS_10BIT[..] }四、帧呈现、合成同步与性能诊断选项wait-for-frame-completion-before-queueing在每一帧完成渲染之后、交给 DRM 之前先等待其彻底完成。debug { wait-for-frame-completion-before-queueing }典型用途诊断某些同步synchronization与性能问题——例如怀疑多缓冲队列掩盖了渲染耗时或帧提交节奏异常时可以用它放慢并暴露真实的完成时机。emulate-zero-presentation-time模拟 DRM 返回零未知presentation time的情况。debug { emulate-zero-presentation-time }背景NVIDIA 专有驱动上确实存在返回零呈现时间的情况因此此标志用于测试 niri 在那些系统上不会坏得太严重。disable-resize-throttling自 0.1.9 版本起可用。禁用发送给窗口的 resize 事件节流throttling。默认行为快速缩放如交互式拖动缩放时窗口只有在为上一次请求的尺寸完成一次 commit 之后才会收到下一个新尺寸。这一机制是resize 事务transactions正常工作的前提同时也帮助某些不擅长批量处理合成器连续 resize 事件的客户端。禁用后果niri 会尽可能快地向窗口发送 resize——可能快得惊人例如在 1000 Hz 鼠标上。debug { disable-resize-throttling }disable-transactions自 0.1.9 版本起可用。禁用事务机制resize 与 close 事务。默认行为必须同时缩放的窗口会一起缩放。例如同一列中的所有窗口必须同时调整尺寸才能保证列总高度等于屏幕高度、各窗口宽度一致。事务机制让 niri等待所有窗口完成缩放之后再把它们放在同一帧里同步显示。重要关联为了让事务正常工作不应禁用 resize 节流即不要与上一个disable-resize-throttling同时使用。debug { disable-transactions }五、屏幕录制Screencasting与 D-Bus 相关选项force-pipewire-invalid-modifier自 25.01 版本起可用。强制 PipeWire 屏幕录制使用invalid modifier即使 DRM 提供了更多 modifier 也如此。debug { force-pipewire-invalid-modifier }典型用途测试不支持 modifier 的驱动才会命中的 invalid modifier 代码路径。这有助于在开发/调试时模拟老式或受限驱动的行为。dbus-interfaces-in-non-session-instances即使 niri不是以--session方式运行也让它创建 D-Bus 接口。debug { dbus-interfaces-in-non-session-instances }典型用途测试屏幕录制相关的改动时无需重新登录即可启动一个测试实例来验证。⚠️注意当你关闭测试实例后主 niri 实例目前不会自动收回这些接口因此最终仍需重新登录一次屏幕录制功能才会恢复正常。六、窗口聚焦与 xdg-activation 相关选项strict-new-window-focus-policy自 25.01 版本起可用。禁用新窗口自动聚焦的启发式规则。启用后只有携带有效 xdg-activation token 且主动激活自身的窗口才会获得焦点。debug { strict-new-window-focus-policy }源码佐证该标志在 src/handlers/compositor.rs 的新窗口/激活处理逻辑中被读取用于决定是否跳过默认的启发式聚焦。honor-xdg-activation-with-invalid-serial自 25.05 版本起可用。背景Discord、Telegram 等被广泛使用的客户端在用户点击其托盘图标或通知时会生成全新的 xdg-activation token。大多数情况下这些新 token 的serial 是无效的——因为应用必须处于聚焦状态才能拿到有效 serial而用户点击托盘/通知通常恰恰是因为应用并未聚焦、希望让它聚焦。默认行为niri 会忽略 serial 无效的 xdg-activation token以防止窗口随意抢占焦点。这会导致上述应用点击托盘图标或通知后无法获得焦点。此调试标志让 niri接受这类无效 serial 的 token使上述应用在点击托盘图标或通知后能够获得焦点。debug { honor-xdg-activation-with-invalid-serial }配套使用可以配合 on-xdg-activate 窗口规则针对单个窗口精确控制 niri 在接受到 xdg-activation 请求时的行为。有意思的细节点击通知时通知守护进程会向应用发送一个完全有效的激活 token但这些应用Electron、Qt 等似乎直接忽略了它。未来若这些应用/工具包修复了该问题此调试标志或许就不再需要了。源码佐证该标志在 src/handlers/mod.rs 的 xdg-activation 请求处理中被读取决定是否放行无效 serial 的激活请求。deactivate-unfocused-windows自 25.08 版本起可用。背景某些客户端特别是Chromium 与 Electron 系如 Teams、Slack会错误地使用 xdg 窗口状态中的Activated而非键盘焦点来判断是否为新消息发送通知在哪里显示 IME 弹出窗口等。而 niri 出于减少不必要动画的考虑会在未聚焦的工作区和不可见的标签页窗口上保留Activated状态从而暴露这些应用中的 bug。此调试标志设置后niri 会丢弃所有未聚焦窗口的Activated状态从而绕开上述问题。debug { deactivate-unfocused-windows }源码佐证该选项通过 src/layout/mod.rs 的布局选项传入并在浮动窗口与滚动布局的聚焦更新逻辑中生效见 src/layout/floating.rs 与 src/layout/scrolling.rs。七、其他选项keep-laptop-panel-on-when-lid-is-closed自 0.1.10 版本起可用。默认行为合上笔记本盖子时niri 会关闭内置显示器。此调试标志关闭这一行为合盖后保持内置显示器开启。debug { keep-laptop-panel-on-when-lid-is-closed }八、调试键绑定Key Bindings以下并非调试选项而是键绑定用于在运行时可视化渲染与合成状态对排查问题极其直观。它们定义在binds {}配置块中binds { ModShiftCtrlT { toggle-debug-tint; } ModShiftCtrlO { debug-toggle-opaque-regions; } ModShiftCtrlD { debug-toggle-damage; } }这三个动作在 niri-config/src/binds.rs 中均有对应的Action枚举变体ToggleDebugTint、DebugToggleOpaqueRegions、DebugToggleDamage并由 src/input/mod.rs 的键位分发逻辑执行——包括切换状态、立即请求全量重绘queue_redraw_all等。这也意味着它们可以像任何普通绑定一样自由更换组合键甚至通过 IPC 触发。toggle-debug-tint将所有 surface 着色为绿色正在被直通扫描direct scanout的除外。典型用途快速验证直通扫描是否真正生效——被直通扫描的画面不会被染绿。binds { ModShiftCtrlT { toggle-debug-tint; } }源码佐证debug_tint标志保存在后端状态中见 src/backend/tty.rs渲染时若开启则通过DebugFlags::TINT通知渲染器进行绿色着色见 src/backend/tty.rs切换后还会通过queue_redraw_all()强制全量重绘。debug-toggle-opaque-regions自 0.1.6 版本起可用。将标记为不透明opaque的区域着色为蓝色其余渲染元素着色为红色。典型用途检查 Wayland surface 与内部渲染元素如何标记自身的不透明区域——这是渲染性能优化的重要手段不透明区域可以跳过混色与底层绘制。binds { ModShiftCtrlO { debug-toggle-opaque-regions; } }源码佐证实现在 src/render_helpers/debug.rs 的push_opaque_regions中对每个渲染元素的不透明区域填充半透明蓝色Color32F::from([0., 0., 0.2, 0.2])对其余半透明区域填充半透明红色Color32F::from([0.3, 0., 0., 0.3])。该功能通过 src/niri.rs 的渲染包装层注入。debug-toggle-damage将受损区域damaged regions着色为红色。典型用途直观观察每一帧的 damage 区域分布验证 niri 的局部重绘damage tracking是否按预期工作——例如滚动窗口时只重绘必要区域而非整屏刷新。binds { ModShiftCtrlD { debug-toggle-damage; } }源码佐证实现在 src/render_helpers/debug.rs 的draw_damage中它调用 damage tracker 的damage_output取出当前帧的损坏矩形并以红色Color32F::from([0.3, 0., 0., 0.3])填充后插入到渲染元素列表最底层。DRM 与 Winit 后端均在渲染时调用它见 src/backend/tty.rs 与 src/backend/winit.rs。九、总结如何系统性地使用调试选项先从症状定位方向显示器不亮/花屏 →force-disable-connectors-on-resume、disable-10bit-output光标闪烁 →disable-cursor-plane画面撕裂/性能异常 →disable-direct-scanout、enable-overlay-planes、wait-for-frame-completion-before-queueing焦点被抢 →strict-new-window-focus-policy、honor-xdg-activation-with-invalid-serial、deactivate-unfocused-windows。善用渲染可视化toggle-debug-tint验证直通扫描debug-toggle-opaque-regions检查不透明区域标记debug-toggle-damage观察损坏区域——三者组合可以快速定位绝大多数渲染问题。务必逐项隔离测试调试选项之间存在相互影响如disable-resize-throttling与disable-transactions的联动建议一次只启用一个确认效果后再叠加。牢记风险所有调试选项不受破坏性变更策略保护可能在任何版本中变更或移除在向 Nvidia.md、IPC.md 等场景排查问题时优先参考当前版本文档与 Getting-Started.md 的配置加载方式确保配置位于正确的配置文件层级。【免费下载链接】niriA scrollable-tiling Wayland compositor.项目地址: https://gitcode.com/GitHub_Trending/ni/niri创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考