wayland: free frame in buffer release callback

The Wayland compositor may still use the buffer when the frame done
callback is called.

This patch destroys the frame (which contains the buffer) until the
release callback is called. The draw termination callback only controls
the display queue dispatching.

Signed-off-by: Víctor Manuel Jáquez Leal <vjaquez@igalia.com>

https://bugzilla.gnome.org/show_bug.cgi?id=747492
This commit is contained in:
Michael Olbrich 2015-02-03 16:52:06 +01:00 committed by Víctor Manuel Jáquez Leal
parent 99f95690b5
commit 7548c72a7d

View file

@ -114,6 +114,7 @@ struct _GstVaapiWindowWaylandPrivate
guint is_shown:1; guint is_shown:1;
guint fullscreen_on_show:1; guint fullscreen_on_show:1;
guint use_vpp:1; guint use_vpp:1;
guint frame_pending:1;
}; };
/** /**
@ -162,14 +163,14 @@ gst_vaapi_window_wayland_sync (GstVaapiWindow * window)
GstVaapiWindowWaylandPrivate *const priv = GstVaapiWindowWaylandPrivate *const priv =
GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE (window); GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE (window);
if (priv->frame) { if (priv->frame_pending) {
struct wl_display *const wl_display = struct wl_display *const wl_display =
GST_VAAPI_OBJECT_NATIVE_DISPLAY (window); GST_VAAPI_OBJECT_NATIVE_DISPLAY (window);
do { do {
if (wl_display_dispatch_queue (wl_display, priv->event_queue) < 0) if (wl_display_dispatch_queue (wl_display, priv->event_queue) < 0)
return FALSE; return FALSE;
} while (priv->frame); } while (priv->frame_pending);
} }
return TRUE; return TRUE;
} }
@ -329,15 +330,24 @@ frame_redraw_callback (void *data, struct wl_callback *callback, uint32_t time)
GstVaapiWindowWaylandPrivate *const priv = GstVaapiWindowWaylandPrivate *const priv =
GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE (frame->window); GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE (frame->window);
frame_state_free (frame);
if (priv->frame == frame) if (priv->frame == frame)
priv->frame = NULL; priv->frame_pending = FALSE;
} }
static const struct wl_callback_listener frame_callback_listener = { static const struct wl_callback_listener frame_callback_listener = {
frame_redraw_callback frame_redraw_callback
}; };
static void
frame_release_callback (void *data, struct wl_buffer *wl_buffer)
{
frame_state_free (data);
}
static const struct wl_buffer_listener frame_buffer_listener = {
frame_release_callback
};
static GstVaapiSurface * static GstVaapiSurface *
vpp_convert (GstVaapiWindow * window, vpp_convert (GstVaapiWindow * window,
GstVaapiSurface * surface, GstVaapiSurface * surface,
@ -474,6 +484,7 @@ gst_vaapi_window_wayland_render (GstVaapiWindow * window,
if (!frame) if (!frame)
return FALSE; return FALSE;
priv->frame = frame; priv->frame = frame;
priv->frame_pending = TRUE;
if (need_vpp && priv->use_vpp) { if (need_vpp && priv->use_vpp) {
frame->surface = surface; frame->surface = surface;
@ -492,6 +503,9 @@ gst_vaapi_window_wayland_render (GstVaapiWindow * window,
} }
frame->buffer = buffer; frame->buffer = buffer;
wl_proxy_set_queue ((struct wl_proxy *) buffer, priv->event_queue);
wl_buffer_add_listener (buffer, &frame_buffer_listener, frame);
frame->callback = wl_surface_frame (priv->surface); frame->callback = wl_surface_frame (priv->surface);
wl_callback_add_listener (frame->callback, &frame_callback_listener, frame); wl_callback_add_listener (frame->callback, &frame_callback_listener, frame);