|
32 | 32 | #include "osdep/poll_wrapper.h" |
33 | 33 | #include "osdep/timer.h" |
34 | 34 | #include "present_sync.h" |
| 35 | +#include "video/out/gpu/video.h" |
35 | 36 | #include "wayland_common.h" |
36 | 37 | #include "win_state.h" |
37 | 38 |
|
@@ -252,6 +253,7 @@ static int spawn_cursor(struct vo_wayland_state *wl); |
252 | 253 | static void add_feedback(struct vo_wayland_feedback_pool *fback_pool, |
253 | 254 | struct wp_presentation_feedback *fback); |
254 | 255 | static void apply_keepaspect(struct vo_wayland_state *wl, int *width, int *height); |
| 256 | +static void get_compositor_icc_file(struct vo_wayland_state *wl); |
255 | 257 | static void get_shape_device(struct vo_wayland_state *wl, struct vo_wayland_seat *s); |
256 | 258 | static void guess_focus(struct vo_wayland_state *wl); |
257 | 259 | static void handle_key_input(struct vo_wayland_seat *s, uint32_t key, uint32_t state, bool no_emit); |
@@ -1403,7 +1405,7 @@ static void supported_feature(void *data, struct wp_color_manager_v1 *color_mana |
1403 | 1405 | switch (feature) { |
1404 | 1406 | case WP_COLOR_MANAGER_V1_FEATURE_ICC_V2_V4: |
1405 | 1407 | MP_VERBOSE(wl, "Compositor supports ICC creator requests.\n"); |
1406 | | - wl->supports_icc = true; // TODO: actually implement |
| 1408 | + wl->supports_icc = true; |
1407 | 1409 | break; |
1408 | 1410 | case WP_COLOR_MANAGER_V1_FEATURE_PARAMETRIC: |
1409 | 1411 | MP_VERBOSE(wl, "Compositor supports parametric image description creator.\n"); |
@@ -1530,6 +1532,106 @@ static const struct wp_image_description_v1_listener image_description_listener |
1530 | 1532 | image_description_failed, |
1531 | 1533 | image_description_ready, |
1532 | 1534 | }; |
| 1535 | + |
| 1536 | +static void info_done(void *data, struct wp_image_description_info_v1 *image_description_info) |
| 1537 | +{ |
| 1538 | + struct vo_wayland_state *wl = data; |
| 1539 | + wp_image_description_info_v1_destroy(image_description_info); |
| 1540 | + if (!wl->icc_file) |
| 1541 | + MP_VERBOSE(wl, "No ICC profile retrieved from the compositor.\n"); |
| 1542 | +} |
| 1543 | + |
| 1544 | +static void info_icc_file(void *data, struct wp_image_description_info_v1 *image_description_info, |
| 1545 | + int32_t icc, uint32_t icc_size) |
| 1546 | +{ |
| 1547 | + struct vo_wayland_state *wl = data; |
| 1548 | + if (wl->icc_size) { |
| 1549 | + munmap(wl->icc_file, wl->icc_size); |
| 1550 | + wl->icc_file = NULL; |
| 1551 | + wl->icc_size = 0; |
| 1552 | + } |
| 1553 | + |
| 1554 | + void *icc_file = mmap(NULL, icc_size, PROT_READ, MAP_PRIVATE, icc, 0); |
| 1555 | + close(icc); |
| 1556 | + |
| 1557 | + if (icc_file != MAP_FAILED) { |
| 1558 | + wl->icc_file = icc_file; |
| 1559 | + wl->icc_size = icc_size; |
| 1560 | + } |
| 1561 | + wl->pending_vo_events |= VO_EVENT_ICC_PROFILE_CHANGED; |
| 1562 | +} |
| 1563 | + |
| 1564 | +static void info_primaries(void *data, struct wp_image_description_info_v1 *image_description_info, |
| 1565 | + int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, int32_t b_x, int32_t b_y, |
| 1566 | + int32_t w_x, int32_t w_y) |
| 1567 | +{ |
| 1568 | +} |
| 1569 | + |
| 1570 | +static void info_primaries_named(void *data, struct wp_image_description_info_v1 *image_description_info, |
| 1571 | + uint32_t primaries) |
| 1572 | +{ |
| 1573 | +} |
| 1574 | + |
| 1575 | +static void info_tf_power(void *data, struct wp_image_description_info_v1 *image_description_info, |
| 1576 | + uint32_t eexp) |
| 1577 | +{ |
| 1578 | +} |
| 1579 | + |
| 1580 | +static void info_tf_named(void *data, struct wp_image_description_info_v1 *image_description_info, |
| 1581 | + uint32_t tf) |
| 1582 | +{ |
| 1583 | +} |
| 1584 | + |
| 1585 | +static void info_luminances(void *data, struct wp_image_description_info_v1 *image_description_info, |
| 1586 | + uint32_t min_lum, uint32_t max_lum, uint32_t reference_lum) |
| 1587 | +{ |
| 1588 | +} |
| 1589 | + |
| 1590 | +static void info_target_primaries(void *data, struct wp_image_description_info_v1 *image_description_info, |
| 1591 | + int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, int32_t b_x, int32_t b_y, |
| 1592 | + int32_t w_x, int32_t w_y) |
| 1593 | +{ |
| 1594 | +} |
| 1595 | + |
| 1596 | +static void info_target_luminance(void *data, struct wp_image_description_info_v1 *image_description_info, |
| 1597 | + uint32_t min_lum, uint32_t max_lum) |
| 1598 | +{ |
| 1599 | +} |
| 1600 | + |
| 1601 | +static void info_target_max_cll(void *data, struct wp_image_description_info_v1 *image_description_info, |
| 1602 | + uint32_t max_cll) |
| 1603 | +{ |
| 1604 | +} |
| 1605 | + |
| 1606 | +static void info_target_max_fall(void *data, struct wp_image_description_info_v1 *image_description_info, |
| 1607 | + uint32_t max_fall) |
| 1608 | +{ |
| 1609 | +} |
| 1610 | + |
| 1611 | +static const struct wp_image_description_info_v1_listener image_description_info_listener = { |
| 1612 | + info_done, |
| 1613 | + info_icc_file, |
| 1614 | + info_primaries, |
| 1615 | + info_primaries_named, |
| 1616 | + info_tf_power, |
| 1617 | + info_tf_named, |
| 1618 | + info_luminances, |
| 1619 | + info_target_primaries, |
| 1620 | + info_target_luminance, |
| 1621 | + info_target_max_cll, |
| 1622 | + info_target_max_fall, |
| 1623 | +}; |
| 1624 | + |
| 1625 | +static void preferred_changed(void *data, struct wp_color_management_surface_feedback_v1 *color_surface_feedback, |
| 1626 | + uint32_t identity) |
| 1627 | +{ |
| 1628 | + struct vo_wayland_state *wl = data; |
| 1629 | + get_compositor_icc_file(wl); |
| 1630 | +} |
| 1631 | + |
| 1632 | +static const struct wp_color_management_surface_feedback_v1_listener surface_feedback_listener = { |
| 1633 | + preferred_changed, |
| 1634 | +}; |
1533 | 1635 | #endif |
1534 | 1636 |
|
1535 | 1637 | static const char *zxdg_decoration_mode_to_str(const uint32_t mode) |
@@ -2219,6 +2321,18 @@ static int get_mods(struct vo_wayland_seat *s) |
2219 | 2321 | return modifiers; |
2220 | 2322 | } |
2221 | 2323 |
|
| 2324 | +static void get_compositor_icc_file(struct vo_wayland_state *wl) |
| 2325 | +{ |
| 2326 | +#if HAVE_WAYLAND_PROTOCOLS_1_41 |
| 2327 | + struct wp_image_description_v1 *image_description = |
| 2328 | + wp_color_management_surface_feedback_v1_get_preferred(wl->color_surface_feedback); |
| 2329 | + struct wp_image_description_info_v1 *description_info = |
| 2330 | + wp_image_description_v1_get_information(image_description); |
| 2331 | + wp_image_description_info_v1_add_listener(description_info, &image_description_info_listener, wl); |
| 2332 | + wp_image_description_v1_destroy(image_description); |
| 2333 | +#endif |
| 2334 | +} |
| 2335 | + |
2222 | 2336 | static void get_shape_device(struct vo_wayland_state *wl, struct vo_wayland_seat *s) |
2223 | 2337 | { |
2224 | 2338 | #if HAVE_WAYLAND_PROTOCOLS_1_32 |
@@ -2991,6 +3105,15 @@ int vo_wayland_control(struct vo *vo, int *events, int request, void *arg) |
2991 | 3105 | *(char ***)arg = get_displays_spanned(wl); |
2992 | 3106 | return VO_TRUE; |
2993 | 3107 | } |
| 3108 | + case VOCTRL_GET_ICC_PROFILE: { |
| 3109 | + if (!wl->supports_icc) |
| 3110 | + MP_WARN(wl, "Compositor does not support ICC profiles!\n"); |
| 3111 | + if (!wl->icc_file) |
| 3112 | + return VO_FALSE; |
| 3113 | + MP_VERBOSE(wl, "Retrieving ICC profile from compositor.\n"); |
| 3114 | + *(bstr *)arg = bstrdup(NULL, (bstr){wl->icc_file, wl->icc_size}); |
| 3115 | + return VO_TRUE; |
| 3116 | + } |
2994 | 3117 | case VOCTRL_GET_UNFS_WINDOW_SIZE: { |
2995 | 3118 | int *s = arg; |
2996 | 3119 | if (wl->opts->window_maximized || wl->tiled) { |
@@ -3292,14 +3415,29 @@ bool vo_wayland_init(struct vo *vo) |
3292 | 3415 | wl_display_roundtrip(wl->display); |
3293 | 3416 |
|
3294 | 3417 | #if HAVE_WAYLAND_PROTOCOLS_1_41 |
3295 | | - // Only bind to vo_dmabuf_wayland for now to avoid conflicting with graphics drivers |
3296 | | - if (wl->color_manager && wl->supports_parametric && !strcmp(wl->vo->driver->name, "dmabuf-wayland")) { |
| 3418 | + // Only bind color surface to vo_dmabuf_wayland for now to avoid conflicting with graphics drivers |
| 3419 | + if (wl->color_manager && wl->supports_parametric && !strcmp(wl->vo->driver->name, "dmabuf-wayland")) |
3297 | 3420 | wl->color_surface = wp_color_manager_v1_get_surface(wl->color_manager, wl->callback_surface); |
3298 | | - } else { |
3299 | | - MP_VERBOSE(wl, "Compositor does not support parametric image descriptions!\n"); |
| 3421 | + |
| 3422 | + if (wl->color_manager && wl->supports_icc) { |
| 3423 | + wl->color_surface_feedback = wp_color_manager_v1_get_surface_feedback(wl->color_manager, wl->callback_surface); |
| 3424 | + wp_color_management_surface_feedback_v1_add_listener(wl->color_surface_feedback, &surface_feedback_listener, wl); |
3300 | 3425 | } |
3301 | 3426 | #endif |
3302 | 3427 |
|
| 3428 | + if (!wl->supports_parametric) |
| 3429 | + MP_VERBOSE(wl, "Compositor does not support parametric image descriptions!\n"); |
| 3430 | + |
| 3431 | + struct gl_video_opts *gl_opts = mp_get_config_group(NULL, vo->global, &gl_video_conf); |
| 3432 | + if (wl->supports_icc) { |
| 3433 | + // dumb workaround for avoiding -Wunused-function |
| 3434 | + get_compositor_icc_file(wl); |
| 3435 | + } else { |
| 3436 | + int msg_level = gl_opts->icc_opts->profile_auto ? MSGL_WARN : MSGL_V; |
| 3437 | + mp_msg(wl->log, msg_level, "Compositor does not support ICC profiles!\n"); |
| 3438 | + } |
| 3439 | + talloc_free(gl_opts); |
| 3440 | + |
3303 | 3441 | return true; |
3304 | 3442 |
|
3305 | 3443 | err: |
@@ -3399,6 +3537,9 @@ void vo_wayland_uninit(struct vo *vo) |
3399 | 3537 |
|
3400 | 3538 | if (wl->color_surface) |
3401 | 3539 | wp_color_management_surface_v1_destroy(wl->color_surface); |
| 3540 | + |
| 3541 | + if (wl->color_surface_feedback) |
| 3542 | + wp_color_management_surface_feedback_v1_destroy(wl->color_surface_feedback); |
3402 | 3543 | #endif |
3403 | 3544 |
|
3404 | 3545 | if (wl->content_type) |
|
0 commit comments