ext_image_capture_source_v1: add scene-per-output capture source

When a compositor uses color transforms (ICC profiles) the output's
postrender buffer is in the display's color space, not sRGB. A
screenshot client receives this buffer and saves it as an untagged PNG,
which appears oversaturated in non-colormanaged viewers.

To fix this without altering the semantics of the raw output source
(which must deliver the exact hardware scanned buffer, including
overlays and direct scanout), add an optional, compositor driven
scene-per-output capture source. This source re-renders the entire scene
graph for a given output with an identity color transform (sRGB), using
a hidden headless output to avoid flicker.

The new function
`wlr_ext_image_capture_source_v1_create_with_scene_output()` takes a
wlr_scene, a reference wlr_output (for dimensions, scale,
renderer/allocator), and an optional wlr_output_layout (for correct
positioning). The source is created on demand in the existing output
capture manager when the compositor has called
`wlr_ext_output_image_capture_source_manager_v1_set_scene()` and
`wlr_ext_output_image_capture_source_manager_v1_set_layout()`.

If the compositor never provides a scene, the manager continues to
create the original raw output source, preserving backward compatibility
and hardware plane capture for compositors that need it.
This commit is contained in:
Furkan Sahin 2026-06-01 12:15:27 -04:00
parent 07ff0a8b1e
commit 53b399d054
4 changed files with 435 additions and 19 deletions

View file

@ -13,9 +13,12 @@
#include <wayland-server-core.h>
#include <wlr/render/drm_format_set.h>
struct wlr_scene;
struct wlr_scene_node;
struct wlr_allocator;
struct wlr_renderer;
struct wlr_output;
struct wlr_output_layout;
/**
* A screen capture source.
@ -79,6 +82,8 @@ struct wlr_ext_image_capture_source_v1_cursor {
*/
struct wlr_ext_output_image_capture_source_manager_v1 {
struct wl_global *global;
struct wlr_scene *scene;
struct wlr_output_layout *layout;
struct {
struct wl_listener display_destroy;
@ -122,6 +127,14 @@ struct wlr_ext_image_capture_source_v1 *wlr_ext_image_capture_source_v1_from_res
struct wlr_ext_output_image_capture_source_manager_v1 *wlr_ext_output_image_capture_source_manager_v1_create(
struct wl_display *display, uint32_t version);
void wlr_ext_output_image_capture_source_manager_v1_set_scene(
struct wlr_ext_output_image_capture_source_manager_v1 *manager,
struct wlr_scene *scene);
void wlr_ext_output_image_capture_source_manager_v1_set_layout(
struct wlr_ext_output_image_capture_source_manager_v1 *manager,
struct wlr_output_layout *layout);
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1 *
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_create(struct wl_display *display, uint32_t version);
@ -133,6 +146,10 @@ struct wlr_ext_image_capture_source_v1 *wlr_ext_image_capture_source_v1_create_w
struct wlr_scene_node *node, struct wl_event_loop *event_loop,
struct wlr_allocator *allocator, struct wlr_renderer *renderer);
struct wlr_ext_image_capture_source_v1 *wlr_ext_image_capture_source_v1_create_with_scene_output(
struct wlr_scene *scene, struct wlr_output *reference_output,
struct wlr_output_layout *layout);
/**
* Returns the corresponding wlr_output for a image capture source
* managed by wlr_ext_output_image_capture_source_manager_v1