gl/egl/display: Add support EGLDevice display type
authorSeungha Yang <seungha.yang@navercorp.com>
Thu, 4 Apr 2019 08:41:13 +0000 (17:41 +0900)
committerMatthew Waters <matthew@centricular.com>
Wed, 21 Aug 2019 05:19:46 +0000 (05:19 +0000)
Simple addition for supporting EXT_platform_device typed display.
It's a kind of special display type (part of EGL specification)
which has no window at all.
To use EGLDevice explicitly, set environment "GST_GL_WINDOW=egl-device"

See also https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_platform_device.txt

docs/meson.build
gst-libs/gst/gl/Makefile.am
gst-libs/gst/gl/egl/Makefile.am
gst-libs/gst/gl/egl/gstglcontext_egl.c
gst-libs/gst/gl/egl/gstgldisplay_egl.c
gst-libs/gst/gl/egl/gstgldisplay_egl_device.c [new file with mode: 0644]
gst-libs/gst/gl/egl/gstgldisplay_egl_device.h [new file with mode: 0644]
gst-libs/gst/gl/gstgldisplay.c
gst-libs/gst/gl/gstgldisplay.h
gst-libs/gst/gl/meson.build

index c4b5fe4..a285f19 100644 (file)
@@ -98,6 +98,7 @@ if build_gstgl
       join_paths('../gst-libs/gst', 'gl', 'egl', 'gstegl.[ch]'),
       join_paths('../gst-libs/gst', 'gl', 'egl', 'gsteglimage.[ch]'),
       join_paths('../gst-libs/gst', 'gl', 'egl', 'gstgldisplay_egl.[ch]'),
+      join_paths('../gst-libs/gst', 'gl', 'egl', 'gstgldisplay_egl_device.[ch]'),
       join_paths('../gst-libs/gst', 'gl', 'egl', 'gstglmemoryegl.[ch]'),
       join_paths('../gst-libs/gst', 'gl', 'x11', 'gstgldisplay_x11.[ch]'),
       join_paths('../gst-libs/gst', 'gl', 'wayland', 'gstgldisplay_wayland.[ch]'),
index ffe70e8..7977748 100644 (file)
@@ -149,7 +149,9 @@ if USE_EGL
 SUBDIRS += egl
 libgstgl_@GST_API_VERSION@_la_LIBADD += egl/libgstgl-egl.la
 gstgl_gir_headers += egl/gstgldisplay_egl.h
+gstgl_gir_headers += egl/gstgldisplay_egl_device.h
 gstgl_gir_sources += egl/gstgldisplay_egl.c
+gstgl_gir_sources += egl/gstgldisplay_egl_device.c
 endif
 
 configexecincludedir = $(libdir)/gstreamer-@GST_API_VERSION@/include/gst/gl
index a22be8b..53e5b14 100644 (file)
@@ -7,7 +7,8 @@ libgstgl_egl_la_SOURCES = \
        gstglcontext_egl.c \
        gstglmemoryegl.c \
        gsteglimage.c \
-       gstegl.c
+       gstegl.c \
+       gstgldisplay_egl_device.c
 
 noinst_HEADERS = \
        gstglcontext_egl.h
@@ -17,7 +18,8 @@ libgstgl_eglinclude_HEADERS = \
        gstgldisplay_egl.h \
        gstglmemoryegl.h \
        gsteglimage.h \
-       gstegl.h
+       gstegl.h \
+       gstgldisplay_egl_device.h
 
 libgstgl_egl_la_CFLAGS = \
        -I$(top_srcdir)/gst-libs \
