From 894035f0d7f03159e05050f44441af6d900aaa85 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Mon, 17 Mar 2014 10:56:39 +0100 Subject: [PATCH] gl: Add EGLDisplay display subclass --- gst-libs/gst/gl/Makefile.am | 49 ++++++----- gst-libs/gst/gl/egl/gstglcontext_egl.c | 53 ++++++------ gst-libs/gst/gl/egl/gstgldisplay_egl.c | 150 +++++++++++++++++++++++++++++++++ gst-libs/gst/gl/egl/gstgldisplay_egl.h | 73 ++++++++++++++++ gst-libs/gst/gl/gstgldisplay.c | 7 ++ gst-libs/gst/gl/gstgldisplay.h | 4 +- 6 files changed, 286 insertions(+), 50 deletions(-) create mode 100644 gst-libs/gst/gl/egl/gstgldisplay_egl.c create mode 100644 gst-libs/gst/gl/egl/gstgldisplay_egl.h diff --git a/gst-libs/gst/gl/Makefile.am b/gst-libs/gst/gl/Makefile.am index 8ae13ad..bc47bef 100644 --- a/gst-libs/gst/gl/Makefile.am +++ b/gst-libs/gst/gl/Makefile.am @@ -25,9 +25,32 @@ libgstgl_@GST_API_VERSION@_la_SOURCES = \ gstglutils.c \ gstglframebuffer.c +libgstgl_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/gl +libgstgl_@GST_API_VERSION@include_HEADERS = \ + gstglwindow.h \ + gstgldisplay.h \ + gstglcontext.h \ + gstglmemory.h \ + gstglbufferpool.h \ + gstgles2.h \ + gstglfilter.h \ + gstglmixer.h \ + gstglmixerpad.h \ + gstglshadervariables.h \ + gstglshader.h \ + gstgldownload.h \ + gstglupload.h \ + gstglapi.h \ + gstglfeature.h \ + gstglutils.h \ + gstglframebuffer.h \ + gstgl_fwd.h \ + gl.h + libgstgl_@GST_API_VERSION@_la_LIBADD = \ $(GST_PLUGINS_BASE_LIBS) \ -lgstvideo-$(GST_API_VERSION) \ + -lgstegl-$(GST_API_VERSION) \ $(GST_BASE_LIBS) \ $(GST_LIBS) \ $(GL_LIBS) @@ -63,32 +86,12 @@ libgstgl_@GST_API_VERSION@_la_LIBADD += android/libgstgl-android.la endif if USE_EGL -libgstgl_@GST_API_VERSION@_la_SOURCES += egl/gstglcontext_egl.c +libgstgl_@GST_API_VERSION@_la_SOURCES += egl/gstglcontext_egl.c \ + egl/gstgldisplay_egl.c +libgstgl_@GST_API_VERSION@include_HEADERS += egl/gstgldisplay_egl.h noinst_HEADERS += egl/gstglcontext_egl.h endif -libgstgl_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/gl -libgstgl_@GST_API_VERSION@include_HEADERS = \ - gstglwindow.h \ - gstgldisplay.h \ - gstglcontext.h \ - gstglmemory.h \ - gstglbufferpool.h \ - gstgles2.h \ - gstglfilter.h \ - gstglmixer.h \ - gstglmixerpad.h \ - gstglshadervariables.h \ - gstglshader.h \ - gstgldownload.h \ - gstglupload.h \ - gstglapi.h \ - gstglfeature.h \ - gstglutils.h \ - gstglframebuffer.h \ - gstgl_fwd.h \ - gl.h - nodist_libgstgl_@GST_API_VERSION@include_HEADERS = \ $(built_header_configure) diff --git a/gst-libs/gst/gl/egl/gstglcontext_egl.c b/gst-libs/gst/gl/egl/gstglcontext_egl.c index 197cd1c..a7b8e09 100644 --- a/gst-libs/gst/gl/egl/gstglcontext_egl.c +++ b/gst-libs/gst/gl/egl/gstglcontext_egl.c @@ -209,7 +209,7 @@ gst_gl_context_egl_create_context (GstGLContext * context, { GstGLContextEGL *egl; GstGLWindow *window = NULL; - EGLNativeWindowType window_handle; + EGLNativeWindowType window_handle = (EGLNativeWindowType) 0; gint i = 0; EGLint context_attrib[3]; EGLint majorVersion; @@ -217,7 +217,6 @@ gst_gl_context_egl_create_context (GstGLContext * context, const gchar *egl_exts; gboolean need_surface = TRUE; guintptr external_gl_context = 0; - guintptr native_display; GstGLDisplay *display; egl = GST_GL_CONTEXT_EGL (context); @@ -240,24 +239,29 @@ gst_gl_context_egl_create_context (GstGLContext * context, } display = gst_gl_context_get_display (context); - native_display = gst_gl_display_get_handle (display); - - if (!native_display) { - GstGLWindow *window = NULL; - GST_WARNING ("Failed to get a global display handle, falling back to " - "per-window display handles. Context sharing may not work"); - - if (other_context) - window = gst_gl_context_get_window (other_context); - if (!window) - window = gst_gl_context_get_window (context); - if (window) { - native_display = gst_gl_window_get_display (window); - gst_object_unref (window); + + if (display->type == GST_GL_DISPLAY_TYPE_EGL) { + egl->egl_display = (EGLDisplay) gst_gl_display_get_handle (display); + } else { + guintptr native_display = gst_gl_display_get_handle (display); + + if (!native_display) { + GstGLWindow *window = NULL; + GST_WARNING ("Failed to get a global display handle, falling back to " + "per-window display handles. Context sharing may not work"); + + if (other_context) + window = gst_gl_context_get_window (other_context); + if (!window) + window = gst_gl_context_get_window (context); + if (window) { + native_display = gst_gl_window_get_display (window); + gst_object_unref (window); + } } - } - egl->egl_display = eglGetDisplay ((EGLNativeDisplayType) native_display); + egl->egl_display = eglGetDisplay ((EGLNativeDisplayType) native_display); + } gst_object_unref (display); if (eglInitialize (egl->egl_display, &majorVersion, &minorVersion)) { @@ -358,8 +362,9 @@ gst_gl_context_egl_create_context (GstGLContext * context, #endif } - window_handle = - (EGLNativeWindowType) gst_gl_window_get_window_handle (window); + if (window) + window_handle = + (EGLNativeWindowType) gst_gl_window_get_window_handle (window); if (window_handle) { egl->egl_surface = @@ -398,7 +403,8 @@ gst_gl_context_egl_create_context (GstGLContext * context, } } - gst_object_unref (window); + if (window) + gst_object_unref (window); return TRUE; @@ -424,10 +430,7 @@ gst_gl_context_egl_destroy_context (GstGLContext * context) if (egl->egl_context) eglDestroyContext (egl->egl_display, egl->egl_context); - if (egl->egl_display) { - eglTerminate (egl->egl_display); - eglReleaseThread (); - } + eglReleaseThread (); } static gboolean diff --git a/gst-libs/gst/gl/egl/gstgldisplay_egl.c b/gst-libs/gst/gl/egl/gstgldisplay_egl.c new file mode 100644 index 0000000..36c7211 --- /dev/null +++ b/gst-libs/gst/gl/egl/gstgldisplay_egl.c @@ -0,0 +1,150 @@ +/* + * GStreamer + * Copyright (C) 2014 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 (GstGLDisplayEGL, gst_gl_display_egl, GST_TYPE_GL_DISPLAY); + +static void gst_gl_display_egl_finalize (GObject * object); +static guintptr gst_gl_display_egl_get_handle (GstGLDisplay * display); + +static void +gst_gl_display_egl_class_init (GstGLDisplayEGLClass * klass) +{ + GST_GL_DISPLAY_CLASS (klass)->get_handle = + GST_DEBUG_FUNCPTR (gst_gl_display_egl_get_handle); + + G_OBJECT_CLASS (klass)->finalize = gst_gl_display_egl_finalize; +} + +static void +gst_gl_display_egl_init (GstGLDisplayEGL * display_egl) +{ + GstGLDisplay *display = (GstGLDisplay *) display_egl; + + display->type = GST_GL_DISPLAY_TYPE_EGL; + display_egl->foreign_display = FALSE; +} + +static void +gst_gl_display_egl_finalize (GObject * object) +{ + GstGLDisplayEGL *display_egl = GST_GL_DISPLAY_EGL (object); + + if (display_egl->gst_display) { + gst_egl_display_unref (display_egl->gst_display); + display_egl->gst_display = NULL; + } else if (display_egl->display && !display_egl->foreign_display) { + eglTerminate (display_egl->display); + display_egl->display = NULL; + } + + G_OBJECT_CLASS (gst_gl_display_egl_parent_class)->finalize (object); +} + +/** + * gst_gl_display_egl_new: + * @name: (allow-none): a display name + * + * Create a new #GstGLDisplayEGL from the x11 display name. See XOpenDisplay() + * for details on what is a valid name. + * + * Returns: (transfer full): a new #GstGLDisplayEGL or %NULL + */ +GstGLDisplayEGL * +gst_gl_display_egl_new (void) +{ + GstGLDisplayEGL *ret; + + GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay"); + + ret = g_object_new (GST_TYPE_GL_DISPLAY_EGL, NULL); + ret->display = eglGetDisplay ((EGLNativeDisplayType) EGL_DEFAULT_DISPLAY); + + if (!ret->display) { + GST_ERROR ("Failed to open EGL display connection"); + } + + return ret; +} + +/** + * gst_gl_display_egl_new_with_display: + * @display: an existing, x11 display + * + * Creates a new display connection from a X11 Display. + * + * Returns: (transfer full): a new #GstGLDisplayEGL + */ +GstGLDisplayEGL * +gst_gl_display_egl_new_with_egl_display (EGLDisplay * display) +{ + GstGLDisplayEGL *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_EGL, NULL); + + ret->display = display; + ret->foreign_display = TRUE; + + return ret; +} + +/** + * gst_gl_display_egl_new_with_display: + * @display: an existing, x11 display + * + * Creates a new display connection from a X11 Display. + * + * Returns: (transfer full): a new #GstGLDisplayEGL + */ +GstGLDisplayEGL * +gst_gl_display_egl_new_with_gst_egl_display (GstEGLDisplay * display) +{ + GstGLDisplayEGL *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_EGL, NULL); + + ret->gst_display = gst_egl_display_ref (display); + ret->display = gst_egl_display_get (display); + ret->foreign_display = TRUE; + + return ret; +} + +static guintptr +gst_gl_display_egl_get_handle (GstGLDisplay * display) +{ + return (guintptr) GST_GL_DISPLAY_EGL (display)->display; +} diff --git a/gst-libs/gst/gl/egl/gstgldisplay_egl.h b/gst-libs/gst/gl/egl/gstgldisplay_egl.h new file mode 100644 index 0000000..bd188d5 --- /dev/null +++ b/gst-libs/gst/gl/egl/gstgldisplay_egl.h @@ -0,0 +1,73 @@ +/* + * GStreamer + * Copyright (C) 2014 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_EGL_H__ +#define __GST_GL_DISPLAY_EGL_H__ + +#include + +#include + +#include +#include + +G_BEGIN_DECLS + +GType gst_gl_display_egl_get_type (void); + +#define GST_TYPE_GL_DISPLAY_EGL (gst_gl_display_egl_get_type()) +#define GST_GL_DISPLAY_EGL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_DISPLAY_EGL,GstGLDisplayEGL)) +#define GST_GL_DISPLAY_EGL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_GL_DISPLAY_EGL,GstGLDisplayEGLClass)) +#define GST_IS_GL_DISPLAY_EGL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_DISPLAY_EGL)) +#define GST_IS_GL_DISPLAY_EGL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_GL_DISPLAY_EGL)) +#define GST_GL_DISPLAY_EGL_CAST(obj) ((GstGLDisplayEGL*)(obj)) + +typedef struct _GstGLDisplayEGL GstGLDisplayEGL; +typedef struct _GstGLDisplayEGLClass GstGLDisplayEGLClass; + +/** + * GstGLDisplayEGL: + * + * the contents of a #GstGLDisplayEGL are private and should only be accessed + * through the provided API + */ +struct _GstGLDisplayEGL +{ + GstGLDisplay parent; + + /* */ + GstEGLDisplay *gst_display; + EGLDisplay *display; + + gboolean foreign_display; +}; + +struct _GstGLDisplayEGLClass +{ + GstGLDisplayClass object_class; +}; + +GstGLDisplayEGL *gst_gl_display_egl_new (void); +GstGLDisplayEGL *gst_gl_display_egl_new_with_egl_display (EGLDisplay *display); +GstGLDisplayEGL *gst_gl_display_egl_new_with_gst_egl_display (GstEGLDisplay *display); + +G_END_DECLS + +#endif /* __GST_GL_DISPLAY_EGL_H__ */ diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c index 656eb83..f71f80b 100644 --- a/gst-libs/gst/gl/gstgldisplay.c +++ b/gst-libs/gst/gl/gstgldisplay.c @@ -42,6 +42,9 @@ #if GST_GL_HAVE_WINDOW_X11 #include #endif +#if GST_GL_HAVE_PLATFORM_EGL +#include +#endif GST_DEBUG_CATEGORY_STATIC (gst_context); GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug); @@ -128,6 +131,10 @@ gst_gl_display_new (void) if (!display && (!user_choice || g_strstr_len (user_choice, 3, "x11"))) display = GST_GL_DISPLAY (gst_gl_display_x11_new (NULL)); #endif +#if GST_GL_HAVE_PLATFORM_EGL + if (!display && (!user_choice || g_strstr_len (user_choice, 3, "egl"))) + display = GST_GL_DISPLAY (gst_gl_display_egl_new ()); +#endif if (!display) { /* subclass returned a NULL window */ GST_WARNING ("Could not create display. user specified %s, creating dummy", diff --git a/gst-libs/gst/gl/gstgldisplay.h b/gst-libs/gst/gl/gstgldisplay.h index 0145545..0d451f9 100644 --- a/gst-libs/gst/gl/gstgldisplay.h +++ b/gst-libs/gst/gl/gstgldisplay.h @@ -47,8 +47,8 @@ typedef enum GST_GL_DISPLAY_TYPE_WAYLAND = (1 << 1), GST_GL_DISPLAY_TYPE_COCOA = (1 << 2), GST_GL_DISPLAY_TYPE_WIN32 = (1 << 3), - GST_GL_DISPLAY_TYPE_ANDROID = (1 << 4), - GST_GL_DISPLAY_TYPE_DISPMANX = (1 << 5), + GST_GL_DISPLAY_TYPE_DISPMANX = (1 << 4), + GST_GL_DISPLAY_TYPE_EGL = (1 << 5), GST_GL_DISPLAY_TYPE_ANY = G_MAXUINT32 } GstGLDisplayType; -- 2.7.4