libs: window: wayland: mark frames as done

When the frame listener callbacks 'done', the number of pending
frames are decreased. Nonetheless, there might be occasions where
the buffer listener callbacks 'release', without calling previously
frame's 'done'. This leads to problem with
gst_vaapi_window_wayland_sync() operation.

This patch marks as done those frames which were callbacked, but if
the buffer callbacks 'release' and associated frame is not marked
as 'done' it is so, thus the number of pending frames keeps correct.

https://bugzilla.gnome.org/show_bug.cgi?id=780442

Signed-off-by: Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
This commit is contained in:
Hyunjun Ko 2017-04-21 15:30:09 +02:00 committed by Víctor Manuel Jáquez Leal
parent 3b314ba93e
commit 824974e657

View file

@ -62,6 +62,7 @@ struct _FrameState
GstVaapiSurface *surface;
GstVaapiVideoPool *surface_pool;
struct wl_callback *callback;
gboolean done;
};
static FrameState *
@ -77,6 +78,7 @@ frame_state_new (GstVaapiWindow * window)
frame->surface = NULL;
frame->surface_pool = NULL;
frame->callback = NULL;
frame->done = FALSE;
return frame;
}
@ -372,15 +374,21 @@ gst_vaapi_window_wayland_resize (GstVaapiWindow * window,
return TRUE;
}
static void
frame_done_callback (void *data, struct wl_callback *callback, uint32_t time)
static inline gboolean
frame_done (FrameState * frame)
{
FrameState *const frame = data;
GstVaapiWindowWaylandPrivate *const priv =
GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE (frame->window);
g_atomic_int_set (&frame->done, TRUE);
g_atomic_pointer_compare_and_exchange (&priv->last_frame, frame, NULL);
g_atomic_int_dec_and_test (&priv->num_frames_pending);
return g_atomic_int_dec_and_test (&priv->num_frames_pending);
}
static void
frame_done_callback (void *data, struct wl_callback *callback, uint32_t time)
{
frame_done (data);
}
static const struct wl_callback_listener frame_callback_listener = {
@ -390,8 +398,12 @@ static const struct wl_callback_listener frame_callback_listener = {
static void
frame_release_callback (void *data, struct wl_buffer *wl_buffer)
{
FrameState *const frame = data;
if (!frame->done)
frame_done (frame);
wl_buffer_destroy (wl_buffer);
frame_state_free (data);
frame_state_free (frame);
}
static const struct wl_buffer_listener frame_buffer_listener = {