summaryrefslogtreecommitdiffstats
path: root/video/out
diff options
context:
space:
mode:
authorDudemanguy <random342@airmail.cc>2023-01-13 19:28:46 -0600
committerDudemanguy <random342@airmail.cc>2023-01-13 22:24:11 -0600
commit6cdce9e18e4cd199c1342db6e6d1db03828ad860 (patch)
tree3f6bd590a8d0853c154119fc0926c67560b80978 /video/out
parentf32c5586d65e85e488e24007d24ee6d75611b756 (diff)
downloadmpv-6cdce9e18e4cd199c1342db6e6d1db03828ad860.tar.bz2
mpv-6cdce9e18e4cd199c1342db6e6d1db03828ad860.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.
Diffstat (limited to 'video/out')
-rw-r--r--video/out/wayland_common.c83
-rw-r--r--video/out/wayland_common.h2
2 files changed, 65 insertions, 20 deletions
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c
index e1712389c7..9c4041f6e4 100644
--- a/video/out/wayland_common.c
+++ b/video/out/wayland_common.c
@@ -144,6 +144,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;
@@ -168,7 +174,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);
@@ -1020,15 +1030,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);
wl->refresh_interval = (int64_t)refresh_nsec / 1000;
@@ -1049,13 +1055,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 = {
@@ -1077,8 +1079,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->use_present) {
- 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;
@@ -1373,6 +1376,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)
@@ -1496,6 +1514,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)
@@ -2007,6 +2047,11 @@ bool 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",
@@ -2165,8 +2210,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 78fbc6158b..6672dab5c0 100644
--- a/video/out/wayland_common.h
+++ b/video/out/wayland_common.h
@@ -97,7 +97,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;