Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
url = https://gitlab.freedesktop.org/wlroots/wlr-protocols.git/
[submodule "proto/wayland-protocols"]
path = proto/wayland-protocols
url = https://gitlab.freedesktop.org/wayland/wayland-protocols.git/
url = https://gitlab.freedesktop.org/mahkoh/wayland-protocols.git/
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ set(WLR_PROTOCOL_DIR "/usr/share/wlr-protocols" CACHE STRING "wlr-protocols dire
set(PROTOCOLS
"stable/xdg-shell/xdg-shell.xml"
"stable/viewporter/viewporter.xml"
"staging/color-management/color-management-v1.xml"
"staging/ext-image-capture-color-management/ext-image-capture-color-management-v1.xml"
"staging/fractional-scale/fractional-scale-v1.xml"
"staging/ext-image-copy-capture/ext-image-copy-capture-v1.xml"
"staging/ext-image-capture-source/ext-image-capture-source-v1.xml"
Expand Down
8 changes: 8 additions & 0 deletions include/wlm/mirror/extcopy.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <wlm/wayland.h>
#include <wlm/proto/ext-image-copy-capture-v1.h>
#include <wlm/proto/ext-image-capture-source-v1.h>
#include <wlm/proto/color-management-v1.h>
#include <wlm/proto/ext-image-capture-color-management-v1.h>

typedef enum {
STATE_INIT,
Expand All @@ -22,6 +24,12 @@ typedef struct {
struct ext_image_capture_source_v1 * capture_source;
struct ext_image_copy_capture_session_v1 * capture_session;
struct ext_image_copy_capture_frame_v1 * capture_frame;
struct ext_image_capture_source_colors_v1 * capture_source_colors;

struct wp_image_description_v1 * pending_desc;
struct wp_image_description_v1 * ready_desc;
struct wp_image_description_v1 * frame_desc;
bool frame_desc_is_surface_desc;

bool has_shm_format;
bool has_drm_format;
Expand Down
7 changes: 7 additions & 0 deletions include/wlm/wayland.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,15 @@ typedef struct ctx_wl {
struct ext_image_copy_capture_manager_v1 * copy_capture_manager;
struct ext_output_image_capture_source_manager_v1 * output_capture_source_manager;
struct ext_foreign_toplevel_image_capture_source_manager_v1 * toplevel_capture_source_manager;
struct ext_image_capture_color_manager_v1 * copy_capture_color_manager;
uint32_t copy_capture_manager_id;
uint32_t output_capture_source_manager_id;
uint32_t toplevel_capture_source_manager_id;
uint32_t copy_capture_color_manager_id;

// color management
struct wp_color_manager_v1 * color_manager;
uint32_t color_manager_id;

// output list
output_list_node_t * outputs;
Expand All @@ -94,6 +100,7 @@ typedef struct ctx_wl {
struct wl_surface * surface;
struct wp_viewport * viewport;
struct wp_fractional_scale_v1 * fractional_scale;
struct wp_color_management_surface_v1 * color_management_surface;
#ifdef WITH_LIBDECOR
struct libdecor * libdecor_context;
struct libdecor_frame * libdecor_frame;
Expand Down
2 changes: 1 addition & 1 deletion proto/wayland-protocols
Submodule wayland-protocols updated from 71da8b to b288f7
96 changes: 96 additions & 0 deletions src/mirror/extcopy.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,20 @@ static void extcopy_frame_cleanup(extcopy_mirror_backend_t * backend) {
static void extcopy_session_cleanup(ctx_t * ctx, extcopy_mirror_backend_t * backend) {
extcopy_frame_cleanup(backend);

if (backend->ready_desc != NULL && backend->ready_desc != backend->frame_desc) wp_image_description_v1_destroy(backend->ready_desc);
if (backend->frame_desc != NULL) wp_image_description_v1_destroy(backend->frame_desc);
if (backend->pending_desc != NULL) wp_image_description_v1_destroy(backend->pending_desc);
if (backend->capture_session != NULL) ext_image_copy_capture_session_v1_destroy(backend->capture_session);
if (backend->capture_source_colors != NULL) ext_image_capture_source_colors_v1_destroy(backend->capture_source_colors);
if (backend->capture_source != NULL) ext_image_capture_source_v1_destroy(backend->capture_source);
if (wlm_wayland_dmabuf_get_buffer(ctx) != NULL) wlm_wayland_dmabuf_dealloc(ctx);
if (wlm_wayland_shm_get_buffer(ctx) != NULL) wlm_wayland_shm_dealloc(ctx);

backend->ready_desc = NULL;
backend->frame_desc = NULL;
backend->pending_desc = NULL;
backend->capture_session = NULL;
backend->capture_source_colors = NULL;
backend->capture_source = NULL;
}

Expand Down Expand Up @@ -277,6 +285,15 @@ static void on_capture_frame_ready(void * data, struct ext_image_copy_capture_fr

wlm_log_debug(ctx, "mirror-extcopy::on_capture_frame_ready(): frame captured\n");

if (!backend->frame_desc_is_surface_desc && ctx->wl.color_management_surface != NULL) {
if (backend->frame_desc) {
wp_color_management_surface_v1_set_image_description(ctx->wl.color_management_surface, backend->frame_desc, WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL);
} else {
wp_color_management_surface_v1_unset_image_description(ctx->wl.color_management_surface);
}
backend->frame_desc_is_surface_desc = true;
}

if (backend->use_dmabuf) {
const wlm_egl_format_t * format = wlm_egl_formats_find_drm(backend->frame_drm_format);
if (format == NULL) {
Expand Down Expand Up @@ -348,6 +365,68 @@ static const struct ext_image_copy_capture_frame_v1_listener capture_frame_liste
.failed = on_capture_frame_failed,
};

static void on_image_description_failed(void *data, struct wp_image_description_v1 *wp_image_description_v1, uint32_t cause, const char *msg) {
ctx_t * ctx = (ctx_t *)data;
extcopy_mirror_backend_t * backend = (extcopy_mirror_backend_t *)ctx->mirror.backend;

wlm_log_error("mirror-extcopy::on_image_description_failed(): failed to retrieve image description, cause = %d, msg = %s\n", cause, msg);

if (backend->ready_desc != NULL && backend->ready_desc != backend->frame_desc) {
wp_image_description_v1_destroy(backend->ready_desc);
}
backend->ready_desc = NULL;
wp_image_description_v1_destroy(backend->pending_desc);
backend->pending_desc = NULL;

(void)wp_image_description_v1;
}

static void on_image_description_ready(void *data, struct wp_image_description_v1 *wp_image_description_v1, uint32_t identity) {
ctx_t * ctx = (ctx_t *)data;
extcopy_mirror_backend_t * backend = (extcopy_mirror_backend_t *)ctx->mirror.backend;

if (backend->ready_desc != NULL && backend->ready_desc != backend->frame_desc) {
wp_image_description_v1_destroy(backend->ready_desc);
}
backend->ready_desc = backend->pending_desc;
backend->pending_desc = NULL;

(void)wp_image_description_v1;
(void)identity;
}

static const struct wp_image_description_v1_listener image_description_listener = {
.failed = on_image_description_failed,
.ready = on_image_description_ready,
};

static void update_preferred_image_description(ctx_t * ctx, extcopy_mirror_backend_t * backend) {
struct wp_image_description_reference_v1 * ref = ext_image_capture_source_colors_v1_get_preferred(backend->capture_source_colors);
struct wp_image_description_v1 * desc = wp_color_manager_v1_get_image_description(ctx->wl.color_manager, ref);
wp_image_description_reference_v1_destroy(ref);
wp_image_description_v1_add_listener(desc, &image_description_listener, (void *)ctx);

if (backend->pending_desc != NULL) {
wp_image_description_v1_destroy(backend->pending_desc);
}
backend->pending_desc = desc;
}

static void on_preferred_changed(void * data, struct ext_image_capture_source_colors_v1 * colors, uint32_t hi, uint32_t lo) {
ctx_t * ctx = (ctx_t *)data;
extcopy_mirror_backend_t * backend = (extcopy_mirror_backend_t *)ctx->mirror.backend;

update_preferred_image_description(ctx, backend);

(void)colors;
(void)hi;
(void)lo;
}

static const struct ext_image_capture_source_colors_v1_listener source_colors_listener = {
.preferred_changed = on_preferred_changed,
};

// --- backend event handlers ---

static void do_capture(ctx_t * ctx) {
Expand All @@ -356,6 +435,12 @@ static void do_capture(ctx_t * ctx) {
if (backend->state == STATE_INIT || backend->state == STATE_CANCELED) {
backend->capture_source = ext_output_image_capture_source_manager_v1_create_source(ctx->wl.output_capture_source_manager, ctx->mirror.current_target->output);

if (ctx->wl.copy_capture_color_manager != NULL && ctx->wl.color_manager != NULL) {
backend->capture_source_colors = ext_image_capture_color_manager_v1_get_capture_source_colors(ctx->wl.copy_capture_color_manager, backend->capture_source);
ext_image_capture_source_colors_v1_add_listener(backend->capture_source_colors, &source_colors_listener, (void *)ctx);
update_preferred_image_description(ctx, backend);
}

wlm_log_debug(ctx, "mirror-extcopy::do_capture(): creating capture session\n");
backend->state = STATE_WAIT_BUFFER_INFO;
backend->capture_session = ext_image_copy_capture_manager_v1_create_session(ctx->wl.copy_capture_manager, backend->capture_source, ctx->opt.show_cursor ? EXT_IMAGE_COPY_CAPTURE_MANAGER_V1_OPTIONS_PAINT_CURSORS : 0);
Expand Down Expand Up @@ -383,6 +468,17 @@ static void do_capture(ctx_t * ctx) {
return;
}

if (backend->frame_desc != backend->ready_desc) {
if (backend->frame_desc != NULL) {
wp_image_description_v1_destroy(backend->frame_desc);
}
backend->frame_desc = backend->ready_desc;
backend->frame_desc_is_surface_desc = false;
}
if (backend->frame_desc != NULL) {
ext_image_capture_color_manager_v1_set_frame_image_description(ctx->wl.copy_capture_color_manager, backend->capture_frame, backend->frame_desc);
}

ext_image_copy_capture_frame_v1_attach_buffer(backend->capture_frame, buffer);
ext_image_copy_capture_frame_v1_capture(backend->capture_frame);
backend->state = STATE_WAIT_READY;
Expand Down
57 changes: 49 additions & 8 deletions src/wayland.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include "wlm/proto/ext-image-capture-source-v1.h"
#include "wlm/proto/color-management-v1.h"
#include "wlm/proto/ext-image-capture-color-management-v1.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -296,8 +298,11 @@ static void on_registry_add(

// bind image copy capture manager object
// - for extcopy backend
if (version > 2) {
version = 2;
}
ctx->wl.copy_capture_manager = (struct ext_image_copy_capture_manager_v1 *)wl_registry_bind(
registry, id, &ext_image_copy_capture_manager_v1_interface, 1
registry, id, &ext_image_copy_capture_manager_v1_interface, version
);
ctx->wl.copy_capture_manager_id = id;
} else if (strcmp(interface, ext_output_image_capture_source_manager_v1_interface.name) == 0) {
Expand Down Expand Up @@ -424,7 +429,27 @@ static void on_registry_add(
registry, id, &wl_seat_interface, 1
);
node->seat_id = id;
}
} else if (strcmp(interface, wp_color_manager_v1_interface.name) == 0 && version >= 2) {
if (ctx->wl.color_manager != NULL) {
wlm_log_error("wayland::on_registry_add(): duplicate color_manager\n");
wlm_exit_fail(ctx);
}

ctx->wl.color_manager = (struct wp_color_manager_v1 *)wl_registry_bind(
registry, id, &wp_color_manager_v1_interface, 2
);
ctx->wl.color_manager_id = id;
} else if (strcmp(interface, ext_image_capture_color_manager_v1_interface.name) == 0) {
if (ctx->wl.copy_capture_color_manager != NULL) {
wlm_log_error("wayland::on_registry_add(): duplicate copy_capture_color_manager\n");
wlm_exit_fail(ctx);
}

ctx->wl.copy_capture_color_manager = (struct ext_image_capture_color_manager_v1 *)wl_registry_bind(
registry, id, &ext_image_capture_color_manager_v1_interface, 1
);
ctx->wl.copy_capture_color_manager_id = id;
}

(void)version;
}
Expand Down Expand Up @@ -467,8 +492,14 @@ static void on_registry_remove(
} else if (id == ctx->wl.output_capture_source_manager_id) {
wlm_log_error("wayland::on_registry_remove(): output_capture_source_manager disappeared\n");
wlm_exit_fail(ctx);
} else if (id == ctx->wl.toplevel_capture_source_manager_id) {
wlm_log_error("wayland::on_registry_remove(): toplevel_capture_source_manager disappeared\n");
} else if (id == ctx->wl.toplevel_capture_source_manager_id) {
wlm_log_error("wayland::on_registry_remove(): toplevel_capture_source_manager disappeared\n");
wlm_exit_fail(ctx);
} else if (id == ctx->wl.color_manager_id) {
wlm_log_error("wayland::on_registry_remove(): color_manager disappeared\n");
wlm_exit_fail(ctx);
} else if (id == ctx->wl.copy_capture_color_manager_id) {
wlm_log_error("wayland::on_registry_remove(): copy_capture_color_manager disappeared\n");
wlm_exit_fail(ctx);
} else {
{
Expand Down Expand Up @@ -1037,6 +1068,11 @@ void wlm_wayland_init(ctx_t * ctx) {

wp_fractional_scale_v1_add_listener(ctx->wl.fractional_scale, &fractional_scale_listener, (void *)ctx);
}

// create color management surface if supported
if (ctx->wl.color_manager != NULL) {
ctx->wl.color_management_surface = wp_color_manager_v1_get_surface(ctx->wl.color_manager, ctx->wl.surface);
}
}

// --- configure_window ---
Expand Down Expand Up @@ -1101,10 +1137,12 @@ void wlm_wayland_configure_window(struct ctx * ctx) {
// commit surface to trigger configure sequence
wl_surface_commit(ctx->wl.surface);

// wait for events
// - expecting surface configure event
// - expecting xdg toplevel configure event
wl_display_roundtrip(ctx->wl.display);
while (!ctx->wl.configured) {
// wait for events
// - expecting surface configure event
// - expecting xdg toplevel configure event
wl_display_roundtrip(ctx->wl.display);
}
#endif

// check if surface is configured
Expand Down Expand Up @@ -1231,6 +1269,8 @@ void wlm_wayland_cleanup(ctx_t *ctx) {
if (ctx->wl.copy_capture_manager != NULL) ext_image_copy_capture_manager_v1_destroy(ctx->wl.copy_capture_manager);
if (ctx->wl.output_capture_source_manager != NULL) ext_output_image_capture_source_manager_v1_destroy(ctx->wl.output_capture_source_manager);
if (ctx->wl.toplevel_capture_source_manager != NULL) ext_foreign_toplevel_image_capture_source_manager_v1_destroy(ctx->wl.toplevel_capture_source_manager);
if (ctx->wl.copy_capture_color_manager != NULL) ext_image_capture_color_manager_v1_destroy(ctx->wl.copy_capture_color_manager);
if (ctx->wl.color_manager != NULL) wp_color_manager_v1_destroy(ctx->wl.color_manager);
if (ctx->wl.dmabuf_manager != NULL) zwlr_export_dmabuf_manager_v1_destroy(ctx->wl.dmabuf_manager);
if (ctx->wl.screencopy_manager != NULL) zwlr_screencopy_manager_v1_destroy(ctx->wl.screencopy_manager);
if (ctx->wl.linux_dmabuf != NULL) zwp_linux_dmabuf_v1_destroy(ctx->wl.linux_dmabuf);
Expand All @@ -1242,6 +1282,7 @@ void wlm_wayland_cleanup(ctx_t *ctx) {
if (ctx->wl.xdg_toplevel != NULL) xdg_toplevel_destroy(ctx->wl.xdg_toplevel);
if (ctx->wl.xdg_surface != NULL) xdg_surface_destroy(ctx->wl.xdg_surface);
#endif
if (ctx->wl.color_management_surface != NULL) wp_color_management_surface_v1_destroy(ctx->wl.color_management_surface);
if (ctx->wl.fractional_scale != NULL) wp_fractional_scale_v1_destroy(ctx->wl.fractional_scale);
if (ctx->wl.viewport != NULL) wp_viewport_destroy(ctx->wl.viewport);
if (ctx->wl.surface != NULL) wl_surface_destroy(ctx->wl.surface);
Expand Down