mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-09 05:51:00 +03:00
drm: convert each display on the GPU that exports it
The unprivileged converter opened its render context with drmtap_open_render(NULL), letting libdrmtap auto-select. On a multi-GPU host that can land on a different GPU than the one driving the display, and importing a scanout across vendors can fail permanently on an incompatible tiling modifier. The service already knows the exporting device, so it now names its render node (drmtap_render_node, libdrmtap 0.4.15) in each DrmDisplayInfo, and the consumer opens the converter on that node. The field is serde(default) and empty means auto-select, so a service and a server from mismatched builds still interoperate and a pre-0.4.15 .so degrades to exactly the previous behaviour. The path is realpath-gated to /dev/dri before it is opened, the same gate the capture device gets, since it arrives over IPC. When the named node cannot be opened the converter returns None and the existing need_cpu fallback runs the convert on the exporting GPU service-side, which is the most correct place for it anyway. Added a wire-compat test that a pre-render_node DrmDisplayInfo payload still decodes (empty node) and a current one round-trips the node.
This commit is contained in:
@@ -295,11 +295,22 @@ async fn recv_thread(
|
||||
// Skip opening the render-node converter entirely when this display previously failed to convert
|
||||
// (multi-GPU render-node mismatch): request the CPU path so the service does the conversion on the
|
||||
// exporting GPU. Otherwise open it normally and fall back to CPU only if no render node is usable.
|
||||
// Bind the converter to the GPU that EXPORTS this display's scanout, which the service
|
||||
// named in the display list. Auto-selection can land on a different GPU on a multi-GPU
|
||||
// host, and importing a scanout across vendors can fail on an incompatible tiling
|
||||
// modifier. Empty (an older service or a device with no render node) means auto-select,
|
||||
// exactly as before. Every display of one device carries the same node, so a display
|
||||
// index that does not resolve still gets the right answer from the first entry.
|
||||
let force_cpu = drm_prefer_cpu(display);
|
||||
let render_node = displays
|
||||
.get(display.max(0) as usize)
|
||||
.or_else(|| displays.first())
|
||||
.map(|d| d.render_node.clone())
|
||||
.unwrap_or_default();
|
||||
let mut converter = if force_cpu {
|
||||
None
|
||||
} else {
|
||||
RenderConverter::open_render()
|
||||
RenderConverter::open_render(Some(render_node.as_str()))
|
||||
};
|
||||
let need_cpu = converter.is_none();
|
||||
if need_cpu {
|
||||
|
||||
Reference in New Issue
Block a user