From 12316417b033465114705430105785e72dfe345d Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 31 Jul 2025 15:21:28 +0200 Subject: [PATCH] ext_image_capture_source_v1: advertise fallback {A,X}RGB8888 formats We can't expect all clients to support all fancy formats. WebRTC's reference implementation doesn't support 10-bit formats yet. More generally, clients are limited by the libraries they use: for instance, Pixman doesn't implement all OpenGL/Vulkan formats. Another MR [1] suggests advertising all render formats. This is a bit heavy-handed because: - Upgrading a 8-bit buffer to a 10-bit buffer doesn't make a lot of sense. I don't think the compositor should expose arbitrary pixel format conversions. - The protocol has no preference order. Clients generally pick the first format they receive and support. As an alternative, only advertise two fallback formats, ARGB8888 and XRGB8888. These two are already hard-required by wl_shm and all clients should be able to handle them. [1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5019 --- types/ext_image_capture_source_v1/base.c | 25 +++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/types/ext_image_capture_source_v1/base.c b/types/ext_image_capture_source_v1/base.c index 7b34030c8..eccbb2884 100644 --- a/types/ext_image_capture_source_v1/base.c +++ b/types/ext_image_capture_source_v1/base.c @@ -10,6 +10,7 @@ #include #include #include "ext-image-capture-source-v1-protocol.h" +#include "render/wlr_renderer.h" static void source_handle_destroy(struct wl_client *client, struct wl_resource *source_resource) { @@ -96,6 +97,12 @@ static uint32_t get_swapchain_shm_format(struct wlr_swapchain *swapchain, return format; } +static void add_drm_format(struct wlr_drm_format_set *set, const struct wlr_drm_format *fmt) { + for (size_t i = 0; i < fmt->len; i++) { + wlr_drm_format_set_add(set, fmt->format, fmt->modifiers[i]); + } +} + bool wlr_ext_image_capture_source_v1_set_constraints_from_swapchain(struct wlr_ext_image_capture_source_v1 *source, struct wlr_swapchain *swapchain, struct wlr_renderer *renderer) { source->width = swapchain->width; @@ -130,9 +137,21 @@ bool wlr_ext_image_capture_source_v1_set_constraints_from_swapchain(struct wlr_e wlr_drm_format_set_finish(&source->dmabuf_formats); source->dmabuf_formats = (struct wlr_drm_format_set){0}; - for (size_t i = 0; i < swapchain->format.len; i++) { - wlr_drm_format_set_add(&source->dmabuf_formats, - swapchain->format.format, swapchain->format.modifiers[i]); + add_drm_format(&source->dmabuf_formats, &swapchain->format); + + const struct wlr_drm_format_set *render_formats = + wlr_renderer_get_render_formats(renderer); + assert(render_formats != NULL); + + // Not all clients support fancy formats. Always ensure we provide + // support for ARGB8888 and XRGB8888 for simple clients. + uint32_t fallback_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 }; + for (size_t i = 0; i < sizeof(fallback_formats) / sizeof(fallback_formats[0]); i++) { + const struct wlr_drm_format *fmt = + wlr_drm_format_set_get(render_formats, fallback_formats[i]); + if (fmt != NULL && swapchain->format.format != fmt->format) { + add_drm_format(&source->dmabuf_formats, fmt); + } } }