Revert previous 3 commits

As suggested by Felix Poisot, it's better to extend the
`scene_node_source` rather than turn output based source into another
scene based source.
This commit is contained in:
Furkan Sahin 2026-06-01 12:34:04 -04:00
parent 8b95c20250
commit 07ff0a8b1e
2 changed files with 25 additions and 169 deletions

View file

@ -12,12 +12,10 @@
#include <pixman.h> #include <pixman.h>
#include <wayland-server-core.h> #include <wayland-server-core.h>
#include <wlr/render/drm_format_set.h> #include <wlr/render/drm_format_set.h>
#include <wlr/backend.h>
struct wlr_scene_node; struct wlr_scene_node;
struct wlr_allocator; struct wlr_allocator;
struct wlr_renderer; struct wlr_renderer;
struct wlr_output_layout;
/** /**
* A screen capture source. * A screen capture source.
@ -81,24 +79,12 @@ struct wlr_ext_image_capture_source_v1_cursor {
*/ */
struct wlr_ext_output_image_capture_source_manager_v1 { struct wlr_ext_output_image_capture_source_manager_v1 {
struct wl_global *global; struct wl_global *global;
struct wl_display *display;
struct wlr_scene *scene;
struct wlr_output_layout *layout;
struct { struct {
struct wl_listener display_destroy; struct wl_listener display_destroy;
} WLR_PRIVATE; } WLR_PRIVATE;
struct wlr_backend *headless_backend;
}; };
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);
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);
/** /**
* Interface exposing one screen capture source per foreign toplevel. * Interface exposing one screen capture source per foreign toplevel.
*/ */

View file