index ae992c8..4917530 100644 (file)
@@ -409,6 +409,16 @@ gst_gl_context_egl_choose_config (GstGLContextEGL * egl, GstGLAPI gl_api,
   EGLint config_attrib[20];
   EGLint egl_api = 0;
   EGLBoolean ret = EGL_FALSE;
+  EGLint surface_type = EGL_WINDOW_BIT;
+  GstGLWindow *window;
+
+  window = gst_gl_context_get_window (GST_GL_CONTEXT (egl));
+
+  if (!window || !gst_gl_window_has_output_surface (window)) {
+    GST_INFO_OBJECT (egl,
+        "gl window has no output surface, use pixel buffer surfaces");
+    surface_type = EGL_PBUFFER_BIT;
+  }
 
   create_context =
       gst_gl_check_extension ("EGL_KHR_create_context", egl->egl_exts);
@@ -432,7 +442,7 @@ gst_gl_context_egl_choose_config (GstGLContextEGL * egl, GstGLAPI gl_api,
     egl_api = EGL_OPENGL_BIT;
 
   config_attrib[i++] = EGL_SURFACE_TYPE;
-  config_attrib[i++] = EGL_WINDOW_BIT;
+  config_attrib[i++] = surface_type;
   config_attrib[i++] = EGL_RENDERABLE_TYPE;
   config_attrib[i++] = egl_api;
 #if defined(USE_EGL_RPI) && GST_GL_HAVE_WINDOW_WAYLAND
index 89aaca3..9961ca0 100644 (file)
@@ -56,6 +56,9 @@ GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug);
 #ifndef EGL_PLATFORM_ANDROID
 #define EGL_PLATFORM_ANDROID 0x3141
 #endif
+#ifndef EGL_PLATFORM_DEVICE_EXT
+#define EGL_PLATFORM_DEVICE_EXT 0x313F
+#endif
 
 typedef EGLDisplay (*_gst_eglGetPlatformDisplay_type) (EGLenum platform,
     void *native_display, const EGLint * attrib_list);
@@ -125,6 +128,8 @@ gst_gl_display_egl_get_from_native (GstGLDisplayType type, guintptr display)
   g_return_val_if_fail ((type != GST_GL_DISPLAY_TYPE_ANY && display != 0)
       || (type == GST_GL_DISPLAY_TYPE_ANY && display == 0), EGL_NO_DISPLAY);
 
+  GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay");
+
   /* given an EGLDisplay already */
   if (type == GST_GL_DISPLAY_TYPE_EGL)
     return (gpointer) display;
@@ -175,6 +180,14 @@ gst_gl_display_egl_get_from_native (GstGLDisplayType type, guintptr display)
         NULL);
   }
 #endif
+  if (ret == EGL_NO_DISPLAY && (type & GST_GL_DISPLAY_TYPE_EGL_DEVICE) &&
+      (gst_gl_check_extension ("EGL_EXT_device_base", egl_exts) &&
+          gst_gl_check_extension ("EGL_EXT_platform_device", egl_exts))) {
+    ret =
+        _gst_eglGetPlatformDisplay (EGL_PLATFORM_DEVICE_EXT, (gpointer) display,
+        NULL);
+  }
+
   /* android only has one winsys/display connection */
 
   if (ret != EGL_NO_DISPLAY)
