diff options
author | Dudemanguy <random342@airmail.cc> | 2023-01-13 19:28:46 -0600 |
---|---|---|
committer | sfan5 <sfan5@live.de> | 2023-01-24 16:40:37 +0100 |
commit | 3813cc4a14162a901ef636ae5b0914a21702f434 (patch) | |
tree | fdbc73da948447935d0bc62c3b6b4963516d608e | |
parent | 8ddc0e8888e2ab2d7e50eafb12d8ea51cf1212c2 (diff) | |
download | mpv-3813cc4a14162a901ef636ae5b0914a21702f434.tar.bz2 mpv-3813cc4a14162a901ef636ae5b0914a21702f434.tar.xz |
wayland: store presentation feedbacks in a pool
Officially, the most cursed part of the wayland code in mpv (third or
fourth try now?) This time, let's allocate a pool during init
(arbitrarily set to the maximum swapchain length mpv allows, 8; don't
even know if this actually works in wayland). Then we add/remove
feedbacks from the pool during the lifecycle of the VO, and clean it up
all at the end. Hopefully, this does the trick for good this time.
-rw-r--r-- | video/out/wayland_common.c | 83 | ||||
-rw-r--r-- | video/out/wayland_common.h | 2 |
2 files changed, 65 insertions, 20 deletions
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index 87b4a814f5..eab0b64fcd 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -139,6 +139,12 @@ const struct m_sub_options wayland_conf = { }, }; +struct vo_wayland_feedback_pool { + struct wp_presentation_feedback **fback; + struct vo_wayland_state *wl; + int len; +}; + struct vo_wayland_output { struct vo_wayland_state *wl; struct wl_output *output; @@ -163,7 +169,11 @@ static int lookupkey(int key); static int set_cursor_visibility(struct vo_wayland_state *wl, bool on); static int spawn_cursor(struct vo_wayland_state *wl); +static void add_feedback(struct vo_wayland_feedback_pool *fback_pool, + struct wp_presentation_feedback *fback); static void greatest_common_divisor(struct vo_wayland_state *wl, int a, int b); +static void remove_feedback(struct vo_wayland_feedback_pool *fback_pool, + struct wp_presentation_feedback *fback); static void remove_output(struct vo_wayland_output *out); static void request_decoration_mode(struct vo_wayland_state *wl, uint32_t mode); static void set_geometry(struct vo_wayland_state *wl); @@ -1015,15 +1025,11 @@ static void feedback_presented(void *data, struct wp_presentation_feedback *fbac uint32_t seq_hi, uint32_t seq_lo, uint32_t flags) { - struct vo_wayland_state *wl = data; + struct vo_wayland_feedback_pool *fback_pool = data; + struct vo_wayland_state *wl = fback_pool->wl; - // NULL is needed to prevent a dangling pointer since presentation_feedback - // is created in the frame_callback and not in any of the actual presentation - // events. - if (fback) { - wp_presentation_feedback_destroy(fback); - wl->feedback = NULL; - } + if (fback) + remove_feedback(fback_pool, fback); if (!wl->use_present) return; @@ -1047,13 +1053,9 @@ static void feedback_presented(void *data, struct wp_presentation_feedback *fbac static void feedback_discarded(void *data, struct wp_presentation_feedback *fback) { - struct vo_wayland_state *wl = data; - - // Same logic in feedback_presented applies here. - if (fback) { - wp_presentation_feedback_destroy(fback); - wl->feedback = NULL; - } + struct vo_wayland_feedback_pool *fback_pool = data; + if (fback) + remove_feedback(fback_pool, fback); } static const struct wp_presentation_feedback_listener feedback_listener = { @@ -1075,8 +1077,9 @@ static void frame_callback(void *data, struct wl_callback *callback, uint32_t ti wl_callback_add_listener(wl->frame_callback, &frame_listener, wl); if (wl->presentation) { - wl->feedback = wp_presentation_feedback(wl->presentation, wl->surface); - wp_presentation_feedback_add_listener(wl->feedback, &feedback_listener, wl); + struct wp_presentation_feedback *fback = wp_presentation_feedback(wl->presentation, wl->surface); + add_feedback(wl->fback_pool, fback); + wp_presentation_feedback_add_listener(fback, &feedback_listener, wl->fback_pool); } wl->frame_wait = false; @@ -1384,6 +1387,21 @@ static int create_xdg_surface(struct vo_wayland_state *wl) return 0; } +static void add_feedback(struct vo_wayland_feedback_pool *fback_pool, + struct wp_presentation_feedback *fback) +{ + for (int i = 0; i < fback_pool->len; ++i) { + if (!fback_pool->fback[i]) { + fback_pool->fback[i] = fback; + break; + } else if (i == fback_pool->len - 1) { + // Shouldn't happen in practice. + wp_presentation_feedback_destroy(fback_pool->fback[i]); + fback_pool->fback[i] = fback; + } + } +} + static void do_minimize(struct vo_wayland_state *wl) { if (!wl->xdg_toplevel) @@ -1507,6 +1525,28 @@ static void request_decoration_mode(struct vo_wayland_state *wl, uint32_t mode) zxdg_toplevel_decoration_v1_set_mode(wl->xdg_toplevel_decoration, mode); } +static void clean_feedback_pool(struct vo_wayland_feedback_pool *fback_pool) +{ + for (int i = 0; i < fback_pool->len; ++i) { + if (fback_pool->fback[i]) { + wp_presentation_feedback_destroy(fback_pool->fback[i]); + fback_pool->fback[i] = NULL; + } + } +} + +static void remove_feedback(struct vo_wayland_feedback_pool *fback_pool, + struct wp_presentation_feedback *fback) +{ + for (int i = 0; i < fback_pool->len; ++i) { + if (fback_pool->fback[i] == fback) { + wp_presentation_feedback_destroy(fback); + fback_pool->fback[i] = NULL; + break; + } + } +} + static void remove_output(struct vo_wayland_output *out) { if (!out) @@ -1981,6 +2021,11 @@ int vo_wayland_init(struct vo *vo) } if (wl->presentation) { + wl->fback_pool = talloc_zero(wl, struct vo_wayland_feedback_pool); + wl->fback_pool->wl = wl; + wl->fback_pool->len = 8; // max swapchain depth allowed + wl->fback_pool->fback = talloc_zero_array(wl->fback_pool, struct wp_presentation_feedback *, + wl->fback_pool->len); wl->present = talloc_zero(wl, struct mp_present); } else { MP_VERBOSE(wl, "Compositor doesn't support the %s protocol!\n", @@ -2133,8 +2178,8 @@ void vo_wayland_uninit(struct vo *vo) if (wl->dnd_offer) wl_data_offer_destroy(wl->dnd_offer); - if (wl->feedback) - wp_presentation_feedback_destroy(wl->feedback); + if (wl->fback_pool) + clean_feedback_pool(wl->fback_pool); if (wl->frame_callback) wl_callback_destroy(wl->frame_callback); diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h index 541b4d0d28..dd8ada1fbd 100644 --- a/video/out/wayland_common.h +++ b/video/out/wayland_common.h @@ -94,7 +94,7 @@ struct vo_wayland_state { /* presentation-time */ struct wp_presentation *presentation; - struct wp_presentation_feedback *feedback; + struct vo_wayland_feedback_pool *fback_pool; struct mp_present *present; int64_t refresh_interval; bool use_present; |