From ed8954e8cf2d92d7f2df22aeeb9b6087f76ef89e Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Mon, 14 Oct 2024 19:30:21 -0500 Subject: [PATCH] wayland: add support for wp-color-representation-v1 This is yet another color-related protocol for wayland. It's pretty simple compared to the color-management protocol, and there's no real reason to not advertise the color representation to compositors that might find it useful. --- video/out/meson.build | 6 +- video/out/opengl/context_wayland.c | 2 + video/out/vo_wlshm.c | 1 + video/out/vulkan/context_wayland.c | 2 + video/out/wayland_common.c | 117 ++++++++++++++++++++++++++++- video/out/wayland_common.h | 7 ++ 6 files changed, 131 insertions(+), 4 deletions(-) diff --git a/video/out/meson.build b/video/out/meson.build index b45011aa92..a90dea7cf3 100644 --- a/video/out/meson.build +++ b/video/out/meson.build @@ -13,7 +13,7 @@ protocols = [[wl_protocol_dir, 'stable/presentation-time/presentation-time.xml'] wl_protocols_source = [] wl_protocols_headers = [] -foreach v: ['1.32', '1.38', '1.39', '1.41'] +foreach v: ['1.32', '1.38', '1.39', '1.41', '1.44'] features += {'wayland-protocols-' + v.replace('.', '-'): wayland['deps'][2].version().version_compare('>=' + v)} endforeach @@ -36,6 +36,10 @@ if features['wayland-protocols-1-41'] protocols += [[wl_protocol_dir, 'staging/color-management/color-management-v1.xml']] endif +if features['wayland-protocols-1-44'] + protocols += [[wl_protocol_dir, 'staging/color-representation/color-representation-v1.xml']] +endif + foreach p: protocols xml = join_paths(p) wl_protocols_source += custom_target(xml.underscorify() + '_c', diff --git a/video/out/opengl/context_wayland.c b/video/out/opengl/context_wayland.c index a44bbed7cd..0ad855dd4a 100644 --- a/video/out/opengl/context_wayland.c +++ b/video/out/opengl/context_wayland.c @@ -67,6 +67,8 @@ static void wayland_egl_swap_buffers(struct ra_ctx *ctx) struct priv *p = ctx->priv; struct vo_wayland_state *wl = ctx->vo->wl; + vo_wayland_handle_color(wl); + eglSwapBuffers(p->egl_display, p->egl_surface); if (wl->opts->wl_internal_vsync) diff --git a/video/out/vo_wlshm.c b/video/out/vo_wlshm.c index 37264989ec..c4c74f7285 100644 --- a/video/out/vo_wlshm.c +++ b/video/out/vo_wlshm.c @@ -261,6 +261,7 @@ static bool draw_frame(struct vo *vo, struct vo_frame *frame) } } if (src) { + vo_wayland_handle_color(wl); struct mp_image dst = buf->mpi; struct mp_rect src_rc; struct mp_rect dst_rc; diff --git a/video/out/vulkan/context_wayland.c b/video/out/vulkan/context_wayland.c index 7a5eba2f47..20f38ac3e2 100644 --- a/video/out/vulkan/context_wayland.c +++ b/video/out/vulkan/context_wayland.c @@ -38,6 +38,8 @@ static void wayland_vk_swap_buffers(struct ra_ctx *ctx) struct vo_wayland_state *wl = ctx->vo->wl; struct priv *p = ctx->priv; + vo_wayland_handle_color(wl); + if ((!p->use_fifo && wl->opts->wl_internal_vsync == 1) || wl->opts->wl_internal_vsync == 2) vo_wayland_wait_frame(wl); diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index e064de7bf4..ed95d594d5 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -61,6 +61,10 @@ #include "color-management-v1.h" #endif +#if HAVE_WAYLAND_PROTOCOLS_1_44 +#include "color-representation-v1.h" +#endif + #if WAYLAND_VERSION_MAJOR > 1 || WAYLAND_VERSION_MINOR >= 22 #define HAVE_WAYLAND_1_22 #endif @@ -1711,6 +1715,63 @@ static const struct wp_color_management_surface_feedback_v1_listener surface_fee }; #endif +#if HAVE_WAYLAND_PROTOCOLS_1_44 +static void supported_alpha_mode(void *data, struct wp_color_representation_manager_v1 *color_representation_manager, + uint32_t alpha_mode) +{ + struct vo_wayland_state *wl = data; + switch (alpha_mode) { + case WP_COLOR_REPRESENTATION_SURFACE_V1_ALPHA_MODE_PREMULTIPLIED_ELECTRICAL: +#if PL_API_VER >= 344 + wl->alpha_map[PL_ALPHA_NONE] = alpha_mode; +#endif + break; + case WP_COLOR_REPRESENTATION_SURFACE_V1_ALPHA_MODE_STRAIGHT: + wl->alpha_map[PL_ALPHA_INDEPENDENT] = alpha_mode; + break; + } +} + +static void supported_coefficients_and_ranges(void *data, struct wp_color_representation_manager_v1 *color_representation_manager, + uint32_t coefficients, uint32_t range) +{ + struct vo_wayland_state *wl = data; + int offset = range == WP_COLOR_REPRESENTATION_SURFACE_V1_RANGE_FULL ? 0 : PL_COLOR_SYSTEM_COUNT; + switch (coefficients) { + case WP_COLOR_REPRESENTATION_SURFACE_V1_COEFFICIENTS_BT709: + wl->coefficients_map[PL_COLOR_SYSTEM_BT_709] = WP_COLOR_REPRESENTATION_SURFACE_V1_COEFFICIENTS_BT709; + wl->range_map[PL_COLOR_SYSTEM_BT_709 + offset] = range; + break; + case WP_COLOR_REPRESENTATION_SURFACE_V1_COEFFICIENTS_BT601: + wl->coefficients_map[PL_COLOR_SYSTEM_BT_601] = WP_COLOR_REPRESENTATION_SURFACE_V1_COEFFICIENTS_BT601; + wl->range_map[PL_COLOR_SYSTEM_BT_601 + offset] = range; + break; + case WP_COLOR_REPRESENTATION_SURFACE_V1_COEFFICIENTS_SMPTE240: + wl->coefficients_map[PL_COLOR_SYSTEM_SMPTE_240M] = WP_COLOR_REPRESENTATION_SURFACE_V1_COEFFICIENTS_SMPTE240; + wl->range_map[PL_COLOR_SYSTEM_SMPTE_240M + offset] = range; + break; + case WP_COLOR_REPRESENTATION_SURFACE_V1_COEFFICIENTS_BT2020: + wl->coefficients_map[PL_COLOR_SYSTEM_BT_2020_NC] = WP_COLOR_REPRESENTATION_SURFACE_V1_COEFFICIENTS_BT2020; + wl->range_map[PL_COLOR_SYSTEM_BT_2020_NC + offset] = range; + break; + case WP_COLOR_REPRESENTATION_SURFACE_V1_COEFFICIENTS_BT2020_CL: + wl->coefficients_map[PL_COLOR_SYSTEM_BT_2020_C] = WP_COLOR_REPRESENTATION_SURFACE_V1_COEFFICIENTS_BT2020_CL; + wl->range_map[PL_COLOR_SYSTEM_BT_2020_C + offset] = range; + break; + } +} + +static void color_representation_done(void *data, struct wp_color_representation_manager_v1 *color_representation_manager) +{ +} + +static const struct wp_color_representation_manager_v1_listener color_representation_listener = { + supported_alpha_mode, + supported_coefficients_and_ranges, + color_representation_done, +}; +#endif + static const char *zxdg_decoration_mode_to_str(const uint32_t mode) { switch (mode) { @@ -2058,6 +2119,14 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id wl->shm = wl_registry_bind(reg, id, &wl_shm_interface, ver); } +#if HAVE_WAYLAND_PROTOCOLS_1_44 + if (!strcmp(interface, wp_color_representation_manager_v1_interface.name) && found++) { + ver = 1; + wl->color_representation_manager = wl_registry_bind(reg, id, &wp_color_representation_manager_v1_interface, ver); + wp_color_representation_manager_v1_add_listener(wl->color_representation_manager, &color_representation_listener, wl); + } +#endif + if (!strcmp(interface, wp_content_type_manager_v1_interface.name) && found++) { ver = 1; wl->content_type_manager = wl_registry_bind(reg, id, &wp_content_type_manager_v1_interface, ver); @@ -2694,11 +2763,9 @@ static void seat_create_text_input(struct vo_wayland_seat *seat) static void set_color_management(struct vo_wayland_state *wl) { #if HAVE_WAYLAND_PROTOCOLS_1_41 - struct mp_image_params target_params = vo_get_target_params(wl->vo); - if (!wl->color_surface || pl_color_space_equal(&target_params.color, &wl->target_params.color)) + if (!wl->color_surface) return; - wl->target_params = target_params; wp_color_management_surface_v1_unset_image_description(wl->color_surface); struct pl_color_space color = wl->target_params.color; @@ -2743,6 +2810,29 @@ static void set_color_management(struct vo_wayland_state *wl) #endif } +static void set_color_representation(struct vo_wayland_state *wl) +{ +#if HAVE_WAYLAND_PROTOCOLS_1_44 + if (wl->color_representation_surface) + wp_color_representation_surface_v1_destroy(wl->color_representation_surface); + + wl->color_representation_surface = + wp_color_representation_manager_v1_get_surface(wl->color_representation_manager, wl->callback_surface); + + struct pl_color_repr repr = wl->target_params.repr; + int alpha = wl->alpha_map[repr.alpha]; + int coefficients = wl->coefficients_map[repr.sys]; + int range = repr.levels == PL_COLOR_LEVELS_FULL ? wl->range_map[repr.sys] : + wl->range_map[repr.sys + PL_COLOR_SYSTEM_COUNT]; + + if (coefficients && range) + wp_color_representation_surface_v1_set_coefficients_and_range(wl->color_representation_surface, coefficients, range); + + if (alpha) + wp_color_representation_surface_v1_set_alpha_mode(wl->color_representation_surface, alpha); +#endif +} + static void set_content_type(struct vo_wayland_state *wl) { if (!wl->content_type_manager) @@ -3326,7 +3416,13 @@ void vo_wayland_handle_color(struct vo_wayland_state *wl) { if (!wl->vo->target_params) return; + struct mp_image_params target_params = vo_get_target_params(wl->vo); + if (pl_color_space_equal(&target_params.color, &wl->target_params.color) && + pl_color_repr_equal(&target_params.repr, &wl->target_params.repr)) + return; + wl->target_params = target_params; set_color_management(wl); + set_color_representation(wl); } @@ -3442,6 +3538,13 @@ bool vo_wayland_init(struct vo *vo) } #endif +#if HAVE_WAYLAND_PROTOCOLS_1_44 + if (!wl->color_representation_manager) { + MP_VERBOSE(wl, "Compositor doesn't support the %s protocol!\n", + wp_color_representation_surface_v1_interface.name); + } +#endif + if (wl->content_type_manager) { wl->content_type = wp_content_type_manager_v1_get_surface_content_type(wl->content_type_manager, wl->surface); } else { @@ -3664,6 +3767,14 @@ void vo_wayland_uninit(struct vo *vo) wp_color_management_surface_feedback_v1_destroy(wl->color_surface_feedback); #endif +#if HAVE_WAYLAND_PROTOCOLS_1_44 + if (wl->color_representation_manager) + wp_color_representation_manager_v1_destroy(wl->color_representation_manager); + + if (wl->color_representation_surface) + wp_color_representation_surface_v1_destroy(wl->color_representation_surface); +#endif + if (wl->content_type) wp_content_type_v1_destroy(wl->content_type); diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h index 153ac7a69e..ad92615c71 100644 --- a/video/out/wayland_common.h +++ b/video/out/wayland_common.h @@ -106,6 +106,13 @@ struct vo_wayland_state { void *icc_file; uint32_t icc_size; + /* color-representation */ + struct wp_color_representation_manager_v1 *color_representation_manager; + struct wp_color_representation_surface_v1 *color_representation_surface; + int alpha_map[PL_ALPHA_MODE_COUNT]; + int coefficients_map[PL_COLOR_SYSTEM_COUNT]; + int range_map[PL_COLOR_SYSTEM_COUNT * 2]; + /* content-type */ struct wp_content_type_manager_v1 *content_type_manager; struct wp_content_type_v1 *content_type;