mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-06-13 14:32:57 -04:00
Merge branch 'vulkan-icc-2' into 'master'
ext_image_capture_source_v1: render hidden sRGB for ICC correct See merge request wlroots/wlroots!5357
This commit is contained in:
commit
56bb41f9f3
4 changed files with 435 additions and 19 deletions
|
|
@ -13,9 +13,12 @@
|
||||||
#include <wayland-server-core.h>
|
#include <wayland-server-core.h>
|
||||||
#include <wlr/render/drm_format_set.h>
|
#include <wlr/render/drm_format_set.h>
|
||||||
|
|
||||||
|
struct wlr_scene;
|
||||||
struct wlr_scene_node;
|
struct wlr_scene_node;
|
||||||
struct wlr_allocator;
|
struct wlr_allocator;
|
||||||
struct wlr_renderer;
|
struct wlr_renderer;
|
||||||
|
struct wlr_output;
|
||||||
|
struct wlr_output_layout;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A screen capture source.
|
* 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 wlr_ext_output_image_capture_source_manager_v1 {
|
||||||
struct wl_global *global;
|
struct wl_global *global;
|
||||||
|
struct wlr_scene *scene;
|
||||||
|
struct wlr_output_layout *layout;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wl_listener display_destroy;
|
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 wlr_ext_output_image_capture_source_manager_v1 *wlr_ext_output_image_capture_source_manager_v1_create(
|
||||||
struct wl_display *display, uint32_t version);
|
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 *
|
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);
|
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_scene_node *node, struct wl_event_loop *event_loop,
|
||||||
struct wlr_allocator *allocator, struct wlr_renderer *renderer);
|
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
|
* Returns the corresponding wlr_output for a image capture source
|
||||||
* managed by wlr_ext_output_image_capture_source_manager_v1
|
* managed by wlr_ext_output_image_capture_source_manager_v1
|
||||||
|
|
|
||||||
|
|
@ -37,12 +37,41 @@ struct wlr_ext_output_image_capture_source_v1 {
|
||||||
bool software_cursors_locked;
|
bool software_cursors_locked;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct scene_output_source_addon {
|
||||||
|
struct wlr_addon addon;
|
||||||
|
struct wlr_ext_image_capture_source_v1 *source;
|
||||||
|
struct wl_listener source_destroy;
|
||||||
|
};
|
||||||
|
|
||||||
struct wlr_ext_output_image_capture_source_v1_frame_event {
|
struct wlr_ext_output_image_capture_source_v1_frame_event {
|
||||||
struct wlr_ext_image_capture_source_v1_frame_event base;
|
struct wlr_ext_image_capture_source_v1_frame_event base;
|
||||||
struct wlr_buffer *buffer;
|
struct wlr_buffer *buffer;
|
||||||
struct timespec when;
|
struct timespec when;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void scene_output_source_addon_handle_source_destroy(struct wl_listener *listener,
|
||||||
|
void *data) {
|
||||||
|
struct scene_output_source_addon *addon =
|
||||||
|
wl_container_of(listener, addon, source_destroy);
|
||||||
|
(void)data;
|
||||||
|
wl_list_remove(&addon->source_destroy.link);
|
||||||
|
wlr_addon_finish(&addon->addon);
|
||||||
|
free(addon);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scene_output_source_addon_destroy(struct wlr_addon *addon) {
|
||||||
|
struct scene_output_source_addon *scene_addon =
|
||||||
|
wl_container_of(addon, scene_addon, addon);
|
||||||
|
wl_list_remove(&scene_addon->source_destroy.link);
|
||||||
|
wlr_addon_finish(&scene_addon->addon);
|
||||||
|
free(scene_addon);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wlr_addon_interface scene_output_source_addon_impl = {
|
||||||
|
.name = "wlr_ext_output_image_capture_scene_source_v1",
|
||||||
|
.destroy = scene_output_source_addon_destroy,
|
||||||
|
};
|
||||||
|
|
||||||
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 = wl_container_of(base, source, base);
|
struct wlr_ext_output_image_capture_source_v1 *source = wl_container_of(base, source, base);
|
||||||
|
|
@ -185,30 +214,66 @@ static void output_manager_handle_create_source(struct wl_client *client,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_ext_output_image_capture_source_v1 *source;
|
struct wlr_ext_output_image_capture_source_manager_v1 *manager =
|
||||||
struct wlr_addon *addon = wlr_addon_find(&output->addons, NULL, &output_addon_impl);
|
wl_resource_get_user_data(manager_resource);
|
||||||
if (addon != NULL) {
|
struct wlr_ext_image_capture_source_v1 *capture_source = NULL;
|
||||||
source = wl_container_of(addon, source, addon);
|
|
||||||
|
if (manager->scene != NULL) {
|
||||||
|
struct scene_output_source_addon *scene_addon = NULL;
|
||||||
|
struct wlr_addon *addon = wlr_addon_find(&output->addons,
|
||||||
|
NULL, &scene_output_source_addon_impl);
|
||||||
|
if (addon != NULL) {
|
||||||
|
scene_addon = wl_container_of(addon, scene_addon, addon);
|
||||||
|
capture_source = scene_addon->source;
|
||||||
|
} else {
|
||||||
|
scene_addon = calloc(1, sizeof(*scene_addon));
|
||||||
|
if (scene_addon == NULL) {
|
||||||
|
wl_resource_post_no_memory(manager_resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
capture_source = wlr_ext_image_capture_source_v1_create_with_scene_output(
|
||||||
|
manager->scene, output, manager->layout);
|
||||||
|
if (capture_source == NULL) {
|
||||||
|
free(scene_addon);
|
||||||
|
wl_resource_post_no_memory(manager_resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
scene_addon->source = capture_source;
|
||||||
|
scene_addon->source_destroy.notify = scene_output_source_addon_handle_source_destroy;
|
||||||
|
wl_signal_add(&capture_source->events.destroy, &scene_addon->source_destroy);
|
||||||
|
wlr_addon_init(&scene_addon->addon, &output->addons, NULL,
|
||||||
|
&scene_output_source_addon_impl);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
source = calloc(1, sizeof(*source));
|
struct wlr_ext_output_image_capture_source_v1 *source;
|
||||||
if (source == NULL) {
|
struct wlr_addon *addon = wlr_addon_find(&output->addons, NULL, &output_addon_impl);
|
||||||
wl_resource_post_no_memory(manager_resource);
|
if (addon != NULL) {
|
||||||
return;
|
source = wl_container_of(addon, source, addon);
|
||||||
|
} else {
|
||||||
|
source = calloc(1, sizeof(*source));
|
||||||
|
if (source == NULL) {
|
||||||
|
wl_resource_post_no_memory(manager_resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_ext_image_capture_source_v1_init(&source->base, &output_source_impl);
|
||||||
|
wlr_addon_init(&source->addon, &output->addons, NULL, &output_addon_impl);
|
||||||
|
source->output = output;
|
||||||
|
|
||||||
|
source->output_commit.notify = source_handle_output_commit;
|
||||||
|
wl_signal_add(&output->events.commit, &source->output_commit);
|
||||||
|
|
||||||
|
source_update_buffer_constraints(source);
|
||||||
|
|
||||||
|
output_cursor_source_init(&source->cursor, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_ext_image_capture_source_v1_init(&source->base, &output_source_impl);
|
capture_source = &source->base;
|
||||||
wlr_addon_init(&source->addon, &output->addons, NULL, &output_addon_impl);
|
|
||||||
source->output = output;
|
|
||||||
|
|
||||||
source->output_commit.notify = source_handle_output_commit;
|
|
||||||
wl_signal_add(&output->events.commit, &source->output_commit);
|
|
||||||
|
|
||||||
source_update_buffer_constraints(source);
|
|
||||||
|
|
||||||
output_cursor_source_init(&source->cursor, output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wlr_ext_image_capture_source_v1_create_resource(&source->base, client, new_id)) {
|
if (!wlr_ext_image_capture_source_v1_create_resource(capture_source, client, new_id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -236,6 +301,18 @@ static void output_manager_bind(struct wl_client *client, void *data,
|
||||||
wl_resource_set_implementation(resource, &output_manager_impl, manager, NULL);
|
wl_resource_set_implementation(resource, &output_manager_impl, manager, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_manager_handle_display_destroy(struct wl_listener *listener, void *data) {
|
static void output_manager_handle_display_destroy(struct wl_listener *listener, void *data) {
|
||||||
struct wlr_ext_output_image_capture_source_manager_v1 *manager =
|
struct wlr_ext_output_image_capture_source_manager_v1 *manager =
|
||||||
wl_container_of(listener, manager, display_destroy);
|
wl_container_of(listener, manager, display_destroy);
|
||||||
|
|
|
||||||
321
types/ext_image_capture_source_v1/scene_output.c
Normal file
321
types/ext_image_capture_source_v1/scene_output.c
Normal file
|
|
@ -0,0 +1,321 @@
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pixman.h>
|
||||||
|
#include <wlr/backend/headless.h>
|
||||||
|
#include <wlr/interfaces/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_output.h>
|
||||||
|
#include <wlr/types/wlr_output_layout.h>
|
||||||
|
#include <wlr/types/wlr_scene.h>
|
||||||
|
|
||||||
|
struct scene_output_source {
|
||||||
|
struct wlr_ext_image_capture_source_v1 base;
|
||||||
|
|
||||||
|
struct wlr_scene *scene;
|
||||||
|
struct wlr_output *ref_output;
|
||||||
|
struct wlr_output_layout *layout;
|
||||||
|
|
||||||
|
struct wlr_backend *headless_backend;
|
||||||
|
struct wlr_output *headless;
|
||||||
|
struct wlr_scene_output *scene_output;
|
||||||
|
|
||||||
|
struct wl_listener headless_frame;
|
||||||
|
struct wl_listener headless_commit;
|
||||||
|
struct wl_listener scene_output_destroy;
|
||||||
|
struct wl_listener ref_output_commit;
|
||||||
|
struct wl_listener ref_output_destroy;
|
||||||
|
|
||||||
|
size_t num_started;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct scene_output_source_frame_event {
|
||||||
|
struct wlr_ext_image_capture_source_v1_frame_event base;
|
||||||
|
struct wlr_buffer *buffer;
|
||||||
|
struct timespec when;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void scene_output_source_update_constraints(struct scene_output_source *source) {
|
||||||
|
struct wlr_output *output = source->ref_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 scene_output_source_handle_ref_output_commit(struct wl_listener *listener,
|
||||||
|
void *data) {
|
||||||
|
struct scene_output_source *source = wl_container_of(listener, source, ref_output_commit);
|
||||||
|
struct wlr_output_event_commit *event = data;
|
||||||
|
|
||||||
|
if (event->state->committed & (WLR_OUTPUT_STATE_MODE |
|
||||||
|
WLR_OUTPUT_STATE_RENDER_FORMAT | WLR_OUTPUT_STATE_ENABLED)) {
|
||||||
|
scene_output_source_update_constraints(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scene_output_source_handle_scene_output_destroy(struct wl_listener *listener,
|
||||||
|
void *data) {
|
||||||
|
struct scene_output_source *source = wl_container_of(listener, source, scene_output_destroy);
|
||||||
|
(void)data;
|
||||||
|
source->scene_output = NULL;
|
||||||
|
wl_list_remove(&source->scene_output_destroy.link);
|
||||||
|
wl_list_init(&source->scene_output_destroy.link);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scene_output_source_handle_headless_frame(struct wl_listener *listener,
|
||||||
|
void *data) {
|
||||||
|
struct scene_output_source *source = wl_container_of(listener, source, headless_frame);
|
||||||
|
(void)data;
|
||||||
|
|
||||||
|
if (source->scene_output == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = source->ref_output->width;
|
||||||
|
int height = source->ref_output->height;
|
||||||
|
if (width <= 0 || height <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixman_region32_t damage;
|
||||||
|
pixman_region32_init_rect(&damage, 0, 0, width, height);
|
||||||
|
pixman_region32_copy(&source->scene_output->pending_commit_damage, &damage);
|
||||||
|
pixman_region32_fini(&damage);
|
||||||
|
|
||||||
|
struct wlr_scene_output_state_options options = {
|
||||||
|
.color_transform = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_output_state state;
|
||||||
|
wlr_output_state_init(&state);
|
||||||
|
wlr_output_state_set_enabled(&state, true);
|
||||||
|
wlr_output_state_set_custom_mode(&state, width, height, source->ref_output->refresh);
|
||||||
|
wlr_output_state_set_scale(&state, source->ref_output->scale);
|
||||||
|
wlr_output_state_set_transform(&state, source->ref_output->transform);
|
||||||
|
wlr_output_state_set_render_format(&state, source->ref_output->render_format);
|
||||||
|
if (!wlr_scene_output_build_state(source->scene_output, &state, &options)) {
|
||||||
|
wlr_output_state_finish(&state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_output_commit_state(source->headless, &state);
|
||||||
|
wlr_output_state_finish(&state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scene_output_source_handle_headless_commit(struct wl_listener *listener,
|
||||||
|
void *data) {
|
||||||
|
struct scene_output_source *source = wl_container_of(listener, source, headless_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 full_damage;
|
||||||
|
|
||||||
|
const pixman_region32_t *damage;
|
||||||
|
if (event->state->committed & WLR_OUTPUT_STATE_DAMAGE) {
|
||||||
|
damage = &event->state->damage;
|
||||||
|
} else {
|
||||||
|
pixman_region32_init_rect(&full_damage, 0, 0, buffer->width, buffer->height);
|
||||||
|
damage = &full_damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct scene_output_source_frame_event frame_event = {
|
||||||
|
.base = {
|
||||||
|
.damage = damage,
|
||||||
|
},
|
||||||
|
.buffer = buffer,
|
||||||
|
.when = event->when,
|
||||||
|
};
|
||||||
|
wl_signal_emit_mutable(&source->base.events.frame, &frame_event.base);
|
||||||
|
|
||||||
|
if (damage == &full_damage) {
|
||||||
|
pixman_region32_fini(&full_damage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scene_output_source_start(struct wlr_ext_image_capture_source_v1 *base,
|
||||||
|
bool with_cursors) {
|
||||||
|
struct scene_output_source *source = wl_container_of(base, source, base);
|
||||||
|
(void)with_cursors;
|
||||||
|
|
||||||
|
source->num_started++;
|
||||||
|
if (source->num_started > 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool created_backend = false;
|
||||||
|
if (source->headless_backend == NULL) {
|
||||||
|
source->headless_backend = wlr_headless_backend_create(source->ref_output->event_loop);
|
||||||
|
if (source->headless_backend == NULL) {
|
||||||
|
source->num_started--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
created_backend = true;
|
||||||
|
if (!wlr_backend_start(source->headless_backend)) {
|
||||||
|
wlr_backend_destroy(source->headless_backend);
|
||||||
|
source->headless_backend = NULL;
|
||||||
|
source->num_started--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
source->headless = wlr_headless_add_output(source->headless_backend,
|
||||||
|
source->ref_output->width, source->ref_output->height);
|
||||||
|
if (source->headless == NULL) {
|
||||||
|
if (created_backend) {
|
||||||
|
wlr_backend_destroy(source->headless_backend);
|
||||||
|
source->headless_backend = NULL;
|
||||||
|
}
|
||||||
|
source->num_started--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_output_init_render(source->headless,
|
||||||
|
source->ref_output->allocator, source->ref_output->renderer);
|
||||||
|
|
||||||
|
source->scene_output = wlr_scene_output_create(source->scene, source->headless);
|
||||||
|
if (source->scene_output == NULL) {
|
||||||
|
wlr_output_destroy(source->headless);
|
||||||
|
source->headless = NULL;
|
||||||
|
if (created_backend) {
|
||||||
|
wlr_backend_destroy(source->headless_backend);
|
||||||
|
source->headless_backend = NULL;
|
||||||
|
}
|
||||||
|
source->num_started--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source->layout != NULL) {
|
||||||
|
struct wlr_box box;
|
||||||
|
wlr_output_layout_get_box(source->layout, source->ref_output, &box);
|
||||||
|
wlr_scene_output_set_position(source->scene_output, box.x, box.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
source->headless_frame.notify = scene_output_source_handle_headless_frame;
|
||||||
|
wl_signal_add(&source->headless->events.frame, &source->headless_frame);
|
||||||
|
|
||||||
|
source->headless_commit.notify = scene_output_source_handle_headless_commit;
|
||||||
|
wl_signal_add(&source->headless->events.commit, &source->headless_commit);
|
||||||
|
|
||||||
|
source->scene_output_destroy.notify = scene_output_source_handle_scene_output_destroy;
|
||||||
|
wl_signal_add(&source->scene_output->events.destroy, &source->scene_output_destroy);
|
||||||
|
|
||||||
|
scene_output_source_update_constraints(source);
|
||||||
|
wl_signal_emit_mutable(&source->headless->events.frame, source->headless);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scene_output_source_stop(struct wlr_ext_image_capture_source_v1 *base) {
|
||||||
|
struct scene_output_source *source = wl_container_of(base, source, base);
|
||||||
|
assert(source->num_started > 0);
|
||||||
|
|
||||||
|
source->num_started--;
|
||||||
|
if (source->num_started > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source->headless != NULL) {
|
||||||
|
wl_list_remove(&source->headless_frame.link);
|
||||||
|
wl_list_remove(&source->headless_commit.link);
|
||||||
|
if (source->scene_output != NULL) {
|
||||||
|
wl_list_remove(&source->scene_output_destroy.link);
|
||||||
|
wlr_scene_output_destroy(source->scene_output);
|
||||||
|
source->scene_output = NULL;
|
||||||
|
}
|
||||||
|
wlr_output_destroy(source->headless);
|
||||||
|
source->headless = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source->headless_backend != NULL) {
|
||||||
|
wlr_backend_destroy(source->headless_backend);
|
||||||
|
source->headless_backend = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scene_output_source_request_frame(struct wlr_ext_image_capture_source_v1 *base,
|
||||||
|
bool schedule_frame) {
|
||||||
|
struct scene_output_source *source = wl_container_of(base, source, base);
|
||||||
|
if (schedule_frame && source->headless != NULL) {
|
||||||
|
wlr_output_schedule_frame(source->headless);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scene_output_source_copy_frame(struct wlr_ext_image_capture_source_v1 *base,
|
||||||
|
struct wlr_ext_image_copy_capture_frame_v1 *frame,
|
||||||
|
struct wlr_ext_image_capture_source_v1_frame_event *base_event) {
|
||||||
|
struct scene_output_source *source = wl_container_of(base, source, base);
|
||||||
|
struct scene_output_source_frame_event *event = wl_container_of(base_event, event, base);
|
||||||
|
|
||||||
|
if (wlr_ext_image_copy_capture_frame_v1_copy_buffer(frame,
|
||||||
|
event->buffer, source->ref_output->renderer)) {
|
||||||
|
wlr_ext_image_copy_capture_frame_v1_ready(frame,
|
||||||
|
source->ref_output->transform, &event->when);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wlr_ext_image_capture_source_v1_interface scene_output_source_impl = {
|
||||||
|
.start = scene_output_source_start,
|
||||||
|
.stop = scene_output_source_stop,
|
||||||
|
.request_frame = scene_output_source_request_frame,
|
||||||
|
.copy_frame = scene_output_source_copy_frame,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void scene_output_source_destroy(struct scene_output_source *source) {
|
||||||
|
if (source->num_started > 0) {
|
||||||
|
scene_output_source_stop(&source->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_list_remove(&source->ref_output_commit.link);
|
||||||
|
wl_list_remove(&source->ref_output_destroy.link);
|
||||||
|
|
||||||
|
wlr_ext_image_capture_source_v1_finish(&source->base);
|
||||||
|
free(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scene_output_source_handle_ref_output_destroy(struct wl_listener *listener,
|
||||||
|
void *data) {
|
||||||
|
struct scene_output_source *source = wl_container_of(listener, source, ref_output_destroy);
|
||||||
|
(void)data;
|
||||||
|
scene_output_source_destroy(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
struct scene_output_source *source = calloc(1, sizeof(*source));
|
||||||
|
if (source == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*source = (struct scene_output_source){
|
||||||
|
.scene = scene,
|
||||||
|
.ref_output = reference_output,
|
||||||
|
.layout = layout,
|
||||||
|
};
|
||||||
|
|
||||||
|
wlr_ext_image_capture_source_v1_init(&source->base, &scene_output_source_impl);
|
||||||
|
|
||||||
|
wl_list_init(&source->headless_frame.link);
|
||||||
|
wl_list_init(&source->headless_commit.link);
|
||||||
|
wl_list_init(&source->scene_output_destroy.link);
|
||||||
|
|
||||||
|
source->ref_output_commit.notify = scene_output_source_handle_ref_output_commit;
|
||||||
|
wl_signal_add(&reference_output->events.commit, &source->ref_output_commit);
|
||||||
|
|
||||||
|
source->ref_output_destroy.notify = scene_output_source_handle_ref_output_destroy;
|
||||||
|
wl_signal_add(&reference_output->events.destroy, &source->ref_output_destroy);
|
||||||
|
|
||||||
|
scene_output_source_update_constraints(source);
|
||||||
|
|
||||||
|
return &source->base;
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ wlr_files += files(
|
||||||
'ext_image_capture_source_v1/output.c',
|
'ext_image_capture_source_v1/output.c',
|
||||||
'ext_image_capture_source_v1/foreign_toplevel.c',
|
'ext_image_capture_source_v1/foreign_toplevel.c',
|
||||||
'ext_image_capture_source_v1/scene.c',
|
'ext_image_capture_source_v1/scene.c',
|
||||||
|
'ext_image_capture_source_v1/scene_output.c',
|
||||||
'output/cursor.c',
|
'output/cursor.c',
|
||||||
'output/output.c',
|
'output/output.c',
|
||||||
'output/render.c',
|
'output/render.c',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue