diff options
author | Matthew Waters <matthew@centricular.com> | 2015-05-27 16:39:06 +1000 |
---|---|---|
committer | Matthew Waters <matthew@centricular.com> | 2015-05-31 16:04:13 +1000 |
commit | de389e07dc553110bb68cc5399bcfc3802df067f (patch) | |
tree | da5bdda307ec287b2e66c2e1bb9aad619933c64e /gst-libs | |
parent | 1dc0f40a35f8b6fa8299e5e74eb10861e4090c48 (diff) | |
download | gstreamer-plugins-bad-de389e07dc553110bb68cc5399bcfc3802df067f.tar.gz |
gl/wayland: implement basic video overlay support via subsurfaces
Currently does not position the subsurface relative to the parent surface at all
Diffstat (limited to 'gst-libs')
-rw-r--r-- | gst-libs/gst/gl/egl/gstglcontext_egl.c | 9 | ||||
-rw-r--r-- | gst-libs/gst/gl/wayland/gstgldisplay_wayland.c | 3 | ||||
-rw-r--r-- | gst-libs/gst/gl/wayland/gstgldisplay_wayland.h | 1 | ||||
-rw-r--r-- | gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c | 188 | ||||
-rw-r--r-- | gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h | 6 |
5 files changed, 165 insertions, 42 deletions
diff --git a/gst-libs/gst/gl/egl/gstglcontext_egl.c b/gst-libs/gst/gl/egl/gstglcontext_egl.c index f1fb70f05..14be7c68c 100644 --- a/gst-libs/gst/gl/egl/gstglcontext_egl.c +++ b/gst-libs/gst/gl/egl/gstglcontext_egl.c @@ -34,6 +34,9 @@ #include "../x11/gstglwindow_x11.h" #include <gst/gl/x11/gstgldisplay_x11.h> #endif +#if GST_GL_HAVE_WINDOW_WAYLAND +#include "../wayland/gstglwindow_wayland_egl.h" +#endif #if GST_GL_HAVE_WINDOW_WIN32 #include "../win32/gstglwindow_win32.h" #endif @@ -393,6 +396,12 @@ gst_gl_context_egl_create_context (GstGLContext * context, gst_gl_window_x11_create_window ((GstGLWindowX11 *) context->window); } #endif +#if GST_GL_HAVE_WINDOW_WAYLAND + if (GST_GL_IS_WINDOW_WAYLAND_EGL (context->window)) { + gst_gl_window_wayland_egl_create_window ((GstGLWindowWaylandEGL *) + context->window); + } +#endif #if GST_GL_HAVE_WINDOW_WIN32 if (GST_GL_IS_WINDOW_WIN32 (context->window)) { gst_gl_window_win32_create_window ((GstGLWindowWin32 *) context->window); diff --git a/gst-libs/gst/gl/wayland/gstgldisplay_wayland.c b/gst-libs/gst/gl/wayland/gstgldisplay_wayland.c index 90cf1eac7..c5c509445 100644 --- a/gst-libs/gst/gl/wayland/gstgldisplay_wayland.c +++ b/gst-libs/gst/gl/wayland/gstgldisplay_wayland.c @@ -45,6 +45,9 @@ registry_handle_global (void *data, struct wl_registry *registry, if (g_strcmp0 (interface, "wl_compositor") == 0) { display->compositor = wl_registry_bind (registry, name, &wl_compositor_interface, 1); + } else if (g_strcmp0 (interface, "wl_subcompositor") == 0) { + display->subcompositor = + wl_registry_bind (registry, name, &wl_subcompositor_interface, 1); } else if (g_strcmp0 (interface, "wl_shell") == 0) { display->shell = wl_registry_bind (registry, name, &wl_shell_interface, 1); } diff --git a/gst-libs/gst/gl/wayland/gstgldisplay_wayland.h b/gst-libs/gst/gl/wayland/gstgldisplay_wayland.h index 67b388371..3612c787f 100644 --- a/gst-libs/gst/gl/wayland/gstgldisplay_wayland.h +++ b/gst-libs/gst/gl/wayland/gstgldisplay_wayland.h @@ -55,6 +55,7 @@ struct _GstGLDisplayWayland struct wl_display *display; struct wl_registry *registry; struct wl_compositor *compositor; + struct wl_subcompositor *subcompositor; struct wl_shell *shell; /* <private> */ diff --git a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c index 6679abc50..519f9af4c 100644 --- a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c +++ b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c @@ -48,6 +48,7 @@ static guintptr gst_gl_window_wayland_egl_get_window_handle (GstGLWindow * window); static void gst_gl_window_wayland_egl_set_window_handle (GstGLWindow * window, guintptr handle); +static void gst_gl_window_wayland_egl_show (GstGLWindow * window); static void gst_gl_window_wayland_egl_draw (GstGLWindow * window); static void gst_gl_window_wayland_egl_run (GstGLWindow * window); static void gst_gl_window_wayland_egl_quit (GstGLWindow * window); @@ -228,56 +229,124 @@ static const struct wl_shell_surface_listener shell_surface_listener = { handle_popup_done }; -static gboolean -create_surface (GstGLWindowWaylandEGL * window_egl) +static void +surface_handle_enter (void *data, struct wl_surface *wl_surface, + struct wl_output *output) { - GstGLDisplayWayland *display = - GST_GL_DISPLAY_WAYLAND (GST_GL_WINDOW (window_egl)->display); - - window_egl->window.surface = - wl_compositor_create_surface (display->compositor); - wl_proxy_set_queue ((struct wl_proxy *) window_egl->window.surface, - window_egl->window.queue); - - window_egl->window.shell_surface = - wl_shell_get_shell_surface (display->shell, window_egl->window.surface); - wl_proxy_set_queue ((struct wl_proxy *) window_egl->window.shell_surface, - window_egl->window.queue); - - wl_shell_surface_add_listener (window_egl->window.shell_surface, - &shell_surface_listener, window_egl); - - if (window_egl->window.window_width <= 0) - window_egl->window.window_width = 320; - if (window_egl->window.window_height <= 0) - window_egl->window.window_height = 240; - - window_egl->window.native = - wl_egl_window_create (window_egl->window.surface, - window_egl->window.window_width, window_egl->window.window_height); +} - wl_shell_surface_set_title (window_egl->window.shell_surface, - "OpenGL Renderer"); +static void +surface_handle_leave (void *data, struct wl_surface *wl_surface, + struct wl_output *output) +{ +} - wl_shell_surface_set_toplevel (window_egl->window.shell_surface); +static const struct wl_surface_listener surface_listener = { + surface_handle_enter, + surface_handle_leave +}; - return TRUE; +static void +destroy_surfaces (GstGLWindowWaylandEGL * window_egl) +{ + if (window_egl->window.subsurface) { + wl_subsurface_destroy (window_egl->window.subsurface); + window_egl->window.subsurface = NULL; + } + if (window_egl->window.shell_surface) { + wl_shell_surface_destroy (window_egl->window.shell_surface); + window_egl->window.shell_surface = NULL; + } + if (window_egl->window.surface) { + wl_surface_destroy (window_egl->window.surface); + window_egl->window.surface = NULL; + } + if (window_egl->window.native) { + wl_egl_window_destroy (window_egl->window.native); + window_egl->window.native = NULL; + } } static void -destroy_surface (GstGLWindowWaylandEGL * window_egl) +create_surfaces (GstGLWindowWaylandEGL * window_egl) { - if (window_egl->window.native) - wl_egl_window_destroy (window_egl->window.native); + GstGLDisplayWayland *display = + GST_GL_DISPLAY_WAYLAND (GST_GL_WINDOW (window_egl)->display); + gint width, height; + + if (!window_egl->window.surface) { + window_egl->window.surface = + wl_compositor_create_surface (display->compositor); + if (window_egl->window.queue) + wl_proxy_set_queue ((struct wl_proxy *) window_egl->window.surface, + window_egl->window.queue); + } - if (window_egl->window.shell_surface) - wl_shell_surface_destroy (window_egl->window.shell_surface); + if (gst_gl_wl_display_roundtrip_queue (display->display, + window_egl->window.queue) < 0) { + GST_ERROR_OBJECT (window_egl, + "Failed to perform a roundtrip on our wl_event_queue"); + } - if (window_egl->window.surface) - wl_surface_destroy (window_egl->window.surface); + if (window_egl->window.foreign_surface) { + /* (re)parent */ + if (!display->subcompositor) { + GST_ERROR_OBJECT (window_egl, + "Wayland server does not support subsurfaces"); + window_egl->window.foreign_surface = NULL; + goto shell_window; + } + + if (!window_egl->window.subsurface) { + window_egl->window.subsurface = + wl_subcompositor_get_subsurface (display->subcompositor, + window_egl->window.surface, window_egl->window.foreign_surface); + if (window_egl->window.queue) + wl_proxy_set_queue ((struct wl_proxy *) window_egl->window.subsurface, + window_egl->window.queue); + + wl_subsurface_set_position (window_egl->window.subsurface, + window_egl->window.window_x, window_egl->window.window_y); + wl_subsurface_set_desync (window_egl->window.subsurface); + } + } else { + shell_window: + if (!window_egl->window.shell_surface) { + window_egl->window.shell_surface = + wl_shell_get_shell_surface (display->shell, + window_egl->window.surface); + if (window_egl->window.queue) + wl_proxy_set_queue ((struct wl_proxy *) window_egl->window. + shell_surface, window_egl->window.queue); + + wl_shell_surface_add_listener (window_egl->window.shell_surface, + &shell_surface_listener, window_egl); + + wl_shell_surface_set_title (window_egl->window.shell_surface, + "OpenGL Renderer"); + wl_shell_surface_set_toplevel (window_egl->window.shell_surface); + } + } - if (window_egl->window.callback) - wl_callback_destroy (window_egl->window.callback); + if (window_egl->window.window_width > 0) + width = window_egl->window.window_width; + else + width = 320; + window_egl->window.window_width = width; + + if (window_egl->window.window_height > 0) + height = window_egl->window.window_height; + else + height = 240; + window_egl->window.window_height = height; + + if (!window_egl->window.native) { + window_egl->window.native = + wl_egl_window_create (window_egl->window.surface, width, height); + if (window_egl->window.queue) + wl_proxy_set_queue ((struct wl_proxy *) window_egl->window.native, + window_egl->window.queue); + } } static void @@ -292,6 +361,7 @@ gst_gl_window_wayland_egl_class_init (GstGLWindowWaylandEGLClass * klass) GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_set_window_handle); window_class->draw_unlocked = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_draw); + window_class->show = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_show); window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_draw); window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_run); window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_quit); @@ -343,7 +413,7 @@ gst_gl_window_wayland_egl_close (GstGLWindow * window) window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); - destroy_surface (window_egl); + destroy_surfaces (window_egl); g_source_destroy (window_egl->wl_source); g_source_unref (window_egl->wl_source); @@ -367,7 +437,7 @@ gst_gl_window_wayland_egl_open (GstGLWindow * window, GError ** error) wl_display_roundtrip (display->display); - create_surface (window_egl); + create_surfaces (window_egl); window_egl->wl_source = wayland_event_source_new (display->display, window_egl->window.queue); @@ -442,6 +512,12 @@ gst_gl_window_wayland_egl_send_message_async (GstGLWindow * window, message); } +void +gst_gl_window_wayland_egl_create_window (GstGLWindowWaylandEGL * window_egl) +{ + create_surfaces (window_egl); +} + static guintptr gst_gl_window_wayland_egl_get_window_handle (GstGLWindow * window) { @@ -452,6 +528,31 @@ static void gst_gl_window_wayland_egl_set_window_handle (GstGLWindow * window, guintptr handle) { + GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); + struct wl_surface *surface = (struct wl_surface *) handle; + + /* already set the NULL handle */ + if (surface == NULL && window_egl->window.foreign_surface == NULL) + return; + + /* unparent */ + destroy_surfaces (window_egl); + window_egl->window.foreign_surface = surface; + create_surfaces (window_egl); +} + +static void +gst_gl_window_wayland_egl_show (GstGLWindow * window) +{ + GstGLDisplayWayland *display_wayland = + GST_GL_DISPLAY_WAYLAND (window->display); + GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); + + create_surfaces (window_egl); + + if (gst_gl_wl_display_roundtrip_queue (display_wayland->display, + window_egl->window.queue) < 0) + GST_WARNING_OBJECT (window, "failed a roundtrip"); } static void @@ -482,11 +583,16 @@ draw_cb (gpointer data) GstGLContext *context = gst_gl_window_get_context (window); GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context); + create_surfaces (window_egl); + if (window->draw) window->draw (window->draw_data); context_class->swap_buffers (context); + if (window_egl->window.subsurface) + wl_subsurface_set_desync (window_egl->window.subsurface); + gst_object_unref (context); } diff --git a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h index 845b9254b..3d08f6f98 100644 --- a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h +++ b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h @@ -64,9 +64,11 @@ struct window { struct display *display; struct wl_event_queue *queue; - struct wl_egl_window *native; struct wl_surface *surface; struct wl_shell_surface *shell_surface; + struct wl_egl_window *native; + struct wl_surface *foreign_surface; + struct wl_subsurface *subsurface; struct wl_callback *callback; int fullscreen, configured; int window_width, window_height; @@ -98,6 +100,8 @@ GType gst_gl_window_wayland_egl_get_type (void); GstGLWindowWaylandEGL * gst_gl_window_wayland_egl_new (void); +void gst_gl_window_wayland_egl_create_window (GstGLWindowWaylandEGL * window_egl); + G_END_DECLS #endif /* __GST_GL_WINDOW_X11_H__ */ |