From 060f597eda27c8e4492c265f249e21d4ad5f3cc3 Mon Sep 17 00:00:00 2001 From: Jian Date: Mon, 25 May 2015 16:30:53 +0800 Subject: [PATCH] [gl] Fix glimagesink loop playback failed in wayland MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gl/wayland: add GstGLDisplayWayland Simple implementation split from GstGLWindowWayland Upstream Status: Back Port https://bugzilla.gnome.org/show_bug.cgi?id=749411 Signed-off-by: Jian --- gst-libs/gst/gl/gstgldisplay.c | 5 +- gst-libs/gst/gl/wayland/Makefile.am | 2 + gst-libs/gst/gl/wayland/gstgldisplay_wayland.c | 157 +++++++++++++++++++++ gst-libs/gst/gl/wayland/gstgldisplay_wayland.h | 74 ++++++++++ gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c | 129 ++++++----------- 5 files changed, 280 insertions(+), 87 deletions(-) create mode 100644 gst-libs/gst/gl/wayland/gstgldisplay_wayland.c create mode 100644 gst-libs/gst/gl/wayland/gstgldisplay_wayland.h diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c index 9de8411..a200c14 100644 --- a/gst-libs/gst/gl/gstgldisplay.c +++ b/gst-libs/gst/gl/gstgldisplay.c @@ -59,6 +59,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 @@ -155,7 +158,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_WINDOW_FB if (!display && (!user_choice || g_strstr_len (user_choice, 2, "fb"))) { diff --git a/gst-libs/gst/gl/wayland/Makefile.am b/gst-libs/gst/gl/wayland/Makefile.am index 9006e67..1b284fb 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 0000000..90cf1ea --- /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 0000000..67b3883 --- /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 5d9b457..f1dd0d0 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 (); @@ -41,13 +42,13 @@ const gchar *WlEGLErrorString (); #define gst_gl_window_wayland_egl_parent_class parent_class G_DEFINE_TYPE (GstGLWindowWaylandEGL, gst_gl_window_wayland_egl, GST_GL_TYPE_WINDOW); +static void gst_gl_window_wayland_egl_finalize (GObject * object); 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_draw (GstGLWindow * window, guint width, - guint height); +static void gst_gl_window_wayland_egl_draw (GstGLWindow * window, guint width, guint height); static void gst_gl_window_wayland_egl_run (GstGLWindow * window); static void gst_gl_window_wayland_egl_quit (GstGLWindow * window); static void gst_gl_window_wayland_egl_send_message_async (GstGLWindow * window, @@ -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) @@ -149,11 +151,15 @@ 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) { + GstGLWindowWaylandEGL *window_egl = data; + + GST_TRACE_OBJECT (window_egl, "ping received serial %u", serial); + wl_shell_surface_pong (shell_surface, serial); } @@ -166,7 +172,8 @@ handle_configure (void *data, struct wl_shell_surface *shell_surface, { GstGLWindowWaylandEGL *window_egl = data; - GST_DEBUG ("configure event %ix%i", width, height); + GST_DEBUG ("configure event on surface %p, %ix%i", shell_surface, width, + height); window_resize (window_egl, width, height); } @@ -185,11 +192,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); @@ -225,46 +234,13 @@ destroy_surface (GstGLWindowWaylandEGL * window_egl) if (window_egl->window.callback) wl_callback_destroy (window_egl->window.callback); - - g_source_destroy (window_egl->wl_source); - g_source_unref (window_egl->wl_source); - window_egl->wl_source = NULL; - g_main_loop_unref (window_egl->loop); - window_egl->loop = NULL, g_main_context_unref (window_egl->main_context); - window_egl->main_context = NULL; -} - -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; - - 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) { GstGLWindowClass *window_class = (GstGLWindowClass *) klass; + GObjectClass *gobject_class = (GObjectClass *) klass; window_class->get_window_handle = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_get_window_handle); @@ -281,11 +257,26 @@ gst_gl_window_wayland_egl_class_init (GstGLWindowWaylandEGLClass * klass) window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_open); window_class->get_display = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_get_display); + + gobject_class->finalize = gst_gl_window_wayland_egl_finalize; } static void gst_gl_window_wayland_egl_init (GstGLWindowWaylandEGL * window) { + window->main_context = g_main_context_new (); + window->loop = g_main_loop_new (window->main_context, FALSE); +} + +static void +gst_gl_window_wayland_egl_finalize (GObject * object) +{ + GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (object); + + g_main_loop_unref (window_egl->loop); + g_main_context_unref (window_egl->main_context); + + G_OBJECT_CLASS (parent_class)->finalize (object); } /* Must be called in the gl thread */ @@ -310,60 +301,33 @@ 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; } 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->main_context = g_main_context_new (); - window_egl->loop = g_main_loop_new (window_egl->main_context, FALSE); + 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 @@ -461,11 +425,6 @@ window_resize (GstGLWindowWaylandEGL * window_egl, guint width, guint height) window_egl->window.window_width = width; window_egl->window.window_height = height; - -#if 0 - wl_shell_surface_resize (window_egl->window.shell_surface, - window_egl->display.seat, window_egl->display.serial, 0); -#endif } struct draw @@ -520,9 +479,7 @@ gst_gl_window_wayland_egl_draw (GstGLWindow * window, guint width, guint height) static guintptr gst_gl_window_wayland_egl_get_display (GstGLWindow * window) { - GstGLWindowWaylandEGL *window_egl; - - window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); + GstGLDisplayWayland *display = GST_GL_DISPLAY_WAYLAND (window->display); - return (guintptr) window_egl->display.display; + return (guintptr) display->display; } -- 1.7.9.5