@ -6,12 +6,7 @@
#include <wlr/types/wlr_ext_image_capture_source_v1.h> #include <wlr/types/wlr_ext_image_capture_source_v1.h>
#include <wlr/types/wlr_ext_image_copy_capture_v1.h> #include <wlr/types/wlr_ext_image_copy_capture_v1.h>
#include <wlr/types/wlr_output.h> #include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/util/addon.h> #include <wlr/util/addon.h>
#include <wlr/backend/headless.h>
#include <wlr/types/wlr_scene.h>
#include "types/wlr_scene.h"
#include <wayland-server-core.h>
#include "ext-image-capture-source-v1-protocol.h" #include "ext-image-capture-source-v1-protocol.h"
#define OUTPUT_IMAGE_SOURCE_MANAGER_V1_VERSION 1 #define OUTPUT_IMAGE_SOURCE_MANAGER_V1_VERSION 1
@ -40,13 +35,6 @@ struct wlr_ext_output_image_capture_source_v1 {
size_t num_started; size_t num_started;
bool software_cursors_locked; bool software_cursors_locked;
// headless output to avoid icc profile stickiness
struct wlr_ext_output_image_capture_source_manager_v1 *manager;
struct wlr_output *hidden_output;
struct wlr_scene_output *hidden_scene_output;
struct wl_listener hidden_output_frame;
struct wl_listener hidden_output_commit;
}; };
struct wlr_ext_output_image_capture_source_v1_frame_event { struct wlr_ext_output_image_capture_source_v1_frame_event {
@ -55,151 +43,30 @@ struct wlr_ext_output_image_capture_source_v1_frame_event {
struct timespec when; struct timespec when;
}; };
static void handle_hidden_commit(struct wl_listener *listener, void *data) {
struct wlr_ext_output_image_capture_source_v1 *source =
wl_container_of(listener, source, hidden_output_commit);
struct wlr_output_event_commit *event = data;
if (!(event->state->committed & WLR_OUTPUT_STATE_BUFFER))
return;
struct wlr_buffer *buffer = event->state->buffer;
pixman_region32_t damage;
pixman_region32_init_rect(&damage, 0, 0, buffer->width, buffer->height);
struct wlr_ext_output_image_capture_source_v1_frame_event frame_event = {
.base = { .damage = &damage },
.buffer = buffer,
.when = event->when,
};
wl_signal_emit_mutable(&source->base.events.frame, &frame_event);
pixman_region32_fini(&damage);
}
static void handle_hidden_frame(struct wl_listener *listener, void *data) {
struct wlr_ext_output_image_capture_source_v1 *source =
wl_container_of(listener, source, hidden_output_frame);
pixman_region32_t damage;
pixman_region32_init_rect(&damage, 0, 0,
source->hidden_output->width, source->hidden_output->height);
pixman_region32_copy(&source->hidden_scene_output->pending_commit_damage, &damage);
pixman_region32_fini(&damage);
struct wlr_scene_output_state_options opts = {
.color_transform = NULL, // sRGB
};
struct wlr_output_state state;
wlr_output_state_init(&state);
wlr_output_state_set_enabled(&state, true);
wlr_output_state_set_scale(&state, source->output->scale);
if (!wlr_scene_output_build_state(source->hidden_scene_output,
&state, &opts)) {
wlr_output_state_finish(&state);
return;
}
wlr_output_commit_state(source->hidden_output, &state);
wlr_output_state_finish(&state);
}
static struct wlr_backend *ensure_headless_backend(
struct wlr_ext_output_image_capture_source_manager_v1 *manager) {
if (manager->headless_backend)
return manager->headless_backend;
struct wl_event_loop *loop =
wl_display_get_event_loop(manager->display);
manager->headless_backend = wlr_headless_backend_create(loop);
if (manager->headless_backend)
wlr_backend_start(manager->headless_backend);
return manager->headless_backend;
}
static void source_update_buffer_constraints(struct wlr_ext_output_image_capture_source_v1 *source) {
struct wlr_output *output = source->output;
if (!wlr_output_configure_primary_swapchain(output, NULL, &output->swapchain)) {
return;
}
wlr_ext_image_capture_source_v1_set_constraints_from_swapchain(&source->base,
output->swapchain, output->renderer);
}
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) {
manager->layout = layout;
}
static void output_source_start(struct wlr_ext_image_capture_source_v1 *base, static void output_source_start(struct wlr_ext_image_capture_source_v1 *base,
bool with_cursors) { bool with_cursors) {
struct wlr_ext_output_image_capture_source_v1 *source = struct wlr_ext_output_image_capture_source_v1 *source = wl_container_of(base, source, base);
wl_container_of(base, source, base);
source->num_started++; source->num_started++;
if (source->num_started > 1) { if (source->num_started > 1) {
return; return;
} }
wlr_output_lock_attach_render(source->output, true);
// Stop the real output from sending its ICC buffer to the capture session if (with_cursors) {
wl_list_remove(&source->output_commit.link); wlr_output_lock_software_cursors(source->output, true);
struct wlr_output *real = source->output;
struct wlr_backend *headless = ensure_headless_backend(source->manager);
if (!headless) {
return;
} }
source->software_cursors_locked = with_cursors;
source->hidden_output = wlr_headless_add_output(headless,
real->width, real->height);
if (!source->hidden_output) {
return;
}
wlr_output_init_render(source->hidden_output,
real->allocator, real->renderer);
source->hidden_scene_output = wlr_scene_output_create(
source->manager->scene, source->hidden_output);
if (source->manager->layout) {
struct wlr_box box;
wlr_output_layout_get_box(source->manager->layout,
source->output, &box);
wlr_scene_output_set_position(source->hidden_scene_output,
box.x, box.y);
}
if (!source->hidden_scene_output) {
wlr_output_destroy(source->hidden_output);
source->hidden_output = NULL;
return;
}
source->hidden_output_frame.notify = handle_hidden_frame;
wl_signal_add(&source->hidden_output->events.frame,
&source->hidden_output_frame);
source->hidden_output_commit.notify = handle_hidden_commit;
wl_signal_add(&source->hidden_output->events.commit,
&source->hidden_output_commit);
source_update_buffer_constraints(source);
wl_signal_emit_mutable(&source->hidden_output->events.frame, source->hidden_output);
} }
static void output_source_stop(struct wlr_ext_image_capture_source_v1 *base) { static void output_source_stop(struct wlr_ext_image_capture_source_v1 *base) {
struct wlr_ext_output_image_capture_source_v1 *source = struct wlr_ext_output_image_capture_source_v1 *source = wl_container_of(base, source, base);
wl_container_of(base, source, base); assert(source->num_started > 0);
source->num_started--; source->num_started--;
if (source->num_started > 0) { if (source->num_started > 0) {
return; return;
} }
wlr_output_lock_attach_render(source->output, false);
// Let real output commit event flow once more if (source->software_cursors_locked) {
wl_signal_add(&source->output->events.commit, &source->output_commit); wlr_output_lock_software_cursors(source->output, false);
if (source->hidden_output) {
wl_list_remove(&source->hidden_output_frame.link);
wl_list_remove(&source->hidden_output_commit.link);
wlr_scene_output_destroy(source->hidden_scene_output);
wlr_output_destroy(source->hidden_output);
source->hidden_scene_output = NULL;
source->hidden_output = NULL;
} }
} }
@ -240,6 +107,21 @@ static const struct wlr_ext_image_capture_source_v1_interface output_source_impl
.get_pointer_cursor = output_source_get_pointer_cursor, .get_pointer_cursor = output_source_get_pointer_cursor,
}; };
static void source_update_buffer_constraints(struct wlr_ext_output_image_capture_source_v1 *source) {
struct wlr_output *output = source->output;
if (!output->enabled) {
return;
}
if (!wlr_output_configure_primary_swapchain(output, NULL, &output->swapchain)) {
return;
}
wlr_ext_image_capture_source_v1_set_constraints_from_swapchain(&source->base,
output->swapchain, output->renderer);
}
static void source_handle_output_commit(struct wl_listener *listener, static void source_handle_output_commit(struct wl_listener *listener,
void *data) { void *data) {
struct wlr_ext_output_image_capture_source_v1 *source = wl_container_of(listener, source, output_commit); struct wlr_ext_output_image_capture_source_v1 *source = wl_container_of(listener, source, output_commit);
@ -318,8 +200,6 @@ static void output_manager_handle_create_source(struct wl_client *client,
wlr_addon_init(&source->addon, &output->addons, NULL, &output_addon_impl); wlr_addon_init(&source->addon, &output->addons, NULL, &output_addon_impl);
source->output = output; source->output = output;
source->manager = wl_resource_get_user_data(manager_resource);
source->output_commit.notify = source_handle_output_commit; source->output_commit.notify = source_handle_output_commit;
wl_signal_add(&output->events.commit, &source->output_commit); wl_signal_add(&output->events.commit, &source->output_commit);
@ -373,10 +253,6 @@ struct wlr_ext_output_image_capture_source_manager_v1 *wlr_ext_output_image_capt
return NULL; return NULL;
} }
manager->display = display;
manager->headless_backend = NULL;
manager->global = wl_global_create(display, manager->global = wl_global_create(display,
&ext_output_image_capture_source_manager_v1_interface, version, manager, output_manager_bind); &ext_output_image_capture_source_manager_v1_interface, version, manager, output_manager_bind);
if (manager->global == NULL) { if (manager->global == NULL) {
@ -390,12 +266,6 @@ struct wlr_ext_output_image_capture_source_manager_v1 *wlr_ext_output_image_capt
return manager; return manager;
} }
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) {
manager->scene = scene;
}
static void output_cursor_source_request_frame(struct wlr_ext_image_capture_source_v1 *base, static void output_cursor_source_request_frame(struct wlr_ext_image_capture_source_v1 *base,
bool schedule_frame) { bool schedule_frame) {
struct output_cursor_source *cursor_source = wl_container_of(base, cursor_source, base); struct output_cursor_source *cursor_source = wl_container_of(base, cursor_source, base);