3 * Copyright (C) 2014 Matthew Waters <ystreet00@gmail.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
25 #include <gst/gl/egl/gstgldisplay_egl.h>
26 #include <gst/gl/egl/gsteglimage.h>
27 #include <gst/gl/egl/gstglmemoryegl.h>
29 GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug);
30 #define GST_CAT_DEFAULT gst_gl_display_debug
32 #ifndef EGL_PLATFORM_X11
33 #define EGL_PLATFORM_X11 0x31D5
35 #ifndef EGL_PLATFORM_WAYLAND
36 #define EGL_PLATFORM_WAYLAND 0x31D8
38 #ifndef EGL_PLATFORM_ANDROID
39 #define EGL_PLATFORM_ANDROID 0x3141
42 typedef EGLDisplay (*_gst_eglGetPlatformDisplay_type) (EGLenum platform,
43 void *native_display, const EGLint * attrib_list);
45 G_DEFINE_TYPE (GstGLDisplayEGL, gst_gl_display_egl, GST_TYPE_GL_DISPLAY);
47 static void gst_gl_display_egl_finalize (GObject * object);
48 static guintptr gst_gl_display_egl_get_handle (GstGLDisplay * display);
51 gst_gl_display_egl_class_init (GstGLDisplayEGLClass * klass)
53 GST_GL_DISPLAY_CLASS (klass)->get_handle =
54 GST_DEBUG_FUNCPTR (gst_gl_display_egl_get_handle);
56 G_OBJECT_CLASS (klass)->finalize = gst_gl_display_egl_finalize;
60 gst_gl_display_egl_init (GstGLDisplayEGL * display_egl)
62 GstGLDisplay *display = (GstGLDisplay *) display_egl;
64 display->type = GST_GL_DISPLAY_TYPE_EGL;
65 display_egl->foreign_display = FALSE;
67 gst_gl_memory_egl_init_once ();
71 gst_gl_display_egl_finalize (GObject * object)
73 GstGLDisplayEGL *display_egl = GST_GL_DISPLAY_EGL (object);
75 if (display_egl->display && !display_egl->foreign_display) {
76 eglTerminate (display_egl->display);
77 display_egl->display = NULL;
80 G_OBJECT_CLASS (gst_gl_display_egl_parent_class)->finalize (object);
84 * gst_gl_display_egl_get_from_native:
85 * @type: a #GstGLDisplayType
86 * @display: pointer to a display (or 0)
88 * Attempts to create a new #EGLDisplay from @display. If @type is
89 * %GST_GL_DISPLAY_TYPE_ANY, then @display must be 0.
91 * Returns: A #EGLDisplay or %EGL_NO_DISPLAY
96 gst_gl_display_egl_get_from_native (GstGLDisplayType type, guintptr display)
98 const gchar *egl_exts;
99 EGLDisplay ret = EGL_NO_DISPLAY;
100 _gst_eglGetPlatformDisplay_type _gst_eglGetPlatformDisplay;
102 g_return_val_if_fail ((type != GST_GL_DISPLAY_TYPE_ANY && display != 0)
103 || (type == GST_GL_DISPLAY_TYPE_ANY && display == 0), EGL_NO_DISPLAY);
104 g_return_val_if_fail ((type != GST_GL_DISPLAY_TYPE_NONE
105 || (type == GST_GL_DISPLAY_TYPE_NONE
106 && display == 0)), EGL_NO_DISPLAY);
108 /* given an EGLDisplay already */
109 if (type == GST_GL_DISPLAY_TYPE_EGL)
110 return (EGLDisplay) display;
112 if (type == GST_GL_DISPLAY_TYPE_NONE)
113 type = GST_GL_DISPLAY_TYPE_ANY;
115 egl_exts = eglQueryString (EGL_NO_DISPLAY, EGL_EXTENSIONS);
116 GST_DEBUG ("egl no display extensions: %s", egl_exts);
118 if (eglGetError () != EGL_SUCCESS || !egl_exts)
119 goto default_display;
121 /* check if we can actually choose the egl display type */
122 if (!gst_gl_check_extension ("EGL_KHR_client_get_all_proc_addresses",
124 goto default_display;
125 if (!gst_gl_check_extension ("EGL_EXT_platform_base", egl_exts))
126 goto default_display;
128 _gst_eglGetPlatformDisplay = (_gst_eglGetPlatformDisplay_type)
129 eglGetProcAddress ("eglGetPlatformDisplay");
130 if (!_gst_eglGetPlatformDisplay)
131 _gst_eglGetPlatformDisplay = (_gst_eglGetPlatformDisplay_type)
132 eglGetProcAddress ("eglGetPlatformDisplayEXT");
133 if (!_gst_eglGetPlatformDisplay)
134 goto default_display;
136 /* try each platform in turn */
137 #if GST_GL_HAVE_WINDOW_X11
138 if (ret == EGL_NO_DISPLAY && (type & GST_GL_DISPLAY_TYPE_X11) &&
139 (gst_gl_check_extension ("EGL_KHR_platform_x11", egl_exts) ||
140 gst_gl_check_extension ("EGL_EXT_platform_x11", egl_exts))) {
141 ret = _gst_eglGetPlatformDisplay (EGL_PLATFORM_X11, (gpointer) display,
145 #if GST_GL_HAVE_WINDOW_WAYLAND
146 if (ret == EGL_NO_DISPLAY && (type & GST_GL_DISPLAY_TYPE_WAYLAND) &&
147 (gst_gl_check_extension ("EGL_KHR_platform_wayland", egl_exts) ||
148 gst_gl_check_extension ("EGL_EXT_platform_wayland", egl_exts))) {
149 ret = _gst_eglGetPlatformDisplay (EGL_PLATFORM_WAYLAND, (gpointer) display,
153 /* android only has one winsys/display connection */
155 if (ret != EGL_NO_DISPLAY)
158 /* otherwise rely on the implementation to choose the correct display
159 * based on the pointer */
161 return eglGetDisplay ((EGLNativeDisplayType) display);
165 * gst_gl_display_egl_new:
167 * Create a new #GstGLDisplayEGL using the default EGL_DEFAULT_DISPLAY.
169 * Returns: (transfer full): a new #GstGLDisplayEGL or %NULL
172 gst_gl_display_egl_new (void)
174 GstGLDisplayEGL *ret;
176 GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay");
178 ret = g_object_new (GST_TYPE_GL_DISPLAY_EGL, NULL);
180 gst_gl_display_egl_get_from_native (GST_GL_DISPLAY_TYPE_ANY, 0);
183 GST_ERROR ("Failed to open EGL display connection");
190 * gst_gl_display_egl_new_with_display:
191 * @display: an existing and connected EGLDisplay
193 * Creates a new display connection from a EGLDisplay.
195 * Returns: (transfer full): a new #GstGLDisplayEGL
200 gst_gl_display_egl_new_with_egl_display (EGLDisplay display)
202 GstGLDisplayEGL *ret;
204 g_return_val_if_fail (display != NULL, NULL);
206 GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay");
208 ret = g_object_new (GST_TYPE_GL_DISPLAY_EGL, NULL);
210 ret->display = display;
211 ret->foreign_display = TRUE;
217 _ref_if_set (gpointer data, gpointer user_data)
220 gst_object_ref (data);
225 * gst_gl_display_egl_from_gl_display:
226 * @display: an existing #GstGLDisplay
228 * Creates a EGL display connection from a native Display.
230 * This function will return the same value for multiple calls with the same
233 * Returns: (transfer full): a new #GstGLDisplayEGL
238 gst_gl_display_egl_from_gl_display (GstGLDisplay * display)
240 GstGLDisplayEGL *ret;
241 GstGLDisplayType display_type;
242 guintptr native_display;
244 g_return_val_if_fail (GST_IS_GL_DISPLAY (display), NULL);
246 GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay");
248 if (GST_IS_GL_DISPLAY_EGL (display)) {
249 GST_LOG_OBJECT (display, "display %" GST_PTR_FORMAT "is already a "
250 "GstGLDisplayEGL", display);
251 return gst_object_ref (display);
254 /* try to get a previously set GstGLDisplayEGL */
255 ret = g_object_dup_data (G_OBJECT (display), GST_GL_DISPLAY_EGL_NAME,
256 (GDuplicateFunc) _ref_if_set, NULL);
257 if (ret && GST_IS_GL_DISPLAY_EGL (ret)) {
258 GST_LOG_OBJECT (display, "display %" GST_PTR_FORMAT "already has a "
259 "GstGLDisplayEGL %" GST_PTR_FORMAT, display, ret);
264 gst_object_unref (ret);
266 display_type = gst_gl_display_get_handle_type (display);
267 native_display = gst_gl_display_get_handle (display);
269 g_return_val_if_fail (native_display != 0, NULL);
270 g_return_val_if_fail (display_type != GST_GL_DISPLAY_TYPE_NONE, NULL);
272 ret = g_object_new (GST_TYPE_GL_DISPLAY_EGL, NULL);
275 gst_gl_display_egl_get_from_native (display_type, native_display);
278 GST_WARNING_OBJECT (ret, "failed to get EGLDisplay from native display");
279 gst_object_unref (ret);
282 g_object_set_data_full (G_OBJECT (display), GST_GL_DISPLAY_EGL_NAME,
283 gst_object_ref (ret), (GDestroyNotify) gst_object_unref);
289 gst_gl_display_egl_get_handle (GstGLDisplay * display)
291 return (guintptr) GST_GL_DISPLAY_EGL (display)->display;