Commit 990a5ded authored by Hyunjun Ko's avatar Hyunjun Ko Committed by Víctor Manuel Jáquez Leal

libs: display,window: wayland: foreign wl_display/wl_surface support

wl_display can be set from application.

It is not fatal when wl_display doesn't support shell/output interface,
since shell_surface and opaque_region are not necessary for external
wayland surfaces.

Also, use wl_subcompositor and wl_subsurface.
See Appendix A. Wayland Protocol Specification as the following.

"""
The aim of sub-surfaces is to offload some of the compositing work
within a window from clients to the compositor. A prime example is
a video player with decorations and video in separate wl_surface
objects.

This should allow the compositor to pass YUV video buffer processing to
dedicated overlay hardware when possible.
"""

Added new method gst_vaapi_window_wayland_new_with_surface()
Original-Patch-By: Víctor Manuel Jáquez Leal's avatarVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
                   Zhao Halley <halley.zhao@intel.com>
                   changzhix.wei@intel.com

https://bugzilla.gnome.org/show_bug.cgi?id=705821
parent ee21fd90
......@@ -115,6 +115,9 @@ registry_handle_global (void *data,
if (strcmp (interface, "wl_compositor") == 0)
priv->compositor =
wl_registry_bind (registry, id, &wl_compositor_interface, 1);
else if (g_strcmp0 (interface, "wl_subcompositor") == 0)
priv->subcompositor =
wl_registry_bind (registry, id, &wl_subcompositor_interface, 1);
else if (strcmp (interface, "wl_shell") == 0)
priv->wl_shell = wl_registry_bind (registry, id, &wl_shell_interface, 1);
else if (strcmp (interface, "xdg_wm_base") == 0) {
......
......@@ -64,6 +64,7 @@ struct _GstVaapiDisplayWaylandPrivate
struct wl_compositor *compositor;
struct wl_shell *wl_shell;
struct xdg_wm_base *xdg_wm_base;
struct wl_subcompositor *subcompositor;
struct wl_output *output;
struct wl_registry *registry;
guint width;
......
......@@ -528,10 +528,12 @@ gst_vaapi_window_set_size (GstVaapiWindow * window, guint width, guint height)
if (!GST_VAAPI_WINDOW_GET_CLASS (window)->resize (window, width, height))
return;
GST_VAAPI_WINDOW_LOCK_DISPLAY (window);
gst_vaapi_video_pool_replace (&window->surface_pool, NULL);
window->width = width;
window->height = height;
GST_VAAPI_WINDOW_UNLOCK_DISPLAY (window);
}
static inline void
......
......@@ -102,6 +102,7 @@ struct _GstVaapiWindowWaylandPrivate
struct xdg_toplevel *xdg_toplevel;
struct wl_shell_surface *wl_shell_surface;
struct wl_surface *surface;
struct wl_subsurface *video_subsurface;
struct wl_region *opaque_region;
struct wl_event_queue *event_queue;
FrameState *last_frame;
......@@ -376,6 +377,10 @@ gst_vaapi_window_wayland_create (GstVaapiWindow * window,
g_return_val_if_fail (priv_display->xdg_wm_base || priv_display->wl_shell,
FALSE);
priv->poll = gst_poll_new (TRUE);
gst_poll_fd_init (&priv->pollfd);
priv->is_shown = TRUE;
GST_VAAPI_WINDOW_LOCK_DISPLAY (window);
priv->event_queue = wl_display_create_queue (priv_display->wl_display);
GST_VAAPI_WINDOW_UNLOCK_DISPLAY (window);
......@@ -389,6 +394,37 @@ gst_vaapi_window_wayland_create (GstVaapiWindow * window,
return FALSE;
wl_proxy_set_queue ((struct wl_proxy *) priv->surface, priv->event_queue);
if (window->use_foreign_window) {
struct wl_surface *wl_surface;
if (priv_display->subcompositor) {
if (GST_VAAPI_OBJECT_ID (window) == VA_INVALID_ID) {
GST_ERROR ("Invalid window");
return FALSE;
}
wl_surface = (struct wl_surface *) GST_VAAPI_WINDOW_ID (window);
GST_VAAPI_WINDOW_LOCK_DISPLAY (window);
priv->video_subsurface =
wl_subcompositor_get_subsurface (priv_display->subcompositor,
priv->surface, wl_surface);
GST_VAAPI_WINDOW_UNLOCK_DISPLAY (window);
if (!priv->video_subsurface)
return FALSE;
wl_proxy_set_queue ((struct wl_proxy *) priv->video_subsurface,
priv->event_queue);
wl_subsurface_set_position (priv->video_subsurface, 0, 0);
wl_subsurface_set_desync (priv->video_subsurface);
return TRUE;
} else {
GST_ERROR ("Wayland server does not support subsurfaces");
window->use_foreign_window = FALSE;
}
}
/* Prefer XDG-shell over deprecated wl_shell (if available) */
if (priv_display->xdg_wm_base) {
/* Create the XDG surface. We make the toplevel on VaapiWindow::show() */
......@@ -411,20 +447,14 @@ gst_vaapi_window_wayland_create (GstVaapiWindow * window,
return FALSE;
wl_proxy_set_queue ((struct wl_proxy *) priv->wl_shell_surface,
priv->event_queue);
wl_shell_surface_add_listener (priv->wl_shell_surface,
&shell_surface_listener, priv);
wl_shell_surface_set_toplevel (priv->wl_shell_surface);
}
priv->poll = gst_poll_new (TRUE);
gst_poll_fd_init (&priv->pollfd);
if (priv->fullscreen_on_show)
gst_vaapi_window_wayland_set_fullscreen (window, TRUE);
priv->is_shown = TRUE;
return TRUE;
}
......@@ -470,6 +500,9 @@ gst_vaapi_window_wayland_resize (GstVaapiWindow * window,
GstVaapiDisplayWaylandPrivate *const priv_display =
GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE (GST_VAAPI_WINDOW_DISPLAY (window));
if (window->use_foreign_window)
return TRUE;
GST_DEBUG ("resize window, new size %ux%u", width, height);
if (priv->opaque_region)
......@@ -590,12 +623,17 @@ gst_vaapi_window_wayland_render (GstVaapiWindow * window,
}
/* Wait for the previous frame to complete redraw */
if (!gst_vaapi_window_wayland_sync (window)) {
/* Release vpp surface if exists */
if (priv->need_vpp && window->has_vpp)
gst_vaapi_video_pool_put_object (window->surface_pool, surface);
wl_buffer_destroy (buffer);
return !priv->sync_failed;
if (!window->use_foreign_window) {
if (!gst_vaapi_window_wayland_sync (window)) {
/* Release vpp surface if exists */
if (priv->need_vpp && window->has_vpp)
gst_vaapi_video_pool_put_object (window->surface_pool, surface);
wl_buffer_destroy (buffer);
return !priv->sync_failed;
}
} else {
if (priv->event_queue)
wl_display_roundtrip_queue (wl_display, priv->event_queue);
}
frame = frame_state_new (window);
......@@ -702,3 +740,27 @@ gst_vaapi_window_wayland_new (GstVaapiDisplay * display,
return gst_vaapi_window_new_internal (GST_TYPE_VAAPI_WINDOW_WAYLAND, display,
GST_VAAPI_ID_INVALID, width, height);
}
/**
* gst_vaapi_window_wayland_new_with_surface:
* @display: a #GstVaapiDisplay
* @wl_surface: a Wayland surface pointer
*
* Creates a window with the specified @wl_surface. The window
* will be attached to the @display and remains invisible to the user
* until gst_vaapi_window_show() is called.
*
* Return value: the newly allocated #GstVaapiWindow object
*/
GstVaapiWindow *
gst_vaapi_window_wayland_new_with_surface (GstVaapiDisplay * display,
guintptr wl_surface)
{
g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_WAYLAND (display), NULL);
g_return_val_if_fail (wl_surface, NULL);
GST_DEBUG ("new window from surface 0x%" G_GUINTPTR_FORMAT, wl_surface);
return gst_vaapi_window_new_internal (GST_TYPE_VAAPI_WINDOW_WAYLAND, display,
wl_surface, 0, 0);
}
......@@ -45,6 +45,10 @@ GstVaapiWindow *
gst_vaapi_window_wayland_new (GstVaapiDisplay * display, guint width,
guint height);
GstVaapiWindow *
gst_vaapi_window_wayland_new_with_surface (GstVaapiDisplay * display,
guintptr wl_surface);
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiWindowWayland, gst_object_unref)
#endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment