summaryrefslogtreecommitdiff
path: root/gst-libs
diff options
context:
space:
mode:
authorMatthew Waters <matthew@centricular.com>2015-05-27 16:39:06 +1000
committerMatthew Waters <matthew@centricular.com>2015-05-31 16:04:13 +1000
commitde389e07dc553110bb68cc5399bcfc3802df067f (patch)
treeda5bdda307ec287b2e66c2e1bb9aad619933c64e /gst-libs
parent1dc0f40a35f8b6fa8299e5e74eb10861e4090c48 (diff)
downloadgstreamer-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.c9
-rw-r--r--gst-libs/gst/gl/wayland/gstgldisplay_wayland.c3
-rw-r--r--gst-libs/gst/gl/wayland/gstgldisplay_wayland.h1
-rw-r--r--gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c188
-rw-r--r--gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h6
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__ */