|
Packit |
971217 |
/*
|
|
Packit |
971217 |
* GStreamer
|
|
Packit |
971217 |
* Copyright (C) 2014 Matthew Waters <ystreet00@gmail.com>
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* This library is free software; you can redistribute it and/or
|
|
Packit |
971217 |
* modify it under the terms of the GNU Library General Public
|
|
Packit |
971217 |
* License as published by the Free Software Foundation; either
|
|
Packit |
971217 |
* version 2 of the License, or (at your option) any later version.
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
971217 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
971217 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
971217 |
* Library General Public License for more details.
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* You should have received a copy of the GNU Library General Public
|
|
Packit |
971217 |
* License along with this library; if not, write to the
|
|
Packit |
971217 |
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
Packit |
971217 |
* Boston, MA 02110-1301, USA.
|
|
Packit |
971217 |
*/
|
|
Packit |
971217 |
|
|
Packit |
971217 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
971217 |
#include "config.h"
|
|
Packit |
971217 |
#endif
|
|
Packit |
971217 |
|
|
Packit |
971217 |
#include "gstgldisplay_egl.h"
|
|
Packit |
971217 |
|
|
Packit |
971217 |
#include <gst/gl/gstglfeature.h>
|
|
Packit |
971217 |
|
|
Packit |
971217 |
#include "gstegl.h"
|
|
Packit |
971217 |
#include "gsteglimage.h"
|
|
Packit |
971217 |
#include "gstglmemoryegl.h"
|
|
Packit |
971217 |
|
|
Packit |
971217 |
GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug);
|
|
Packit |
971217 |
#define GST_CAT_DEFAULT gst_gl_display_debug
|
|
Packit |
971217 |
|
|
Packit |
971217 |
#ifndef EGL_PLATFORM_X11
|
|
Packit |
971217 |
#define EGL_PLATFORM_X11 0x31D5
|
|
Packit |
971217 |
#endif
|
|
Packit |
971217 |
#ifndef EGL_PLATFORM_WAYLAND
|
|
Packit |
971217 |
#define EGL_PLATFORM_WAYLAND 0x31D8
|
|
Packit |
971217 |
#endif
|
|
Packit |
971217 |
#ifndef EGL_PLATFORM_ANDROID
|
|
Packit |
971217 |
#define EGL_PLATFORM_ANDROID 0x3141
|
|
Packit |
971217 |
#endif
|
|
Packit |
971217 |
|
|
Packit |
971217 |
typedef EGLDisplay (*_gst_eglGetPlatformDisplay_type) (EGLenum platform,
|
|
Packit |
971217 |
void *native_display, const EGLint * attrib_list);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
G_DEFINE_TYPE (GstGLDisplayEGL, gst_gl_display_egl, GST_TYPE_GL_DISPLAY);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
static void gst_gl_display_egl_finalize (GObject * object);
|
|
Packit |
971217 |
static guintptr gst_gl_display_egl_get_handle (GstGLDisplay * display);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
static void
|
|
Packit |
971217 |
gst_gl_display_egl_class_init (GstGLDisplayEGLClass * klass)
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
GST_GL_DISPLAY_CLASS (klass)->get_handle =
|
|
Packit |
971217 |
GST_DEBUG_FUNCPTR (gst_gl_display_egl_get_handle);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
G_OBJECT_CLASS (klass)->finalize = gst_gl_display_egl_finalize;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
static void
|
|
Packit |
971217 |
gst_gl_display_egl_init (GstGLDisplayEGL * display_egl)
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
GstGLDisplay *display = (GstGLDisplay *) display_egl;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
display->type = GST_GL_DISPLAY_TYPE_EGL;
|
|
Packit |
971217 |
display_egl->foreign_display = FALSE;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
gst_gl_memory_egl_init_once ();
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
static void
|
|
Packit |
971217 |
gst_gl_display_egl_finalize (GObject * object)
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
GstGLDisplayEGL *display_egl = GST_GL_DISPLAY_EGL (object);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
if (display_egl->display && !display_egl->foreign_display) {
|
|
Packit |
971217 |
eglTerminate (display_egl->display);
|
|
Packit |
971217 |
display_egl->display = NULL;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
G_OBJECT_CLASS (gst_gl_display_egl_parent_class)->finalize (object);
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
/**
|
|
Packit |
971217 |
* gst_gl_display_egl_get_from_native:
|
|
Packit |
971217 |
* @type: a #GstGLDisplayType
|
|
Packit |
971217 |
* @display: pointer to a display (or 0)
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* Attempts to create a new #EGLDisplay from @display. If @type is
|
|
Packit |
971217 |
* %GST_GL_DISPLAY_TYPE_ANY, then @display must be 0. @type must not be
|
|
Packit |
971217 |
* %GST_GL_DISPLAY_TYPE_NONE.
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* Returns: A #EGLDisplay or %EGL_NO_DISPLAY
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* Since: 1.12
|
|
Packit |
971217 |
*/
|
|
Packit |
971217 |
gpointer
|
|
Packit |
971217 |
gst_gl_display_egl_get_from_native (GstGLDisplayType type, guintptr display)
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
const gchar *egl_exts;
|
|
Packit |
971217 |
EGLDisplay ret = EGL_NO_DISPLAY;
|
|
Packit |
971217 |
_gst_eglGetPlatformDisplay_type _gst_eglGetPlatformDisplay;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
g_return_val_if_fail (type != GST_GL_DISPLAY_TYPE_NONE, EGL_NO_DISPLAY);
|
|
Packit |
971217 |
g_return_val_if_fail ((type != GST_GL_DISPLAY_TYPE_ANY && display != 0)
|
|
Packit |
971217 |
|| (type == GST_GL_DISPLAY_TYPE_ANY && display == 0), EGL_NO_DISPLAY);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
/* given an EGLDisplay already */
|
|
Packit |
971217 |
if (type == GST_GL_DISPLAY_TYPE_EGL)
|
|
Packit |
971217 |
return (gpointer) display;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
egl_exts = eglQueryString (EGL_NO_DISPLAY, EGL_EXTENSIONS);
|
|
Packit |
971217 |
GST_DEBUG ("egl no display extensions: %s", egl_exts);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
if (eglGetError () != EGL_SUCCESS || !egl_exts)
|
|
Packit |
971217 |
goto default_display;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
/* check if we can actually choose the egl display type */
|
|
Packit |
971217 |
if (!gst_gl_check_extension ("EGL_KHR_client_get_all_proc_addresses",
|
|
Packit |
971217 |
egl_exts))
|
|
Packit |
971217 |
goto default_display;
|
|
Packit |
971217 |
if (!gst_gl_check_extension ("EGL_EXT_platform_base", egl_exts))
|
|
Packit |
971217 |
goto default_display;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
_gst_eglGetPlatformDisplay = (_gst_eglGetPlatformDisplay_type)
|
|
Packit |
971217 |
eglGetProcAddress ("eglGetPlatformDisplay");
|
|
Packit |
971217 |
if (!_gst_eglGetPlatformDisplay)
|
|
Packit |
971217 |
_gst_eglGetPlatformDisplay = (_gst_eglGetPlatformDisplay_type)
|
|
Packit |
971217 |
eglGetProcAddress ("eglGetPlatformDisplayEXT");
|
|
Packit |
971217 |
if (!_gst_eglGetPlatformDisplay)
|
|
Packit |
971217 |
goto default_display;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
/* try each platform in turn */
|
|
Packit |
971217 |
#if GST_GL_HAVE_WINDOW_X11
|
|
Packit |
971217 |
if (ret == EGL_NO_DISPLAY && (type & GST_GL_DISPLAY_TYPE_X11) &&
|
|
Packit |
971217 |
(gst_gl_check_extension ("EGL_KHR_platform_x11", egl_exts) ||
|
|
Packit |
971217 |
gst_gl_check_extension ("EGL_EXT_platform_x11", egl_exts))) {
|
|
Packit |
971217 |
ret = _gst_eglGetPlatformDisplay (EGL_PLATFORM_X11, (gpointer) display,
|
|
Packit |
971217 |
NULL);
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
#endif
|
|
Packit |
971217 |
#if GST_GL_HAVE_WINDOW_WAYLAND
|
|
Packit |
971217 |
if (ret == EGL_NO_DISPLAY && (type & GST_GL_DISPLAY_TYPE_WAYLAND) &&
|
|
Packit |
971217 |
(gst_gl_check_extension ("EGL_KHR_platform_wayland", egl_exts) ||
|
|
Packit |
971217 |
gst_gl_check_extension ("EGL_EXT_platform_wayland", egl_exts))) {
|
|
Packit |
971217 |
ret = _gst_eglGetPlatformDisplay (EGL_PLATFORM_WAYLAND, (gpointer) display,
|
|
Packit |
971217 |
NULL);
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
#endif
|
|
Packit |
971217 |
#if GST_GL_HAVE_WINDOW_GBM
|
|
Packit |
971217 |
if (ret == EGL_NO_DISPLAY && (type & GST_GL_DISPLAY_TYPE_GBM) &&
|
|
Packit |
971217 |
(gst_gl_check_extension ("EGL_MESA_platform_gbm", egl_exts) ||
|
|
Packit |
971217 |
gst_gl_check_extension ("EGL_MESA_platform_gbm", egl_exts))) {
|
|
Packit |
971217 |
ret = _gst_eglGetPlatformDisplay (EGL_PLATFORM_GBM_MESA, (gpointer) display,
|
|
Packit |
971217 |
NULL);
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
#endif
|
|
Packit |
971217 |
/* android only has one winsys/display connection */
|
|
Packit |
971217 |
|
|
Packit |
971217 |
if (ret != EGL_NO_DISPLAY)
|
|
Packit |
971217 |
return ret;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
/* otherwise rely on the implementation to choose the correct display
|
|
Packit |
971217 |
* based on the pointer */
|
|
Packit |
971217 |
default_display:
|
|
Packit |
971217 |
return (gpointer) eglGetDisplay ((EGLNativeDisplayType) display);
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
/**
|
|
Packit |
971217 |
* gst_gl_display_egl_new:
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* Create a new #GstGLDisplayEGL using the default EGL_DEFAULT_DISPLAY.
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* Returns: (transfer full): a new #GstGLDisplayEGL or %NULL
|
|
Packit |
971217 |
*/
|
|
Packit |
971217 |
GstGLDisplayEGL *
|
|
Packit |
971217 |
gst_gl_display_egl_new (void)
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
GstGLDisplayEGL *ret;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay");
|
|
Packit |
971217 |
|
|
Packit |
971217 |
ret = g_object_new (GST_TYPE_GL_DISPLAY_EGL, NULL);
|
|
Packit |
971217 |
gst_object_ref_sink (ret);
|
|
Packit |
971217 |
ret->display =
|
|
Packit |
971217 |
gst_gl_display_egl_get_from_native (GST_GL_DISPLAY_TYPE_ANY, 0);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
if (!ret->display) {
|
|
Packit |
971217 |
GST_INFO ("Failed to open EGL display connection");
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
return ret;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
/**
|
|
Packit |
971217 |
* gst_gl_display_egl_new_with_display:
|
|
Packit |
971217 |
* @display: an existing and connected EGLDisplay
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* Creates a new display connection from a EGLDisplay.
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* Returns: (transfer full): a new #GstGLDisplayEGL
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* Since: 1.12
|
|
Packit |
971217 |
*/
|
|
Packit |
971217 |
GstGLDisplayEGL *
|
|
Packit |
971217 |
gst_gl_display_egl_new_with_egl_display (gpointer display)
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
GstGLDisplayEGL *ret;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
g_return_val_if_fail (display != NULL, NULL);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay");
|
|
Packit |
971217 |
|
|
Packit |
971217 |
ret = g_object_new (GST_TYPE_GL_DISPLAY_EGL, NULL);
|
|
Packit |
971217 |
gst_object_ref_sink (ret);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
ret->display = display;
|
|
Packit |
971217 |
ret->foreign_display = TRUE;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
return ret;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
static gpointer
|
|
Packit |
971217 |
_ref_if_set (gpointer data, gpointer user_data)
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
if (data)
|
|
Packit |
971217 |
gst_object_ref (data);
|
|
Packit |
971217 |
return data;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
/**
|
|
Packit |
971217 |
* gst_gl_display_egl_from_gl_display:
|
|
Packit |
971217 |
* @display: an existing #GstGLDisplay
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* Creates a EGL display connection from a native Display.
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* This function will return the same value for multiple calls with the same
|
|
Packit |
971217 |
* @display.
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* Returns: (transfer full): a new #GstGLDisplayEGL
|
|
Packit |
971217 |
*
|
|
Packit |
971217 |
* Since: 1.12
|
|
Packit |
971217 |
*/
|
|
Packit |
971217 |
GstGLDisplayEGL *
|
|
Packit |
971217 |
gst_gl_display_egl_from_gl_display (GstGLDisplay * display)
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
GstGLDisplayEGL *ret;
|
|
Packit |
971217 |
GstGLDisplayType display_type;
|
|
Packit |
971217 |
guintptr native_display;
|
|
Packit |
971217 |
|
|
Packit |
971217 |
g_return_val_if_fail (GST_IS_GL_DISPLAY (display), NULL);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay");
|
|
Packit |
971217 |
|
|
Packit |
971217 |
if (GST_IS_GL_DISPLAY_EGL (display)) {
|
|
Packit |
971217 |
GST_LOG_OBJECT (display, "display %" GST_PTR_FORMAT "is already a "
|
|
Packit |
971217 |
"GstGLDisplayEGL", display);
|
|
Packit |
971217 |
return gst_object_ref (display);
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
/* try to get a previously set GstGLDisplayEGL */
|
|
Packit |
971217 |
ret = g_object_dup_data (G_OBJECT (display), GST_GL_DISPLAY_EGL_NAME,
|
|
Packit |
971217 |
(GDuplicateFunc) _ref_if_set, NULL);
|
|
Packit |
971217 |
if (ret && GST_IS_GL_DISPLAY_EGL (ret)) {
|
|
Packit |
971217 |
GST_LOG_OBJECT (display, "display %" GST_PTR_FORMAT "already has a "
|
|
Packit |
971217 |
"GstGLDisplayEGL %" GST_PTR_FORMAT, display, ret);
|
|
Packit |
971217 |
return ret;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
if (ret)
|
|
Packit |
971217 |
gst_object_unref (ret);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
display_type = gst_gl_display_get_handle_type (display);
|
|
Packit |
971217 |
native_display = gst_gl_display_get_handle (display);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
g_return_val_if_fail (native_display != 0, NULL);
|
|
Packit |
971217 |
g_return_val_if_fail (display_type != GST_GL_DISPLAY_TYPE_NONE, NULL);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
ret = g_object_new (GST_TYPE_GL_DISPLAY_EGL, NULL);
|
|
Packit |
971217 |
gst_object_ref_sink (ret);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
ret->display =
|
|
Packit |
971217 |
gst_gl_display_egl_get_from_native (display_type, native_display);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
if (!ret->display) {
|
|
Packit |
971217 |
GST_WARNING_OBJECT (ret, "failed to get EGLDisplay from native display");
|
|
Packit |
971217 |
gst_object_unref (ret);
|
|
Packit |
971217 |
return NULL;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
g_object_set_data_full (G_OBJECT (display), GST_GL_DISPLAY_EGL_NAME,
|
|
Packit |
971217 |
gst_object_ref (ret), (GDestroyNotify) gst_object_unref);
|
|
Packit |
971217 |
|
|
Packit |
971217 |
return ret;
|
|
Packit |
971217 |
}
|
|
Packit |
971217 |
|
|
Packit |
971217 |
static guintptr
|
|
Packit |
971217 |
gst_gl_display_egl_get_handle (GstGLDisplay * display)
|
|
Packit |
971217 |
{
|
|
Packit |
971217 |
return (guintptr) GST_GL_DISPLAY_EGL (display)->display;
|
|
Packit |
971217 |
}
|