From 5fdc9a0e9512134d2e44a1574f596ad34b62461a Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Tue, 27 Aug 2013 16:26:22 +0200 Subject: [PATCH] wayland: add new frame redraw infrastructure. Update the frame redraw infrastructure with a new FrameState stucture holds all the necessary information used to display the next pending surface. While we are at it, delay the sync operation down to when it is actually needed. That way, we keep performing additional tasks meanwhile. --- gst-libs/gst/vaapi/gstvaapiwindow_wayland.c | 91 +++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 24 deletions(-) diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_wayland.c b/gst-libs/gst/vaapi/gstvaapiwindow_wayland.c index fb88a2b..4621ac4 100644 --- a/gst-libs/gst/vaapi/gstvaapiwindow_wayland.c +++ b/gst-libs/gst/vaapi/gstvaapiwindow_wayland.c @@ -44,14 +44,53 @@ typedef struct _GstVaapiWindowWaylandPrivate GstVaapiWindowWaylandPrivate; typedef struct _GstVaapiWindowWaylandClass GstVaapiWindowWaylandClass; +typedef struct _FrameState FrameState; + +struct _FrameState { + GstVaapiWindow *window; + struct wl_buffer *buffer; + struct wl_callback *callback; +}; + +static FrameState * +frame_state_new(GstVaapiWindow *window) +{ + FrameState *frame; + + frame = g_slice_new(FrameState); + if (!frame) + return NULL; + + frame->window = window; + frame->buffer = NULL; + frame->callback = NULL; + return frame; +} + +static void +frame_state_free(FrameState *frame) +{ + if (!frame) + return; + + if (frame->buffer) { + wl_buffer_destroy(frame->buffer); + frame->buffer = NULL; + } + + if (frame->callback) { + wl_callback_destroy(frame->callback); + frame->callback = NULL; + } + g_slice_free(FrameState, frame); +} struct _GstVaapiWindowWaylandPrivate { struct wl_shell_surface *shell_surface; struct wl_surface *surface; - struct wl_buffer *buffer; struct wl_region *opaque_region; struct wl_event_queue *event_queue; - guint redraw_pending : 1; + FrameState *frame; guint is_shown : 1; guint fullscreen_on_show : 1; }; @@ -100,14 +139,14 @@ gst_vaapi_window_wayland_sync(GstVaapiWindow *window) GstVaapiWindowWaylandPrivate * const priv = GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE(window); - if (priv->redraw_pending) { + if (priv->frame) { struct wl_display * const wl_display = GST_VAAPI_OBJECT_WL_DISPLAY(window); do { if (wl_display_dispatch_queue(wl_display, priv->event_queue) < 0) return FALSE; - } while (priv->redraw_pending); + } while (priv->frame); } return TRUE; } @@ -207,7 +246,6 @@ gst_vaapi_window_wayland_create( if (priv->fullscreen_on_show) gst_vaapi_window_wayland_set_fullscreen(window, TRUE); - priv->redraw_pending = FALSE; priv->is_shown = TRUE; return TRUE; @@ -219,6 +257,11 @@ gst_vaapi_window_wayland_destroy(GstVaapiWindow * window) GstVaapiWindowWaylandPrivate * const priv = GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE(window); + if (priv->frame) { + frame_state_free(priv->frame); + priv->frame = NULL; + } + if (priv->shell_surface) { wl_shell_surface_destroy(priv->shell_surface); priv->shell_surface = NULL; @@ -229,11 +272,6 @@ gst_vaapi_window_wayland_destroy(GstVaapiWindow * window) priv->surface = NULL; } - if (priv->buffer) { - wl_buffer_destroy(priv->buffer); - priv->buffer = NULL; - } - if (priv->event_queue) { wl_event_queue_destroy(priv->event_queue); priv->event_queue = NULL; @@ -267,12 +305,13 @@ gst_vaapi_window_wayland_resize( static void frame_redraw_callback(void *data, struct wl_callback *callback, uint32_t time) { - GstVaapiWindowWaylandPrivate * const priv = data; + FrameState * const frame = data; + GstVaapiWindowWaylandPrivate * const priv = + GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE(frame->window); - wl_buffer_destroy(priv->buffer); - priv->buffer = NULL; - wl_callback_destroy(callback); - priv->redraw_pending = FALSE; + frame_state_free(frame); + if (priv->frame == frame) + priv->frame = NULL; } static const struct wl_callback_listener frame_callback_listener = { @@ -293,7 +332,7 @@ gst_vaapi_window_wayland_render( GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(window); struct wl_display * const wl_display = GST_VAAPI_OBJECT_WL_DISPLAY(window); struct wl_buffer *buffer; - struct wl_callback *callback; + FrameState *frame; guint width, height, va_flags; VASurfaceID surface_id; VAStatus status; @@ -317,10 +356,6 @@ gst_vaapi_window_wayland_render( if (surface_id == VA_INVALID_ID) return FALSE; - /* Wait for the previous frame to complete redraw */ - if (!gst_vaapi_window_wayland_sync(window)) - return FALSE; - /* XXX: use VA/VPP for other filters */ GST_VAAPI_OBJECT_LOCK_DISPLAY(window); va_flags = from_GstVaapiSurfaceRenderFlags(flags); @@ -343,6 +378,15 @@ gst_vaapi_window_wayland_render( if (!vaapi_check_status(status, "vaGetSurfaceBufferWl()")) return FALSE; + /* Wait for the previous frame to complete redraw */ + if (!gst_vaapi_window_wayland_sync(window)) + return FALSE; + + frame = frame_state_new(window); + if (!frame) + return FALSE; + priv->frame = frame; + /* XXX: attach to the specified target rectangle */ GST_VAAPI_OBJECT_LOCK_DISPLAY(window); wl_surface_attach(priv->surface, buffer, 0, 0); @@ -354,10 +398,9 @@ gst_vaapi_window_wayland_render( priv->opaque_region = NULL; } - priv->redraw_pending = TRUE; - priv->buffer = buffer; - callback = wl_surface_frame(priv->surface); - wl_callback_add_listener(callback, &frame_callback_listener, priv); + frame->buffer = buffer; + frame->callback = wl_surface_frame(priv->surface); + wl_callback_add_listener(frame->callback, &frame_callback_listener, frame); wl_surface_commit(priv->surface); wl_display_flush(wl_display); -- 2.7.4