From 5a786d96d06f687259d538c205262aa84ce50ad9 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Tue, 25 Nov 2025 15:20:14 +0100 Subject: [PATCH] WIP Introduce WLR_GBM_EXPLICIT_UPGRADE When the `WLR_GBM_EXPLICIT_UPGRADE` flag is set to 1, the GBM allocator will attempt to "upgrade" buffers allocated with implicit modifiers to be managed with explicit modifiers. This is useful to enable the conservative modifier fallback for the Vulkan renderer on drivers/hardware that fully support implicit and explicit modifiers, including being able to report the modifier of an implicitly allocated BO. --- docs/env_vars.md | 3 +++ include/render/allocator/gbm.h | 4 ++++ render/allocator/gbm.c | 6 ++++++ types/wlr_output_swapchain_manager.c | 9 ++++++++- 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/env_vars.md b/docs/env_vars.md index 59c8f078f..b65e993cb 100644 --- a/docs/env_vars.md +++ b/docs/env_vars.md @@ -18,6 +18,9 @@ wlroots reads these environment variables and Vulkan * *WLR_EGL_NO_MODIFIERS*: set to 1 to disable format modifiers in EGL, this can be used to understand and work around driver bugs. +* *WLR_GBM_EXPLICIT_UPGRADE*: set to 1 to attempt to "upgrade" buffers + allocated with implicit modifiers to explicit modifiers. May help when a + conservative modifier is required, but may not work with all drivers. ## DRM backend diff --git a/include/render/allocator/gbm.h b/include/render/allocator/gbm.h index 7d0016eb4..72b30f36b 100644 --- a/include/render/allocator/gbm.h +++ b/include/render/allocator/gbm.h @@ -22,6 +22,10 @@ struct wlr_gbm_allocator { struct gbm_device *gbm_device; struct wl_list buffers; // wlr_gbm_buffer.link + + struct { + bool explicit_upgrade; + } WLR_PRIVATE; }; /** diff --git a/render/allocator/gbm.c b/render/allocator/gbm.c index fadfac9f8..818c96fc8 100644 --- a/render/allocator/gbm.c +++ b/render/allocator/gbm.c @@ -11,6 +11,7 @@ #include "render/allocator/gbm.h" #include "render/drm_format_set.h" +#include "util/env.h" static const struct wlr_buffer_impl buffer_impl; @@ -90,6 +91,10 @@ static struct wlr_gbm_buffer *create_buffer(struct wlr_gbm_allocator *alloc, return NULL; } + if (!has_modifier && alloc->explicit_upgrade) { + fallback_modifier = gbm_bo_get_modifier(bo); + } + struct wlr_gbm_buffer *buffer = calloc(1, sizeof(*buffer)); if (buffer == NULL) { gbm_bo_destroy(bo); @@ -174,6 +179,7 @@ struct wlr_allocator *wlr_gbm_allocator_create(int fd) { return NULL; } wlr_allocator_init(&alloc->base, &allocator_impl, WLR_BUFFER_CAP_DMABUF); + alloc->explicit_upgrade = env_parse_bool("WLR_GBM_EXPLICIT_UPGRADE"); alloc->fd = fd; wl_list_init(&alloc->buffers); diff --git a/types/wlr_output_swapchain_manager.c b/types/wlr_output_swapchain_manager.c index 9df3a6524..c073219a5 100644 --- a/types/wlr_output_swapchain_manager.c +++ b/types/wlr_output_swapchain_manager.c @@ -9,6 +9,7 @@ #include #include "render/drm_format_set.h" #include "types/wlr_output.h" +#include "util/env.h" struct wlr_output_swapchain_manager_output { struct wlr_output *output; @@ -22,6 +23,9 @@ struct wlr_output_swapchain_manager_output { // wlr_output_swapchain_manager_apply() is called. Can be either a pointer // to the newly allocated swapchain, or the old swapchain, or NULL. struct wlr_swapchain *pending_swapchain; + // Whether we will trust the allocator to upgrade implicit allocations to + // use explicit modifiers. + bool explicit_upgrade; }; void wlr_output_swapchain_manager_init(struct wlr_output_swapchain_manager *manager, @@ -55,6 +59,7 @@ static struct wlr_output_swapchain_manager_output *manager_get_or_add_output( } *manager_output = (struct wlr_output_swapchain_manager_output){ .output = output, + .explicit_upgrade = env_parse_bool("WLR_GBM_EXPLICIT_UPGRADE"), }; return manager_output; } @@ -122,7 +127,9 @@ static bool manager_output_prepare(struct wlr_output_swapchain_manager_output *m } if (!explicit_modifiers && (format.len != 1 || format.modifiers[0] != DRM_FORMAT_MOD_LINEAR)) { - if (!wlr_drm_format_has(&format, DRM_FORMAT_MOD_INVALID)) { + if (!wlr_drm_format_has(&format, DRM_FORMAT_MOD_INVALID) && + !(wlr_drm_format_set_has(display_formats, format.format, DRM_FORMAT_MOD_INVALID) && + manager_output->explicit_upgrade)) { wlr_log(WLR_DEBUG, "Implicit modifiers not supported"); wlr_drm_format_finish(&format); return false;