diff --git a/gst-libs/gst/gl/egl/gstgldisplay_egl_device.c b/gst-libs/gst/gl/egl/gstgldisplay_egl_device.c
new file mode 100644 (file)
index 0000000..3db8253
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * GStreamer
+ * Copyright (C) 2014 Matthew Waters <ystreet00@gmail.com>
+ * Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
+ *
+ * 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.
+ */
+
+/**
+ * SECTION:gstgldisplay_egl_device
+ * @short_description: EGL EGLDeviceEXT object
+ * @title: GstGLDisplayEGLDevice
+ * @see_also: #GstGLDisplay, #GstGLDisplayEGL
+ *
+ * #GstGLDisplayEGLDevice represents a `EGLDeviceEXT` handle created internally
+ * (gst_gl_display_egl_device_new()) or wrapped by the application
+ * (gst_gl_display_egl_device_new_with_egl_device())
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstgldisplay_egl.h"
+#include "gstgldisplay_egl_device.h"
+
+#include <gst/gl/gstglfeature.h>
+
+#include "gstegl.h"
+#include "gstglmemoryegl.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug);
+#define GST_CAT_DEFAULT gst_gl_display_debug
+
+typedef EGLBoolean (*eglQueryDevicesEXT_type) (EGLint max_devices,
+    EGLDeviceEXT * devices, EGLint * num_devices);
+
+G_DEFINE_TYPE (GstGLDisplayEGLDevice, gst_gl_display_egl_device,
+    GST_TYPE_GL_DISPLAY);
+
+static guintptr gst_gl_display_egl_device_get_handle (GstGLDisplay * display);
+
+static void
+gst_gl_display_egl_device_class_init (GstGLDisplayEGLDeviceClass * klass)
+{
+  GstGLDisplayClass *display_class = GST_GL_DISPLAY_CLASS (klass);
+
+  display_class->get_handle =
+      GST_DEBUG_FUNCPTR (gst_gl_display_egl_device_get_handle);
+}
+
+static void
+gst_gl_display_egl_device_init (GstGLDisplayEGLDevice * self)
+{
+  GstGLDisplay *display = GST_GL_DISPLAY (self);
+
+  display->type = GST_GL_DISPLAY_TYPE_EGL_DEVICE;
+
+  gst_gl_memory_egl_init_once ();
+}
+
+static guintptr
+gst_gl_display_egl_device_get_handle (GstGLDisplay * display)
+{
+  GstGLDisplayEGLDevice *self = GST_GL_DISPLAY_EGL_DEVICE (display);
+
+  return (guintptr) self->device;
+}
+
+/**
+ * gst_gl_display_egl_device_new:
+ * @device_index: the index of device to use
+ *
+ * Create a new #GstGLDisplayEGLDevice with an EGLDevice supported device
+ *
+ * Returns: (transfer full): a new #GstGLDisplayEGLDevice or %NULL
+ *
+ * Since: 1.18
+ */
+GstGLDisplayEGLDevice *
+gst_gl_display_egl_device_new (guint device_index)
+{
+  GstGLDisplayEGLDevice *ret;
+  eglQueryDevicesEXT_type query_device_func;
+  EGLint num_devices = 0;
+  EGLDeviceEXT *device_list;
+
+  GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay");
+
+  query_device_func =
+      (eglQueryDevicesEXT_type) eglGetProcAddress ("eglQueryDevicesEXT");
+
+  if (!query_device_func) {
+    GST_ERROR ("eglQueryDevicesEXT is unavailable");
+    return NULL;
+  }
+
+  if (query_device_func (0, NULL, &num_devices) == EGL_FALSE) {
+    GST_ERROR ("eglQueryDevicesEXT fail");
+    return NULL;
+  } else if (num_devices < 1) {
+    GST_ERROR ("no EGLDevice supported device");
+    return NULL;
+  }
+
+  if (num_devices <= device_index) {
+    GST_ERROR ("requested index %d exceeds the number of devices %d",
+        device_index, num_devices);
+    return NULL;
+  }
+
+  device_list = g_alloca (sizeof (EGLDeviceEXT) * num_devices);
+  query_device_func (num_devices, device_list, &num_devices);
+
+  ret = g_object_new (GST_TYPE_GL_DISPLAY_EGL_DEVICE, NULL);
+  gst_object_ref_sink (ret);
+
+  ret->device = device_list[device_index];
+
+  return ret;
+}
+
+/**
+ * gst_gl_display_egl_device_new_with_egl_device:
+ * @device: an existing EGLDeviceEXT
+ *
+ * Creates a new #GstGLDisplayEGLDevice with EGLDeviceEXT .
+ * The @device must be created using EGLDevice enumeration.
+ *
+ * Returns: (transfer full): a new #GstGLDisplayEGLDevice
+ *
+ * Since: 1.18
+ */
+GstGLDisplayEGLDevice *
+gst_gl_display_egl_device_new_with_egl_device (gpointer device)
+{
+  GstGLDisplayEGLDevice *ret;
+
+  g_return_val_if_fail (device != NULL, NULL);
+
+  GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay");
+
+  ret = g_object_new (GST_TYPE_GL_DISPLAY_EGL_DEVICE, NULL);
+  gst_object_ref_sink (ret);
+
+  ret->device = device;
+
+  return ret;
+}
diff --git a/gst-libs/gst/gl/egl/gstgldisplay_egl_device.h b/gst-libs/gst/gl/egl/gstgldisplay_egl_device.h
new file mode 100644 (file)
index 0000000..ab1aefa
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * GStreamer
+ * Copyright (C) 2014 Matthew Waters <ystreet00@gmail.com>
+ * Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
+ *
+ * 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_DEVICE_H__
+#define __GST_GL_DISPLAY_EGL_DEVICE_H__
+
+#include <gst/gl/gstgldisplay.h>
+
+G_BEGIN_DECLS
+
+GST_GL_API
+GType gst_gl_display_egl_device_get_type (void);
+
+#define GST_TYPE_GL_DISPLAY_EGL_DEVICE             (gst_gl_display_egl_device_get_type())
+#define GST_GL_DISPLAY_EGL_DEVICE(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_DISPLAY_EGL_DEVICE,GstGLDisplayEGLDevice))
+#define GST_GL_DISPLAY_EGL_DEVICE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_GL_DISPLAY_EGL_DEVICE,GstGLDisplayEGLDeviceClass))
+#define GST_IS_GL_DISPLAY_EGL_DEVICE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_DISPLAY_EGL_DEVICE))
+#define GST_IS_GL_DISPLAY_EGL_DEVICE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_GL_DISPLAY_EGL_DEVICE))
+#define GST_GL_DISPLAY_EGL_DEVICE_CAST(obj)        ((GstGLDisplayEGLDevice*)(obj))
+
+typedef struct _GstGLDisplayEGLDevice GstGLDisplayEGLDevice;
+typedef struct _GstGLDisplayEGLDeviceClass GstGLDisplayEGLDeviceClass;
+
+/**
+ * GstGLDisplayEGLDevice:
+ *
+ * the contents of a #GstGLDisplayEGLDevice are private and should only be accessed
+ * through the provided API
+ *
+ * Since: 1.18
+ */
+struct _GstGLDisplayEGLDevice
+{
+  GstGLDisplay parent;
+
+  gpointer device;
+
+  gpointer _padding[GST_PADDING];
+};
+
+/**
+ * GstGLDisplayEGLDeviceClass:
+ *
+ * Opaque #GstGLDisplayEGLDeviceClass struct
+ *
+ * Since: 1.18
+ */
+struct _GstGLDisplayEGLDeviceClass
+{
+  GstGLDisplayClass object_class;
+
+  gpointer _padding[GST_PADDING];
+};
+
+GST_GL_API
+GstGLDisplayEGLDevice *gst_gl_display_egl_device_new (guint device_index);
+
+GST_GL_API
+GstGLDisplayEGLDevice *gst_gl_display_egl_device_new_with_egl_device (gpointer device);
+
+
+G_END_DECLS
+
+#endif /* __GST_GL_DISPLAY_EGL_DEVICE_H__ */
index 6256ec6..ba11328 100644 (file)
@@ -67,6 +67,7 @@
 #endif
 #if GST_GL_HAVE_PLATFORM_EGL
 #include <gst/gl/egl/gstgldisplay_egl.h>
