From 4a07c73c0c45fbd465c9ef893ab8c778c4c9a90b Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Thu, 29 Nov 2012 01:01:59 +1100 Subject: [PATCH] [618/906] add wayland-egl window backend --- gst-libs/gst/gl/Makefile.am | 14 +- gst-libs/gst/gl/cocoa/Makefile.am | 1 + gst-libs/gst/gl/gstglwindow.c | 25 +- gst-libs/gst/gl/gstglwindow.h | 2 + gst-libs/gst/gl/wayland/Makefile.am | 27 + .../gst/gl/wayland/gstglwindow_wayland_egl.c | 550 ++++++++++++++++++ .../gst/gl/wayland/gstglwindow_wayland_egl.h | 106 ++++ .../gst/gl/wayland/wayland_event_source.c | 125 ++++ .../gst/gl/wayland/wayland_event_source.h | 39 ++ 9 files changed, 881 insertions(+), 8 deletions(-) create mode 100644 gst-libs/gst/gl/wayland/Makefile.am create mode 100644 gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c create mode 100644 gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h create mode 100644 gst-libs/gst/gl/wayland/wayland_event_source.c create mode 100644 gst-libs/gst/gl/wayland/wayland_event_source.h diff --git a/gst-libs/gst/gl/Makefile.am b/gst-libs/gst/gl/Makefile.am index 26dd2ff1fc..a59b8dd4c4 100644 --- a/gst-libs/gst/gl/Makefile.am +++ b/gst-libs/gst/gl/Makefile.am @@ -16,8 +16,10 @@ libgstgl_@GST_API_VERSION@_la_SOURCES = \ gstglwindow.c libgstgl_@GST_API_VERSION@_la_LIBADD = \ - $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_API_VERSION) \ - $(GST_BASE_LIBS) $(GST_LIBS) \ + $(GST_PLUGINS_BASE_LIBS) \ + -lgstvideo-$(GST_API_VERSION) \ + $(GST_BASE_LIBS) \ + $(GST_LIBS) \ $(GL_LIBS) if HAVE_WINDOW_WIN32 @@ -35,6 +37,11 @@ SUBDIRS += x11 libgstgl_@GST_API_VERSION@_la_LIBADD += x11/libgstgl-x11.la endif +if HAVE_WINDOW_WAYLAND +SUBDIRS += wayland +libgstgl_@GST_API_VERSION@_la_LIBADD += wayland/libgstgl-wayland.la +endif + libgstgl_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/gl libgstgl_@GST_API_VERSION@include_HEADERS = \ gstglwindow.h \ @@ -55,7 +62,8 @@ libgstgl_@GST_API_VERSION@_la_CFLAGS = \ $(X_CFLAGS) \ $(GST_PLUGINS_BASE_CFLAGS) \ $(GST_BASE_CFLAGS) \ - $(GST_CFLAGS) + $(GST_CFLAGS) \ + $(GL_CFLAGS) libgstgl_@GST_API_VERSION@_la_LDFLAGS = \ $(GST_LIB_LDFLAGS) \ diff --git a/gst-libs/gst/gl/cocoa/Makefile.am b/gst-libs/gst/gl/cocoa/Makefile.am index 80d9f88702..665a168caf 100644 --- a/gst-libs/gst/gl/cocoa/Makefile.am +++ b/gst-libs/gst/gl/cocoa/Makefile.am @@ -21,6 +21,7 @@ libgstgl_cocoa_la_CFLAGS = \ libgstgl_cocoa_la_OBJCFLAGS = \ $(GL_CFLAGS) \ + $(GL_OBJCFLAGS) \ $(X_CFLAGS) \ $(GST_PLUGINS_BASE_CFLAGS) \ $(GST_BASE_CFLAGS) \ diff --git a/gst-libs/gst/gl/gstglwindow.c b/gst-libs/gst/gl/gstglwindow.c index 0252cab5bf..667fd9d398 100644 --- a/gst-libs/gst/gl/gstglwindow.c +++ b/gst-libs/gst/gl/gstglwindow.c @@ -33,15 +33,15 @@ #ifdef HAVE_WINDOW_COCOA #include "cocoa/gstglwindow_cocoa.h" #endif +#ifdef HAVE_WINDOW_WAYLAND +#include "wayland/gstglwindow_wayland_egl.h" +#endif #define GST_CAT_DEFAULT gst_gl_window_debug -GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); +GST_DEBUG_CATEGORY (GST_CAT_DEFAULT); -#define DEBUG_INIT \ - GST_DEBUG_CATEGORY_INIT (gst_gl_window_debug, "glwindow", 0, "glwindow element"); #define gst_gl_window_parent_class parent_class -G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstGLWindow, gst_gl_window, G_TYPE_OBJECT, - DEBUG_INIT); +G_DEFINE_ABSTRACT_TYPE (GstGLWindow, gst_gl_window, G_TYPE_OBJECT); static void gst_gl_window_init (GstGLWindow * window) @@ -60,8 +60,17 @@ gst_gl_window_new (GstGLRendererAPI render_api, guintptr external_gl_context) { GstGLWindow *window = NULL; const gchar *user_choice; + static volatile gsize _init = 0; + + if (g_once_init_enter (&_init)) { + GST_DEBUG_CATEGORY_INIT (gst_gl_window_debug, "glwindow", 0, + "glwindow element"); + g_once_init_leave (&_init, 1); + } user_choice = g_getenv ("GST_GL_WINDOW"); + GST_INFO ("creating a window, user choice:%s", user_choice); + #ifdef HAVE_WINDOW_X11 if (!window && (!user_choice || g_strstr_len (user_choice, 3, "x11"))) window = @@ -78,6 +87,12 @@ gst_gl_window_new (GstGLRendererAPI render_api, guintptr external_gl_context) window = GST_GL_WINDOW (gst_gl_window_cocoa_new (render_api, external_gl_context)); +#endif +#ifdef HAVE_WINDOW_WAYLAND + if (!window && (!user_choice || g_strstr_len (user_choice, 7, "wayland"))) + window = + GST_GL_WINDOW (gst_gl_window_wayland_egl_new (render_api, + external_gl_context)); #endif if (!window) { GST_WARNING ("could not create a window, user choice:%s", user_choice); diff --git a/gst-libs/gst/gl/gstglwindow.h b/gst-libs/gst/gl/gstglwindow.h index 1733999dd1..d78291d95b 100644 --- a/gst-libs/gst/gl/gstglwindow.h +++ b/gst-libs/gst/gl/gstglwindow.h @@ -136,6 +136,8 @@ void gst_gl_window_send_message (GstGLWindow *window, GstGLWindowCB GstGLPlatform gst_gl_window_get_platform (GstGLWindow *window); +GST_DEBUG_CATEGORY_EXTERN (gst_gl_window_debug); + G_END_DECLS #endif /* __GST_GL_WINDOW_H__ */ diff --git a/gst-libs/gst/gl/wayland/Makefile.am b/gst-libs/gst/gl/wayland/Makefile.am new file mode 100644 index 0000000000..f0dcec92fc --- /dev/null +++ b/gst-libs/gst/gl/wayland/Makefile.am @@ -0,0 +1,27 @@ +## Process this file with automake to produce Makefile.in + +noinst_LTLIBRARIES = libgstgl-wayland.la + +libgstgl_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/gl +libgstglwaylandincludedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/gl/wayland + +libgstgl_wayland_la_SOURCES = \ + gstglwindow_wayland_egl.c \ + wayland_event_source.c + +libgstglwaylandinclude_HEADERS = \ + gstglwindow_wayland_egl.h \ + wayland_event_source.h + +libgstgl_wayland_la_CFLAGS = \ + $(GL_CFLAGS) \ + $(X_CFLAGS) \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(GST_CFLAGS) \ + -I$(top_srcdir)/gst-libs/gst/gl + +libgstgl_wayland_la_LDFLAGS = \ + $(GST_LIB_LDFLAGS) \ + $(GST_ALL_LDFLAGS) \ + $(GST_LT_LDFLAGS) diff --git a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c new file mode 100644 index 0000000000..0627198dc1 --- /dev/null +++ b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c @@ -0,0 +1,550 @@ +/* + * GStreamer + * Copyright (C) 2008 Julien Isorce + * Copyright (C) 2012 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. + */ + +#define GLIB_DISABLE_DEPRECATION_WARNINGS + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "wayland_event_source.h" + +#include "gstglwindow_wayland_egl.h" + +const gchar *WlEGLErrorString (); + +#define GST_CAT_DEFAULT gst_gl_window_wayland_egl_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +#define DEBUG_INIT \ + GST_DEBUG_CATEGORY_GET (GST_CAT_DEFAULT, "glwindow"); +#define gst_gl_window_wayland_egl_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstGLWindowWaylandEGL, gst_gl_window_wayland_egl, + GST_GL_TYPE_WINDOW, DEBUG_INIT); + +static guintptr gst_gl_window_wayland_egl_get_gl_context (GstGLWindow * window); +static gboolean gst_gl_window_wayland_egl_activate (GstGLWindow * window, + gboolean activate); +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_run (GstGLWindow * window); +static void gst_gl_window_wayland_egl_quit (GstGLWindow * window, + GstGLWindowCB callback, gpointer data); +static void gst_gl_window_wayland_egl_send_message (GstGLWindow * window, + GstGLWindowCB callback, gpointer data); +static void gst_gl_window_wayland_egl_destroy_context (GstGLWindowWaylandEGL * + window_egl); +static gboolean gst_gl_window_wayland_egl_create_context (GstGLWindowWaylandEGL + * window_egl, GstGLRendererAPI render_api, guintptr external_gl_context); + +static void gst_gl_window_wayland_egl_finalize (GObject * object); + +static void +handle_ping (void *data, struct wl_shell_surface *shell_surface, + uint32_t serial) +{ + wl_shell_surface_pong (shell_surface, serial); +} + +static void +handle_configure (void *data, struct wl_shell_surface *shell_surface, + uint32_t edges, int32_t width, int32_t height) +{ + GstGLWindowWaylandEGL *window_egl = data; + struct window window = window_egl->window; + + if (window.native) + wl_egl_window_resize (window.native, width, height, 0, 0); + + window.window_width = width; + window.window_height = height; +} + +static void +handle_popup_done (void *data, struct wl_shell_surface *shell_surface) +{ +} + +static const struct wl_shell_surface_listener shell_surface_listener = { + handle_ping, + handle_configure, + handle_popup_done +}; + +static gboolean +create_surface (GstGLWindowWaylandEGL * window_egl) +{ + struct display display = window_egl->display; + struct window window = window_egl->window; + EGLBoolean ret; + + window.surface = wl_compositor_create_surface (display.compositor); + window.shell_surface = wl_shell_get_shell_surface (display.shell, + window.surface); + + wl_shell_surface_add_listener (window.shell_surface, + &shell_surface_listener, window_egl); + + if (!window.window_width) + window.window_width = 320; + if (!window.window_height) + window.window_height = 240; + + window.native = + wl_egl_window_create (window.surface, window.window_width, + window.window_height); + window_egl->egl_surface = + eglCreateWindowSurface (window_egl->egl_display, window_egl->egl_config, + window.native, NULL); + + wl_shell_surface_set_title (window.shell_surface, "OpenGL Renderer"); + + ret = + eglMakeCurrent (window_egl->egl_display, window_egl->egl_surface, + window_egl->egl_surface, window_egl->egl_context); + + wl_shell_surface_set_toplevel (window.shell_surface); + handle_configure (window_egl, window.shell_surface, 0, + window_egl->window.window_width, window_egl->window.window_height); + + return ret == EGL_TRUE; +} + +static void +destroy_surface (GstGLWindowWaylandEGL * window_egl) +{ + if (window_egl->window.native) + wl_egl_window_destroy (window_egl->window.native); + + if (window_egl->window.shell_surface) + wl_shell_surface_destroy (window_egl->window.shell_surface); + + if (window_egl->window.surface) + wl_surface_destroy (window_egl->window.surface); + + if (window_egl->window.callback) + 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) +{ + struct display *d = data; + + 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 (strcmp(interface, "wl_seat") == 0) { + d->seat = wl_registry_bind(registry, name, &wl_seat_interface, 1); + wl_seat_add_listener(d->seat, &seat_listener, d); +*/ } 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) +{ + GObjectClass *object_class = (GObjectClass *) klass; + GstGLWindowClass *window_class = (GstGLWindowClass *) klass; + + window_class->get_gl_context = + GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_get_gl_context); + window_class->activate = + GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_activate); + window_class->set_window_handle = + 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->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); + window_class->send_message = + GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_send_message); + + object_class->finalize = gst_gl_window_wayland_egl_finalize; +} + +static void +gst_gl_window_wayland_egl_init (GstGLWindowWaylandEGL * window) +{ +} + +/* Must be called in the gl thread */ +GstGLWindowWaylandEGL * +gst_gl_window_wayland_egl_new (GstGLRendererAPI render_api, + guintptr external_gl_context) +{ + GstGLWindowWaylandEGL *window = + g_object_new (GST_GL_TYPE_WINDOW_WAYLAND_EGL, NULL); + + gst_gl_window_set_need_lock (GST_GL_WINDOW (window), FALSE); + + window->display.display = wl_display_connect (NULL); + g_assert (window->display.display); + + window->display.registry = wl_display_get_registry (window->display.display); + wl_registry_add_listener (window->display.registry, ®istry_listener, + &window->display); + + wl_display_dispatch (window->display.display); + +// init_egl(&display, window.opaque); + create_surface (window); +// init_gl(&window); + + window->display.cursor_surface = + wl_compositor_create_surface (window->display.compositor); + + window->wl_source = wayland_event_source_new (window->display.display); + window->main_context = g_main_context_new (); + window->loop = g_main_loop_new (window->main_context, FALSE); + + g_source_attach (window->wl_source, window->main_context); + + gst_gl_window_wayland_egl_create_context (window, render_api, + external_gl_context); + + return window; +} + +static void +gst_gl_window_wayland_egl_finalize (GObject * object) +{ + GstGLWindowWaylandEGL *window_egl; + + window_egl = GST_GL_WINDOW_WAYLAND_EGL (object); + + gst_gl_window_wayland_egl_destroy_context (window_egl); +// fini_egl(&display); + + 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); + + wl_display_flush (window_egl->display.display); + wl_display_disconnect (window_egl->display.display); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_gl_window_wayland_egl_create_context (GstGLWindowWaylandEGL * window_egl, + GstGLRendererAPI render_api, guintptr external_gl_context) +{ + EGLint config_attrib[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, 1, + EGL_GREEN_SIZE, 1, + EGL_BLUE_SIZE, 1, + EGL_ALPHA_SIZE, 1, + EGL_DEPTH_SIZE, 1, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + + EGLint context_attrib[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + EGLint majorVersion; + EGLint minorVersion; + EGLint numConfigs; + + window_egl->egl_display = + eglGetDisplay ((EGLNativeDisplayType) window_egl->display.display); + + if (eglInitialize (window_egl->egl_display, &majorVersion, &minorVersion)) + GST_DEBUG ("egl initialized: %d.%d", majorVersion, minorVersion); + else { + GST_DEBUG ("failed to initialize egl %ld, %s", + (gulong) window_egl->egl_display, WlEGLErrorString ()); + goto failure; + } + + if (!eglBindAPI (EGL_OPENGL_ES_API)) { + GST_WARNING ("failed to bind OpenGL|ES API"); + goto failure; + } + + if (eglChooseConfig (window_egl->egl_display, config_attrib, + &window_egl->egl_config, 1, &numConfigs)) + GST_DEBUG ("config set: %ld, %ld", (gulong) window_egl->egl_config, + (gulong) numConfigs); + else { + GST_DEBUG ("failed to set config %ld, %s", (gulong) window_egl->egl_display, + WlEGLErrorString ()); + goto failure; + } + + GST_DEBUG ("about to create gl context"); + + window_egl->egl_context = + eglCreateContext (window_egl->egl_display, window_egl->egl_config, + (EGLContext) external_gl_context, context_attrib); + + if (window_egl->egl_context != EGL_NO_CONTEXT) + GST_DEBUG ("gl context created: %ld", (gulong) window_egl->egl_context); + else { + GST_DEBUG ("failed to create glcontext %ld, %ld, %s", + (gulong) window_egl->egl_context, (gulong) window_egl->egl_display, + WlEGLErrorString ()); + goto failure; + } + + create_surface (window_egl); +/* window_egl->egl_surface = + eglCreateWindowSurface (window_egl->egl_display, window_egl->config, + (EGLNativeWindowType) window_wayland_egl->internal_win_id, NULL); + if (window_egl->egl_surface != EGL_NO_SURFACE) + GST_DEBUG ("surface created: %ld", (gulong) window_egl->egl_surface); + else { + GST_DEBUG ("failed to create surface %ld, %ld, %ld, %s", + (gulong) window_egl->egl_display, (gulong) window_egl->egl_surface, + (gulong) window_egl->egl_display, WlEGLErrorString ()); + goto failure; + } +*/ + + return TRUE; + +failure: + return FALSE; +} + +static void +gst_gl_window_wayland_egl_destroy_context (GstGLWindowWaylandEGL * window_egl) +{ + destroy_surface (window_egl); + + if (window_egl->egl_context) + eglDestroyContext (window_egl->egl_display, window_egl->egl_context); + + if (window_egl->egl_display) { + eglTerminate (window_egl->egl_display); + eglReleaseThread (); + } +} + +static gboolean +gst_gl_window_wayland_egl_activate (GstGLWindow * window, gboolean activate) +{ + gboolean result; + GstGLWindowWaylandEGL *window_egl; + + window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); + + GST_DEBUG ("activate:%s", activate ? "TRUE" : "FALSE"); + + if (activate) + result = eglMakeCurrent (window_egl->egl_display, window_egl->egl_surface, + window_egl->egl_surface, window_egl->egl_context); + else + result = eglMakeCurrent (window_egl->egl_display, EGL_NO_SURFACE, + EGL_NO_SURFACE, EGL_NO_CONTEXT); + + return result; +} + +static guintptr +gst_gl_window_wayland_egl_get_gl_context (GstGLWindow * window) +{ + return (guintptr) GST_GL_WINDOW_WAYLAND_EGL (window)->egl_context; +} + +static void +gst_gl_window_wayland_egl_swap_buffers (GstGLWindow * window) +{ + GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); + + eglSwapBuffers (window_egl->egl_display, window_egl->egl_surface); +} + +static void +gst_gl_window_wayland_egl_run (GstGLWindow * window) +{ + GstGLWindowWaylandEGL *window_egl; + + window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); + + GST_LOG ("starting main loop"); + g_main_loop_run (window_egl->loop); + GST_LOG ("exiting main loop"); +} + +static void +gst_gl_window_wayland_egl_quit (GstGLWindow * window, GstGLWindowCB callback, + gpointer data) +{ + GstGLWindowWaylandEGL *window_egl; + + window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); + + gst_gl_window_wayland_egl_send_message (window, callback, data); + + GST_LOG ("sending quit"); + + g_main_loop_quit (window_egl->loop); + + GST_LOG ("quit sent"); +} + +typedef struct _GstGLMessage +{ + GMutex lock; + GCond cond; + gboolean fired; + + GstGLWindowCB callback; + gpointer data; +} GstGLMessage; + +static gboolean +_run_message (GstGLMessage * message) +{ + g_mutex_lock (&message->lock); + + if (message->callback) + message->callback (message->data); + + message->fired = TRUE; + g_cond_signal (&message->cond); + g_mutex_unlock (&message->lock); + + return FALSE; +} + +static void +gst_gl_window_wayland_egl_send_message (GstGLWindow * window, + GstGLWindowCB callback, gpointer data) +{ + GstGLWindowWaylandEGL *window_egl; + GstGLMessage message; + + window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); + message.callback = callback; + message.data = data; + message.fired = FALSE; + g_mutex_init (&message.lock); + g_cond_init (&message.cond); + + g_mutex_lock (&message.lock); + + g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message, + &message); + + while (!message.fired) + g_cond_wait (&message.cond, &message.lock); + g_mutex_unlock (&message.lock); +} + +static void +gst_gl_window_wayland_egl_set_window_handle (GstGLWindow * window, + guintptr handle) +{ +} + +struct draw +{ + GstGLWindowWaylandEGL *window; + guint width, height; +}; + +static void +draw_cb (gpointer data) +{ + struct draw *draw_data = data; + GstGLWindow *window = GST_GL_WINDOW (draw_data->window); + + if (window->draw) + window->draw (window->draw_data); + + gst_gl_window_wayland_egl_swap_buffers (window); +} + +static void +gst_gl_window_wayland_egl_draw (GstGLWindow * window, guint width, guint height) +{ + struct draw draw_data; + + draw_data.window = GST_GL_WINDOW_WAYLAND_EGL (window); + draw_data.width = width; + draw_data.height = height; + + gst_gl_window_send_message (window, (GstGLWindowCB) draw_cb, &draw_data); +} + +const gchar * +WlEGLErrorString () +{ + EGLint nErr = eglGetError (); + switch (nErr) { + case EGL_SUCCESS: + return "EGL_SUCCESS"; + case EGL_BAD_DISPLAY: + return "EGL_BAD_DISPLAY"; + case EGL_NOT_INITIALIZED: + return "EGL_NOT_INITIALIZED"; + case EGL_BAD_ACCESS: + return "EGL_BAD_ACCESS"; + case EGL_BAD_ALLOC: + return "EGL_BAD_ALLOC"; + case EGL_BAD_ATTRIBUTE: + return "EGL_BAD_ATTRIBUTE"; + case EGL_BAD_CONFIG: + return "EGL_BAD_CONFIG"; + case EGL_BAD_CONTEXT: + return "EGL_BAD_CONTEXT"; + case EGL_BAD_CURRENT_SURFACE: + return "EGL_BAD_CURRENT_SURFACE"; + case EGL_BAD_MATCH: + return "EGL_BAD_MATCH"; + case EGL_BAD_NATIVE_PIXMAP: + return "EGL_BAD_NATIVE_PIXMAP"; + case EGL_BAD_NATIVE_WINDOW: + return "EGL_BAD_NATIVE_WINDOW"; + case EGL_BAD_PARAMETER: + return "EGL_BAD_PARAMETER"; + case EGL_BAD_SURFACE: + return "EGL_BAD_SURFACE"; + default: + return "unknown"; + } +} diff --git a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h new file mode 100644 index 0000000000..b57a525409 --- /dev/null +++ b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h @@ -0,0 +1,106 @@ +/* + * GStreamer + * Copyright (C) 2012 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_WINDOW_WAYLAND_EGL_H__ +#define __GST_GL_WINDOW_WAYLAND_EGL_H__ + +#include +#include +#include + +#include + +#include "gstglwindow.h" + +G_BEGIN_DECLS + +#define GST_GL_TYPE_WINDOW_WAYLAND_EGL (gst_gl_window_wayland_egl_get_type()) +#define GST_GL_WINDOW_WAYLAND_EGL(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_GL_TYPE_WINDOW_WAYLAND_EGL, GstGLWindowWaylandEGL)) +#define GST_GL_WINDOW_WAYLAND_EGL_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_GL_TYPE_WINDOW_WAYLAND_EGL, GstGLWindowWaylandEGLClass)) +#define GST_GL_IS_WINDOW_WAYLAND_EGL(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_GL_TYPE_WINDOW_WAYLAND_EGL)) +#define GST_GL_IS_WINDOW_WAYLAND_EGL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_GL_TYPE_WINDOW_WAYLAND_EGL)) +#define GST_GL_WINDOW_WAYLAND_EGL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_GL_TYPE_WINDOW_WAYLAND_EGL, GstGLWindowWaylandEGL_Class)) + +typedef struct _GstGLWindowWaylandEGL GstGLWindowWaylandEGL; +typedef struct _GstGLWindowWaylandEGLClass GstGLWindowWaylandEGLClass; + +struct window; + +struct display { + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_shell *shell; + struct wl_seat *seat; +/* struct wl_pointer *pointer; + struct wl_keyboard *keyboard;*/ + struct wl_shm *shm; + struct wl_cursor_theme *cursor_theme; + struct wl_cursor *default_cursor; + struct wl_surface *cursor_surface; + struct window *window; +}; + +struct window { + struct display *display; + + struct wl_egl_window *native; + struct wl_surface *surface; + struct wl_shell_surface *shell_surface; + struct wl_callback *callback; + int fullscreen, configured; + int window_width, window_height; +}; + +struct _GstGLWindowWaylandEGL { + /*< private >*/ + GstGLWindow parent; + + EGLContext egl_context; + EGLDisplay egl_display; + EGLSurface egl_surface; + EGLConfig egl_config; + + struct display display; + struct window window; + + GSource *wl_source; + GMainContext *main_context; + GMainLoop *loop; + + gpointer _reserved[GST_PADDING]; +}; + +struct _GstGLWindowWaylandEGLClass { + /*< private >*/ + GstGLWindowClass parent_class; + + /*< private >*/ + gpointer _reserved[GST_PADDING]; +}; + +GType gst_gl_window_wayland_egl_get_type (void); + +GstGLWindowWaylandEGL * gst_gl_window_wayland_egl_new (GstGLRendererAPI render_api, + guintptr external_gl_context); + +G_END_DECLS + +#endif /* __GST_GL_WINDOW_X11_H__ */ diff --git a/gst-libs/gst/gl/wayland/wayland_event_source.c b/gst-libs/gst/gl/wayland/wayland_event_source.c new file mode 100644 index 0000000000..509a799c34 --- /dev/null +++ b/gst-libs/gst/gl/wayland/wayland_event_source.c @@ -0,0 +1,125 @@ +/* + * GStreamer + * Copyright (C) 2010 Intel Corporation. + * Copyright (C) 2012 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. + * + * Authors: + * Matthew Allum + * Robert Bragg + * Kristian Høgsberg + */ + +/* code originally from clutter's wayland backend found here + * http://git.gnome.org/browse/clutter/tree/clutter/wayland/clutter-event-wayland.c + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "wayland_event_source.h" + +typedef struct _WaylandEventSource +{ + GSource source; + GPollFD pfd; + uint32_t mask; + struct wl_display *display; +} WaylandEventSource; + +static gboolean +wayland_event_source_prepare (GSource * base, gint * timeout) +{ + WaylandEventSource *source = (WaylandEventSource *) base; + gboolean retval; + + *timeout = -1; + + /* We have to add/remove the GPollFD if we want to update our + * poll event mask dynamically. Instead, let's just flush all + * writes on idle */ + wl_display_flush (source->display); + + retval = FALSE; //clutter_events_pending (); + + return retval; +} + +static gboolean +wayland_event_source_check (GSource * base) +{ + WaylandEventSource *source = (WaylandEventSource *) base; + gboolean retval; + + retval = source->pfd.revents; // || clutter_events_pending(); + + return retval; +} + +static gboolean +wayland_event_source_dispatch (GSource * base, + GSourceFunc callback, gpointer data) +{ + WaylandEventSource *source = (WaylandEventSource *) base; +// ClutterEvent *event; + + if (source->pfd.revents) { + wl_display_roundtrip (source->display); + source->pfd.revents = 0; + } + + if (callback) + callback (data); + +#if 0 + event = clutter_event_get (); + + if (event) { + /* forward the event into clutter for emission etc. */ + clutter_do_event (event); + clutter_event_free (event); + } +#endif + return TRUE; +} + +static GSourceFuncs wayland_event_source_funcs = { + wayland_event_source_prepare, + wayland_event_source_check, + wayland_event_source_dispatch, + NULL +}; + +GSource * +wayland_event_source_new (struct wl_display *display) +{ + WaylandEventSource *source; + + source = (WaylandEventSource *) + g_source_new (&wayland_event_source_funcs, sizeof (WaylandEventSource)); + source->display = display; + source->pfd.fd = wl_display_get_fd (display); + source->pfd.events = G_IO_IN | G_IO_ERR; + g_source_add_poll (&source->source, &source->pfd); + + return &source->source; +} diff --git a/gst-libs/gst/gl/wayland/wayland_event_source.h b/gst-libs/gst/gl/wayland/wayland_event_source.h new file mode 100644 index 0000000000..e70d5681c5 --- /dev/null +++ b/gst-libs/gst/gl/wayland/wayland_event_source.h @@ -0,0 +1,39 @@ +/* + * GStreamer + * Copyright (C) 2011 Intel Corporation. + * Copyright (C) 2012 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. + * Authors: + * Robert Bragg + */ + +/* code originally from clutter's wayland backend found here + * http://git.gnome.org/browse/clutter/tree/clutter/wayland/clutter-event-wayland.h + */ + +#ifndef __WAYLAND_EVENT_SOURCE_H__ +#define __WAYLAND_EVENT_SOURCE_H__ + +#include +//#include + +#include + +GSource * +wayland_event_source_new (struct wl_display *display); + +#endif /* __WAYLAND_EVENT_SOURCE_H__ */