diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c index a049af4640..5baee7ae05 100644 --- a/gst-libs/gst/gl/gstgldisplay.c +++ b/gst-libs/gst/gl/gstgldisplay.c @@ -62,6 +62,9 @@ #if GST_GL_HAVE_WINDOW_X11 #include #endif +#if GST_GL_HAVE_WINDOW_WAYLAND +#include +#endif #if GST_GL_HAVE_PLATFORM_EGL #include #include @@ -174,7 +177,7 @@ gst_gl_display_new (void) #endif #if GST_GL_HAVE_WINDOW_WAYLAND if (!display && (!user_choice || g_strstr_len (user_choice, 7, "wayland"))) - display = g_object_new (GST_TYPE_GL_DISPLAY, NULL); + display = GST_GL_DISPLAY (gst_gl_display_wayland_new (NULL)); #endif #if GST_GL_HAVE_PLATFORM_EGL if (!display && (!platform_choice diff --git a/gst-libs/gst/gl/wayland/Makefile.am b/gst-libs/gst/gl/wayland/Makefile.am index 9006e672ac..1b284fbc66 100644 --- a/gst-libs/gst/gl/wayland/Makefile.am +++ b/gst-libs/gst/gl/wayland/Makefile.am @@ -3,10 +3,12 @@ noinst_LTLIBRARIES = libgstgl-wayland.la libgstgl_wayland_la_SOURCES = \ + gstgldisplay_wayland.c \ gstglwindow_wayland_egl.c \ wayland_event_source.c noinst_HEADERS = \ + gstgldisplay_wayland.h \ gstglwindow_wayland_egl.h \ wayland_event_source.h diff --git a/gst-libs/gst/gl/wayland/gstgldisplay_wayland.c b/gst-libs/gst/gl/wayland/gstgldisplay_wayland.c new file mode 100644 index 0000000000..90cf1eac78 --- /dev/null +++ b/gst-libs/gst/gl/wayland/gstgldisplay_wayland.c @@ -0,0 +1,157 @@ +/* + * GStreamer + * Copyright (C) 2013 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug); +#define GST_CAT_DEFAULT gst_gl_display_debug + +G_DEFINE_TYPE (GstGLDisplayWayland, gst_gl_display_wayland, + GST_TYPE_GL_DISPLAY); + +static void gst_gl_display_wayland_finalize (GObject * object); +static guintptr gst_gl_display_wayland_get_handle (GstGLDisplay * display); + +static void +registry_handle_global (void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) +{ + GstGLDisplayWayland *display = data; + + GST_TRACE_OBJECT (display, "registry_handle_global with registry %p, " + "interface %s, version %u", registry, interface, version); + + if (g_strcmp0 (interface, "wl_compositor") == 0) { + display->compositor = + wl_registry_bind (registry, name, &wl_compositor_interface, 1); + } else if (g_strcmp0 (interface, "wl_shell") == 0) { + display->shell = wl_registry_bind (registry, name, &wl_shell_interface, 1); + } +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global +}; + +static void +_connect_listeners (GstGLDisplayWayland * display) +{ + display->registry = wl_display_get_registry (display->display); + wl_registry_add_listener (display->registry, ®istry_listener, display); + + wl_display_roundtrip (display->display); +} + +static void +gst_gl_display_wayland_class_init (GstGLDisplayWaylandClass * klass) +{ + GST_GL_DISPLAY_CLASS (klass)->get_handle = + GST_DEBUG_FUNCPTR (gst_gl_display_wayland_get_handle); + + G_OBJECT_CLASS (klass)->finalize = gst_gl_display_wayland_finalize; +} + +static void +gst_gl_display_wayland_init (GstGLDisplayWayland * display_wayland) +{ + GstGLDisplay *display = (GstGLDisplay *) display_wayland; + + display->type = GST_GL_DISPLAY_TYPE_WAYLAND; + display_wayland->foreign_display = FALSE; +} + +static void +gst_gl_display_wayland_finalize (GObject * object) +{ + GstGLDisplayWayland *display_wayland = GST_GL_DISPLAY_WAYLAND (object); + + if (!display_wayland->foreign_display && display_wayland->display) { + wl_display_flush (display_wayland->display); + wl_display_disconnect (display_wayland->display); + } + + G_OBJECT_CLASS (gst_gl_display_wayland_parent_class)->finalize (object); +} + +/** + * gst_gl_display_wayland_new: + * @name: (allow-none): a display name + * + * Create a new #GstGLDisplayWayland from the wayland display name. See wl_display_connect() + * for details on what is a valid name. + * + * Returns: (transfer full): a new #GstGLDisplayWayland or %NULL + */ +GstGLDisplayWayland * +gst_gl_display_wayland_new (const gchar * name) +{ + GstGLDisplayWayland *ret; + + GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay"); + + ret = g_object_new (GST_TYPE_GL_DISPLAY_WAYLAND, NULL); + ret->display = wl_display_connect (name); + + if (!ret->display) { + GST_ERROR ("Failed to open X11 display connection with name, \'%s\'", name); + return NULL; + } + + _connect_listeners (ret); + + return ret; +} + +/** + * gst_gl_display_wayland_new_with_display: + * @display: an existing, wayland display + * + * Creates a new display connection from a wl_display Display. + * + * Returns: (transfer full): a new #GstGLDisplayWayland + */ +GstGLDisplayWayland * +gst_gl_display_wayland_new_with_display (struct wl_display * display) +{ + GstGLDisplayWayland *ret; + + g_return_val_if_fail (display != NULL, NULL); + + GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay"); + + ret = g_object_new (GST_TYPE_GL_DISPLAY_WAYLAND, NULL); + + ret->display = display; + ret->foreign_display = TRUE; + + _connect_listeners (ret); + + return ret; +} + +static guintptr +gst_gl_display_wayland_get_handle (GstGLDisplay * display) +{ + return (guintptr) GST_GL_DISPLAY_WAYLAND (display)->display; +} diff --git a/gst-libs/gst/gl/wayland/gstgldisplay_wayland.h b/gst-libs/gst/gl/wayland/gstgldisplay_wayland.h new file mode 100644 index 0000000000..67b388371d --- /dev/null +++ b/gst-libs/gst/gl/wayland/gstgldisplay_wayland.h @@ -0,0 +1,74 @@ +/* + * GStreamer + * Copyright (C) 2013 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_GL_DISPLAY_WAYLAND_H__ +#define __GST_GL_DISPLAY_WAYLAND_H__ + +#include + +#include + +#include +#include + +G_BEGIN_DECLS + +GType gst_gl_display_wayland_get_type (void); + +#define GST_TYPE_GL_DISPLAY_WAYLAND (gst_gl_display_wayland_get_type()) +#define GST_GL_DISPLAY_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_DISPLAY_WAYLAND,GstGLDisplayWayland)) +#define GST_GL_DISPLAY_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_GL_DISPLAY_WAYLAND,GstGLDisplayWaylandClass)) +#define GST_IS_GL_DISPLAY_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_DISPLAY_WAYLAND)) +#define GST_IS_GL_DISPLAY_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_GL_DISPLAY_WAYLAND)) +#define GST_GL_DISPLAY_WAYLAND_CAST(obj) ((GstGLDisplayWayland*)(obj)) + +typedef struct _GstGLDisplayWayland GstGLDisplayWayland; +typedef struct _GstGLDisplayWaylandClass GstGLDisplayWaylandClass; + +/** + * GstGLDisplayWayland: + * + * the contents of a #GstGLDisplayWayland are private and should only be accessed + * through the provided API + */ +struct _GstGLDisplayWayland +{ + GstGLDisplay parent; + + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_shell *shell; + + /* */ + gboolean foreign_display; +}; + +struct _GstGLDisplayWaylandClass +{ + GstGLDisplayClass object_class; +}; + +GstGLDisplayWayland *gst_gl_display_wayland_new (const gchar * name); +GstGLDisplayWayland *gst_gl_display_wayland_new_with_display (struct wl_display *display); + +G_END_DECLS + +#endif /* __GST_GL_DISPLAY_WAYLAND_H__ */ diff --git a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c index 271a677993..34f0a0660e 100644 --- a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c +++ b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c @@ -32,6 +32,7 @@ #include "../gstgl_fwd.h" #include +#include "gstgldisplay_wayland.h" #include "gstglwindow_wayland_egl.h" const gchar *WlEGLErrorString (); @@ -57,6 +58,7 @@ static gboolean gst_gl_window_wayland_egl_open (GstGLWindow * window, GError ** error); static guintptr gst_gl_window_wayland_egl_get_display (GstGLWindow * window); +#if 0 static void pointer_handle_enter (void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t sx_w, wl_fixed_t sy_w) @@ -188,7 +190,7 @@ seat_handle_capabilities (void *data, struct wl_seat *seat, static const struct wl_seat_listener seat_listener = { seat_handle_capabilities, }; - +#endif static void handle_ping (void *data, struct wl_shell_surface *shell_surface, uint32_t serial) @@ -229,11 +231,13 @@ static const struct wl_shell_surface_listener shell_surface_listener = { static gboolean create_surface (GstGLWindowWaylandEGL * window_egl) { + GstGLDisplayWayland *display = + GST_GL_DISPLAY_WAYLAND (GST_GL_WINDOW (window_egl)->display); + window_egl->window.surface = - wl_compositor_create_surface (window_egl->display.compositor); + wl_compositor_create_surface (display->compositor); window_egl->window.shell_surface = - wl_shell_get_shell_surface (window_egl->display.shell, - window_egl->window.surface); + wl_shell_get_shell_surface (display->shell, window_egl->window.surface); wl_shell_surface_add_listener (window_egl->window.shell_surface, &shell_surface_listener, window_egl); @@ -271,36 +275,6 @@ destroy_surface (GstGLWindowWaylandEGL * window_egl) wl_callback_destroy (window_egl->window.callback); } -static void -registry_handle_global (void *data, struct wl_registry *registry, - uint32_t name, const char *interface, uint32_t version) -{ - GstGLWindowWaylandEGL *window_egl = data; - struct display *d = &window_egl->display; - - GST_TRACE_OBJECT (window_egl, "registry_handle_global with registry %p, " - "interface %s, version %u", registry, interface, version); - - if (g_strcmp0 (interface, "wl_compositor") == 0) { - d->compositor = - wl_registry_bind (registry, name, &wl_compositor_interface, 1); - } else if (g_strcmp0 (interface, "wl_shell") == 0) { - d->shell = wl_registry_bind (registry, name, &wl_shell_interface, 1); - } else if (g_strcmp0 (interface, "wl_seat") == 0) { - d->seat = wl_registry_bind (registry, name, &wl_seat_interface, 1); - wl_seat_add_listener (d->seat, &seat_listener, window_egl); - } else if (g_strcmp0 (interface, "wl_shm") == 0) { - d->shm = wl_registry_bind (registry, name, &wl_shm_interface, 1); - d->cursor_theme = wl_cursor_theme_load (NULL, 32, d->shm); - d->default_cursor = - wl_cursor_theme_get_cursor (d->cursor_theme, "left_ptr"); - } -} - -static const struct wl_registry_listener registry_listener = { - registry_handle_global -}; - static void gst_gl_window_wayland_egl_class_init (GstGLWindowWaylandEGLClass * klass) { @@ -366,23 +340,6 @@ gst_gl_window_wayland_egl_close (GstGLWindow * window) destroy_surface (window_egl); - if (window_egl->display.cursor_surface) - wl_surface_destroy (window_egl->display.cursor_surface); - - if (window_egl->display.cursor_theme) - wl_cursor_theme_destroy (window_egl->display.cursor_theme); - - if (window_egl->display.shell) - wl_shell_destroy (window_egl->display.shell); - - if (window_egl->display.compositor) - wl_compositor_destroy (window_egl->display.compositor); - - if (window_egl->display.display) { - wl_display_flush (window_egl->display.display); - wl_display_disconnect (window_egl->display.display); - } - g_source_destroy (window_egl->wl_source); g_source_unref (window_egl->wl_source); window_egl->wl_source = NULL; @@ -391,37 +348,25 @@ gst_gl_window_wayland_egl_close (GstGLWindow * window) static gboolean gst_gl_window_wayland_egl_open (GstGLWindow * window, GError ** error) { + GstGLDisplayWayland *display = GST_GL_DISPLAY_WAYLAND (window->display); GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); - window_egl->display.display = wl_display_connect (NULL); - if (!window_egl->display.display) { + if (!display->display) { g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_RESOURCE_UNAVAILABLE, - "Failed to connect to Wayland display server"); - goto error; + "Failed to retreive Wayland display"); + return FALSE; } - window_egl->display.registry = - wl_display_get_registry (window_egl->display.display); - wl_registry_add_listener (window_egl->display.registry, ®istry_listener, - window_egl); - - wl_display_dispatch (window_egl->display.display); + wl_display_roundtrip (display->display); create_surface (window_egl); - window_egl->display.cursor_surface = - wl_compositor_create_surface (window_egl->display.compositor); - - window_egl->wl_source = - wayland_event_source_new (window_egl->display.display); + window_egl->wl_source = wayland_event_source_new (display->display); g_source_attach (window_egl->wl_source, window_egl->main_context); return TRUE; - -error: - return FALSE; } static void @@ -546,9 +491,7 @@ gst_gl_window_wayland_egl_draw (GstGLWindow * window) static guintptr gst_gl_window_wayland_egl_get_display (GstGLWindow * window) { - GstGLWindowWaylandEGL *window_egl; + GstGLDisplayWayland *display = GST_GL_DISPLAY_WAYLAND (window->display); - window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); - - return (guintptr) window_egl->display.display; + return (guintptr) display->display; }