+#include <gst/gl/egl/gstgldisplay_egl_device.h>
 #include <gst/gl/egl/gsteglimage.h>
 #include <gst/gl/egl/gstglmemoryegl.h>
 #endif
@@ -321,9 +322,14 @@ gst_gl_display_new (void)
   }
 #endif
 #if GST_GL_HAVE_PLATFORM_EGL
+  if (!display && (user_choice && g_strstr_len (user_choice, 10, "egl-device"))) {
+    display = GST_GL_DISPLAY (gst_gl_display_egl_device_new (0));
+  }
+
   if (!display && (!platform_choice
-          || g_strstr_len (platform_choice, 3, "egl")))
+          || g_strstr_len (platform_choice, 3, "egl"))) {
     display = GST_GL_DISPLAY (gst_gl_display_egl_new ());
+  }
 #endif
   if (!display) {
     GST_INFO ("Could not create platform/winsys display. user specified %s "
index fec528b..c9c5d7d 100644 (file)
@@ -50,6 +50,7 @@ GType gst_gl_display_get_type (void);
  * @GST_GL_DISPLAY_TYPE_EGL: EGL display
  * @GST_GL_DISPLAY_TYPE_VIV_FB: Vivante Framebuffer display
  * @GST_GL_DISPLAY_TYPE_GBM: Mesa3D GBM display
+ * @GST_GL_DISPLAY_TYPE_EGL_DEVICE: EGLDevice display (Since: 1.18)
  * @GST_GL_DISPLAY_TYPE_ANY: any display type
  */
 typedef enum
@@ -63,6 +64,7 @@ typedef enum
   GST_GL_DISPLAY_TYPE_EGL = (1 << 5),
   GST_GL_DISPLAY_TYPE_VIV_FB = (1 << 6),
   GST_GL_DISPLAY_TYPE_GBM = (1 << 7),
+  GST_GL_DISPLAY_TYPE_EGL_DEVICE = (1 << 8),
 
   GST_GL_DISPLAY_TYPE_ANY = G_MAXUINT32
 } GstGLDisplayType;
index 4aeb559..a503494 100644 (file)
@@ -488,12 +488,14 @@ if need_platform_egl != 'no'
       'egl/gstglcontext_egl.c',
       'egl/gstgldisplay_egl.c',
       'egl/gstglmemoryegl.c',
+      'egl/gstgldisplay_egl_device.c',
     ]
     gl_egl_headers += [
       'egl/gstegl.h',
       'egl/gsteglimage.h',
       'egl/gstgldisplay_egl.h',
       'egl/gstglmemoryegl.h',
+      'egl/gstgldisplay_egl_device.h',
     ]
     gl_platform_deps += egl_dep
     glconf.set10('GST_GL_HAVE_PLATFORM_EGL', 1)