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.
This commit is contained in:
Gwenole Beauchesne 2013-08-27 16:26:22 +02:00
parent 71e5fd536f
commit 5fdc9a0e95

View file

@ -44,14 +44,53 @@
typedef struct _GstVaapiWindowWaylandPrivate GstVaapiWindowWaylandPrivate; typedef struct _GstVaapiWindowWaylandPrivate GstVaapiWindowWaylandPrivate;
typedef struct _GstVaapiWindowWaylandClass GstVaapiWindowWaylandClass; 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 _GstVaapiWindowWaylandPrivate {
struct wl_shell_surface *shell_surface; struct wl_shell_surface *shell_surface;
struct wl_surface *surface; struct wl_surface *surface;
struct wl_buffer *buffer;
struct wl_region *opaque_region; struct wl_region *opaque_region;
struct wl_event_queue *event_queue; struct wl_event_queue *event_queue;
guint redraw_pending : 1; FrameState *frame;
guint is_shown : 1; guint is_shown : 1;
guint fullscreen_on_show : 1; guint fullscreen_on_show : 1;
}; };
@ -100,14 +139,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->redraw_pending) { if (priv->frame) {
struct wl_display * const wl_display = struct wl_display * const wl_display =
GST_VAAPI_OBJECT_WL_DISPLAY(window); GST_VAAPI_OBJECT_WL_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->redraw_pending); } while (priv->frame);
} }
return TRUE; return TRUE;
} }
@ -207,7 +246,6 @@ gst_vaapi_window_wayland_create(
if (priv->fullscreen_on_show) if (priv->fullscreen_on_show)
gst_vaapi_window_wayland_set_fullscreen(window, TRUE); gst_vaapi_window_wayland_set_fullscreen(window, TRUE);
priv->redraw_pending = FALSE;
priv->is_shown = TRUE; priv->is_shown = TRUE;
return TRUE; return TRUE;
@ -219,6 +257,11 @@ gst_vaapi_window_wayland_destroy(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) {
frame_state_free(priv->frame);
priv->frame = NULL;
}
if (priv->shell_surface) { if (priv->shell_surface) {
wl_shell_surface_destroy(priv->shell_surface); wl_shell_surface_destroy(priv->shell_surface);
priv->shell_surface = NULL; priv->shell_surface = NULL;
@ -229,11 +272,6 @@ gst_vaapi_window_wayland_destroy(GstVaapiWindow * window)
priv->surface = NULL; priv->surface = NULL;
} }
if (priv->buffer) {
wl_buffer_destroy(priv->buffer);
priv->buffer = NULL;
}
if (priv->event_queue) { if (priv->event_queue) {
wl_event_queue_destroy(priv->event_queue); wl_event_queue_destroy(priv->event_queue);
priv->event_queue = NULL; priv->event_queue = NULL;
@ -267,12 +305,13 @@ gst_vaapi_window_wayland_resize(
static void static void
frame_redraw_callback(void *data, struct wl_callback *callback, uint32_t time) 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); frame_state_free(frame);
priv->buffer = NULL; if (priv->frame == frame)
wl_callback_destroy(callback); priv->frame = NULL;
priv->redraw_pending = FALSE;
} }
static const struct wl_callback_listener frame_callback_listener = { 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); GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(window);
struct wl_display * const wl_display = GST_VAAPI_OBJECT_WL_DISPLAY(window); struct wl_display * const wl_display = GST_VAAPI_OBJECT_WL_DISPLAY(window);
struct wl_buffer *buffer; struct wl_buffer *buffer;
struct wl_callback *callback; FrameState *frame;
guint width, height, va_flags; guint width, height, va_flags;
VASurfaceID surface_id; VASurfaceID surface_id;
VAStatus status; VAStatus status;
@ -317,10 +356,6 @@ gst_vaapi_window_wayland_render(
if (surface_id == VA_INVALID_ID) if (surface_id == VA_INVALID_ID)
return FALSE; 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 */ /* XXX: use VA/VPP for other filters */
GST_VAAPI_OBJECT_LOCK_DISPLAY(window); GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
va_flags = from_GstVaapiSurfaceRenderFlags(flags); va_flags = from_GstVaapiSurfaceRenderFlags(flags);
@ -343,6 +378,15 @@ gst_vaapi_window_wayland_render(
if (!vaapi_check_status(status, "vaGetSurfaceBufferWl()")) if (!vaapi_check_status(status, "vaGetSurfaceBufferWl()"))
return FALSE; 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 */ /* XXX: attach to the specified target rectangle */
GST_VAAPI_OBJECT_LOCK_DISPLAY(window); GST_VAAPI_OBJECT_LOCK_DISPLAY(window);
wl_surface_attach(priv->surface, buffer, 0, 0); wl_surface_attach(priv->surface, buffer, 0, 0);
@ -354,10 +398,9 @@ gst_vaapi_window_wayland_render(
priv->opaque_region = NULL; priv->opaque_region = NULL;
} }
priv->redraw_pending = TRUE; frame->buffer = buffer;
priv->buffer = buffer; frame->callback = wl_surface_frame(priv->surface);
callback = wl_surface_frame(priv->surface); wl_callback_add_listener(frame->callback, &frame_callback_listener, frame);
wl_callback_add_listener(callback, &frame_callback_listener, priv);
wl_surface_commit(priv->surface); wl_surface_commit(priv->surface);
wl_display_flush(wl_display); wl_display_flush(wl_display);