From 0108506c770753604d6b77d24d1aa7f68feb7a23 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Thu, 7 Nov 2024 16:28:49 +0100 Subject: [PATCH] backend/drm: Allow proceeding with render-less mgpu If an mgpu device does not have a renderer, continue without one rather than ignoring it entirely. It is not guaranteed that we will be able to scan out to it in any particular configuration, but that is true for any output regardless, and having the output visible is not harmful even if it cannot light up. To proceed safely, we strip implicit modifier support from all planes, while avoiding duplication of the same logic for mdgpu_formats. This helps GUD and DisplayLink scenarios. --- backend/drm/backend.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/backend/drm/backend.c b/backend/drm/backend.c index fd1701438..ba0e8651c 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -13,6 +13,7 @@ #include #include "backend/drm/drm.h" #include "backend/drm/fb.h" +#include "render/drm_format_set.h" struct wlr_drm_backend *get_drm_backend_from_backend( struct wlr_backend *wlr_backend) { @@ -172,10 +173,25 @@ static void handle_parent_destroy(struct wl_listener *listener, void *data) { backend_destroy(&drm->backend); } +static void sanitize_mgpu_modifiers(struct wlr_drm_format_set *set) { + for (size_t idx = 0; idx < set->len; idx++) { + // Implicit modifiers are not well-defined across devices, so strip + // them from all formats in multi-gpu scenarios. + struct wlr_drm_format *fmt = &set->formats[idx]; + wlr_drm_format_set_remove(set, fmt->format, DRM_FORMAT_MOD_INVALID); + } +} + static bool init_mgpu_renderer(struct wlr_drm_backend *drm) { if (!init_drm_renderer(drm, &drm->mgpu_renderer)) { - wlr_log(WLR_ERROR, "Failed to initialize renderer"); - return false; + wlr_log(WLR_INFO, "Failed to initialize mgpu blit renderer" + ", falling back to scanning out from primary GPU"); + + for (uint32_t plane_idx = 0; plane_idx < drm->num_planes; plane_idx++) { + struct wlr_drm_plane *plane = &drm->planes[plane_idx]; + sanitize_mgpu_modifiers(&plane->formats); + } + return true; } // We'll perform a multi-GPU copy for all submitted buffers, we need @@ -188,18 +204,8 @@ static bool init_mgpu_renderer(struct wlr_drm_backend *drm) { return false; } - // Forbid implicit modifiers, because their meaning changes from one - // GPU to another. - for (size_t i = 0; i < texture_formats->len; i++) { - const struct wlr_drm_format *fmt = &texture_formats->formats[i]; - for (size_t j = 0; j < fmt->len; j++) { - uint64_t mod = fmt->modifiers[j]; - if (mod == DRM_FORMAT_MOD_INVALID) { - continue; - } - wlr_drm_format_set_add(&drm->mgpu_formats, fmt->format, mod); - } - } + wlr_drm_format_set_copy(&drm->mgpu_formats, texture_formats); + sanitize_mgpu_modifiers(&drm->mgpu_formats); drm->backend.features.timeline = drm->backend.features.timeline && drm->mgpu_renderer.wlr_rend->features.timeline; return true;