mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
display/egl: implement getting the EGLDisplay of a specific platform
https://bugzilla.gnome.org/show_bug.cgi?id=774518
This commit is contained in:
parent
ddf7fe0e80
commit
415ce6c96a
4 changed files with 198 additions and 23 deletions
|
@ -313,7 +313,7 @@ gst_gl_context_egl_create_context (GstGLContext * context,
|
||||||
EGLint egl_minor;
|
EGLint egl_minor;
|
||||||
gboolean need_surface = TRUE;
|
gboolean need_surface = TRUE;
|
||||||
guintptr external_gl_context = 0;
|
guintptr external_gl_context = 0;
|
||||||
GstGLDisplay *display;
|
guintptr egl_display;
|
||||||
|
|
||||||
egl = GST_GL_CONTEXT_EGL (context);
|
egl = GST_GL_CONTEXT_EGL (context);
|
||||||
window = gst_gl_context_get_window (context);
|
window = gst_gl_context_get_window (context);
|
||||||
|
@ -337,31 +337,22 @@ gst_gl_context_egl_create_context (GstGLContext * context,
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
display = gst_gl_context_get_display (context);
|
if (!egl->display_egl) {
|
||||||
|
GstGLDisplay *display = gst_gl_context_get_display (context);
|
||||||
|
|
||||||
if (display->type == GST_GL_DISPLAY_TYPE_EGL) {
|
egl->display_egl = gst_gl_display_egl_from_gl_display (display);
|
||||||
egl->egl_display = (EGLDisplay) gst_gl_display_get_handle (display);
|
if (!egl->display_egl) {
|
||||||
} else {
|
g_set_error (error, GST_GL_CONTEXT_ERROR,
|
||||||
guintptr native_display = gst_gl_display_get_handle (display);
|
GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE,
|
||||||
|
"Failed to create EGLDisplay from native display");
|
||||||
if (!native_display) {
|
goto failure;
|
||||||
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);
|
gst_object_unref (display);
|
||||||
}
|
}
|
||||||
gst_object_unref (display);
|
|
||||||
|
egl_display = gst_gl_display_get_handle (GST_GL_DISPLAY (egl->display_egl));
|
||||||
|
egl->egl_display = (EGLDisplay) egl_display;
|
||||||
|
|
||||||
if (eglInitialize (egl->egl_display, &egl_major, &egl_minor)) {
|
if (eglInitialize (egl->egl_display, &egl_major, &egl_minor)) {
|
||||||
GST_INFO ("egl initialized, version: %d.%d", egl_major, egl_minor);
|
GST_INFO ("egl initialized, version: %d.%d", egl_major, egl_minor);
|
||||||
|
@ -531,6 +522,8 @@ gst_gl_context_egl_create_context (GstGLContext * context,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (other_context == NULL) {
|
if (other_context == NULL) {
|
||||||
|
/* FIXME: fails to show two outputs at all. We need a property/option for
|
||||||
|
* glimagesink to say its a visible context */
|
||||||
#if GST_GL_HAVE_WINDOW_WAYLAND
|
#if GST_GL_HAVE_WINDOW_WAYLAND
|
||||||
if (GST_IS_GL_WINDOW_WAYLAND_EGL (context->window)) {
|
if (GST_IS_GL_WINDOW_WAYLAND_EGL (context->window)) {
|
||||||
gst_gl_window_wayland_egl_create_window ((GstGLWindowWaylandEGL *)
|
gst_gl_window_wayland_egl_create_window ((GstGLWindowWaylandEGL *)
|
||||||
|
@ -654,6 +647,11 @@ gst_gl_context_egl_destroy_context (GstGLContext * context)
|
||||||
egl->window_handle = 0;
|
egl->window_handle = 0;
|
||||||
|
|
||||||
eglReleaseThread ();
|
eglReleaseThread ();
|
||||||
|
|
||||||
|
if (egl->display_egl) {
|
||||||
|
gst_object_unref (egl->display_egl);
|
||||||
|
egl->display_egl = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include <gst/gl/gl.h>
|
#include <gst/gl/gl.h>
|
||||||
#include <gst/gl/egl/gstegl.h>
|
#include <gst/gl/egl/gstegl.h>
|
||||||
|
|
||||||
|
#include <gst/gl/egl/gstgldisplay_egl.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
typedef struct _GstGLContextEGL GstGLContextEGL;
|
typedef struct _GstGLContextEGL GstGLContextEGL;
|
||||||
|
@ -52,6 +54,8 @@ struct _GstGLContextEGL
|
||||||
/* <private> */
|
/* <private> */
|
||||||
GstGLContext context;
|
GstGLContext context;
|
||||||
|
|
||||||
|
GstGLDisplayEGL *display_egl;
|
||||||
|
|
||||||
EGLContext egl_context;
|
EGLContext egl_context;
|
||||||
EGLDisplay egl_display;
|
EGLDisplay egl_display;
|
||||||
EGLSurface egl_surface;
|
EGLSurface egl_surface;
|
||||||
|
|
|
@ -29,6 +29,19 @@
|
||||||
GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug);
|
GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug);
|
||||||
#define GST_CAT_DEFAULT gst_gl_display_debug
|
#define GST_CAT_DEFAULT gst_gl_display_debug
|
||||||
|
|
||||||
|
#ifndef EGL_PLATFORM_X11
|
||||||
|
#define EGL_PLATFORM_X11 0x31D5
|
||||||
|
#endif
|
||||||
|
#ifndef EGL_PLATFORM_WAYLAND
|
||||||
|
#define EGL_PLATFORM_WAYLAND 0x31D8
|
||||||
|
#endif
|
||||||
|
#ifndef EGL_PLATFORM_ANDROID
|
||||||
|
#define EGL_PLATFORM_ANDROID 0x3141
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef EGLDisplay (*_gst_eglGetPlatformDisplay_type) (EGLenum platform,
|
||||||
|
void *native_display, const EGLint * attrib_list);
|
||||||
|
|
||||||
G_DEFINE_TYPE (GstGLDisplayEGL, gst_gl_display_egl, GST_TYPE_GL_DISPLAY);
|
G_DEFINE_TYPE (GstGLDisplayEGL, gst_gl_display_egl, GST_TYPE_GL_DISPLAY);
|
||||||
|
|
||||||
static void gst_gl_display_egl_finalize (GObject * object);
|
static void gst_gl_display_egl_finalize (GObject * object);
|
||||||
|
@ -67,6 +80,87 @@ gst_gl_display_egl_finalize (GObject * object)
|
||||||
G_OBJECT_CLASS (gst_gl_display_egl_parent_class)->finalize (object);
|
G_OBJECT_CLASS (gst_gl_display_egl_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_gl_display_egl_get_from_native:
|
||||||
|
* @type: a #GstGLDisplayType
|
||||||
|
* @display: pointer to a display (or 0)
|
||||||
|
*
|
||||||
|
* Attempts to create a new #EGLDisplay from @display. If @type is
|
||||||
|
* %GST_GL_DISPLAY_TYPE_ANY, then @display must be 0.
|
||||||
|
*
|
||||||
|
* Returns: A #EGLDisplay or %EGL_NO_DISPLAY
|
||||||
|
*
|
||||||
|
* Since: 1.12
|
||||||
|
*/
|
||||||
|
EGLDisplay
|
||||||
|
gst_gl_display_egl_get_from_native (GstGLDisplayType type, guintptr display)
|
||||||
|
{
|
||||||
|
const gchar *egl_exts;
|
||||||
|
EGLDisplay ret = EGL_NO_DISPLAY;
|
||||||
|
_gst_eglGetPlatformDisplay_type _gst_eglGetPlatformDisplay;
|
||||||
|
|
||||||
|
g_return_val_if_fail ((type != GST_GL_DISPLAY_TYPE_ANY && display != 0)
|
||||||
|
|| (type == GST_GL_DISPLAY_TYPE_ANY && display == 0), EGL_NO_DISPLAY);
|
||||||
|
g_return_val_if_fail ((type != GST_GL_DISPLAY_TYPE_NONE
|
||||||
|
|| (type == GST_GL_DISPLAY_TYPE_NONE
|
||||||
|
&& display == 0)), EGL_NO_DISPLAY);
|
||||||
|
|
||||||
|
/* given an EGLDisplay already */
|
||||||
|
if (type == GST_GL_DISPLAY_TYPE_EGL)
|
||||||
|
return (EGLDisplay) display;
|
||||||
|
|
||||||
|
if (type == GST_GL_DISPLAY_TYPE_NONE)
|
||||||
|
type = GST_GL_DISPLAY_TYPE_ANY;
|
||||||
|
|
||||||
|
egl_exts = eglQueryString (EGL_NO_DISPLAY, EGL_EXTENSIONS);
|
||||||
|
GST_DEBUG ("egl no display extensions: %s", egl_exts);
|
||||||
|
|
||||||
|
if (eglGetError () != EGL_SUCCESS || !egl_exts)
|
||||||
|
goto default_display;
|
||||||
|
|
||||||
|
/* check if we can actually choose the egl display type */
|
||||||
|
if (!gst_gl_check_extension ("EGL_KHR_client_get_all_proc_addresses",
|
||||||
|
egl_exts))
|
||||||
|
goto default_display;
|
||||||
|
if (!gst_gl_check_extension ("EGL_EXT_platform_base", egl_exts))
|
||||||
|
goto default_display;
|
||||||
|
|
||||||
|
_gst_eglGetPlatformDisplay = (_gst_eglGetPlatformDisplay_type)
|
||||||
|
eglGetProcAddress ("eglGetPlatformDisplay");
|
||||||
|
if (!_gst_eglGetPlatformDisplay)
|
||||||
|
_gst_eglGetPlatformDisplay = (_gst_eglGetPlatformDisplay_type)
|
||||||
|
eglGetProcAddress ("eglGetPlatformDisplayEXT");
|
||||||
|
if (!_gst_eglGetPlatformDisplay)
|
||||||
|
goto default_display;
|
||||||
|
|
||||||
|
/* try each platform in turn */
|
||||||
|
#if GST_GL_HAVE_WINDOW_X11
|
||||||
|
if (ret == EGL_NO_DISPLAY && (type & GST_GL_DISPLAY_TYPE_X11) &&
|
||||||
|
(gst_gl_check_extension ("EGL_KHR_platform_x11", egl_exts) ||
|
||||||
|
gst_gl_check_extension ("EGL_EXT_platform_x11", egl_exts))) {
|
||||||
|
ret = _gst_eglGetPlatformDisplay (EGL_PLATFORM_X11, (gpointer) display,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if GST_GL_HAVE_WINDOW_WAYLAND
|
||||||
|
if (ret == EGL_NO_DISPLAY && (type & GST_GL_DISPLAY_TYPE_WAYLAND) &&
|
||||||
|
(gst_gl_check_extension ("EGL_KHR_platform_wayland", egl_exts) ||
|
||||||
|
gst_gl_check_extension ("EGL_EXT_platform_wayland", egl_exts))) {
|
||||||
|
ret = _gst_eglGetPlatformDisplay (EGL_PLATFORM_WAYLAND, (gpointer) display,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* android only has one winsys/display connection */
|
||||||
|
|
||||||
|
if (ret != EGL_NO_DISPLAY)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* otherwise rely on the implementation to choose the correct display
|
||||||
|
* based on the pointer */
|
||||||
|
default_display:
|
||||||
|
return eglGetDisplay ((EGLNativeDisplayType) display);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_gl_display_egl_new:
|
* gst_gl_display_egl_new:
|
||||||
*
|
*
|
||||||
|
@ -82,7 +176,8 @@ gst_gl_display_egl_new (void)
|
||||||
GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay");
|
GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay");
|
||||||
|
|
||||||
ret = g_object_new (GST_TYPE_GL_DISPLAY_EGL, NULL);
|
ret = g_object_new (GST_TYPE_GL_DISPLAY_EGL, NULL);
|
||||||
ret->display = eglGetDisplay ((EGLNativeDisplayType) EGL_DEFAULT_DISPLAY);
|
ret->display =
|
||||||
|
gst_gl_display_egl_get_from_native (GST_GL_DISPLAY_TYPE_ANY, 0);
|
||||||
|
|
||||||
if (!ret->display) {
|
if (!ret->display) {
|
||||||
GST_ERROR ("Failed to open EGL display connection");
|
GST_ERROR ("Failed to open EGL display connection");
|
||||||
|
@ -98,6 +193,8 @@ gst_gl_display_egl_new (void)
|
||||||
* Creates a new display connection from a EGLDisplay.
|
* Creates a new display connection from a EGLDisplay.
|
||||||
*
|
*
|
||||||
* Returns: (transfer full): a new #GstGLDisplayEGL
|
* Returns: (transfer full): a new #GstGLDisplayEGL
|
||||||
|
*
|
||||||
|
* Since: 1.12
|
||||||
*/
|
*/
|
||||||
GstGLDisplayEGL *
|
GstGLDisplayEGL *
|
||||||
gst_gl_display_egl_new_with_egl_display (EGLDisplay display)
|
gst_gl_display_egl_new_with_egl_display (EGLDisplay display)
|
||||||
|
@ -116,6 +213,78 @@ gst_gl_display_egl_new_with_egl_display (EGLDisplay display)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
_ref_if_set (gpointer data, gpointer user_data)
|
||||||
|
{
|
||||||
|
if (data)
|
||||||
|
gst_object_ref (data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_gl_display_egl_from_gl_display:
|
||||||
|
* @display: an existing #GstGLDisplay
|
||||||
|
*
|
||||||
|
* Creates a EGL display connection from a native Display.
|
||||||
|
*
|
||||||
|
* This function will return the same value for multiple calls with the same
|
||||||
|
* @display.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): a new #GstGLDisplayEGL
|
||||||
|
*
|
||||||
|
* Since: 1.12
|
||||||
|
*/
|
||||||
|
GstGLDisplayEGL *
|
||||||
|
gst_gl_display_egl_from_gl_display (GstGLDisplay * display)
|
||||||
|
{
|
||||||
|
GstGLDisplayEGL *ret;
|
||||||
|
GstGLDisplayType display_type;
|
||||||
|
guintptr native_display;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GST_IS_GL_DISPLAY (display), NULL);
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay");
|
||||||
|
|
||||||
|
if (GST_IS_GL_DISPLAY_EGL (display)) {
|
||||||
|
GST_LOG_OBJECT (display, "display %" GST_PTR_FORMAT "is already a "
|
||||||
|
"GstGLDisplayEGL", display);
|
||||||
|
return gst_object_ref (display);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try to get a previously set GstGLDisplayEGL */
|
||||||
|
ret = g_object_dup_data (G_OBJECT (display), GST_GL_DISPLAY_EGL_NAME,
|
||||||
|
(GDuplicateFunc) _ref_if_set, NULL);
|
||||||
|
if (ret && GST_IS_GL_DISPLAY_EGL (ret)) {
|
||||||
|
GST_LOG_OBJECT (display, "display %" GST_PTR_FORMAT "already has a "
|
||||||
|
"GstGLDisplayEGL %" GST_PTR_FORMAT, display, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
gst_object_unref (ret);
|
||||||
|
|
||||||
|
display_type = gst_gl_display_get_handle_type (display);
|
||||||
|
native_display = gst_gl_display_get_handle (display);
|
||||||
|
|
||||||
|
g_return_val_if_fail (native_display != 0, NULL);
|
||||||
|
g_return_val_if_fail (display_type != GST_GL_DISPLAY_TYPE_NONE, NULL);
|
||||||
|
|
||||||
|
ret = g_object_new (GST_TYPE_GL_DISPLAY_EGL, NULL);
|
||||||
|
|
||||||
|
ret->display =
|
||||||
|
gst_gl_display_egl_get_from_native (display_type, native_display);
|
||||||
|
|
||||||
|
if (!ret->display) {
|
||||||
|
GST_WARNING_OBJECT (ret, "failed to get EGLDisplay from native display");
|
||||||
|
gst_object_unref (ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
g_object_set_data_full (G_OBJECT (display), GST_GL_DISPLAY_EGL_NAME,
|
||||||
|
gst_object_ref (ret), (GDestroyNotify) gst_object_unref);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static guintptr
|
static guintptr
|
||||||
gst_gl_display_egl_get_handle (GstGLDisplay * display)
|
gst_gl_display_egl_get_handle (GstGLDisplay * display)
|
||||||
{
|
{
|
||||||
|
|
|
@ -66,6 +66,10 @@ struct _GstGLDisplayEGLClass
|
||||||
|
|
||||||
GstGLDisplayEGL *gst_gl_display_egl_new (void);
|
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_egl_display (EGLDisplay display);
|
||||||
|
GstGLDisplayEGL *gst_gl_display_egl_from_gl_display (GstGLDisplay * display);
|
||||||
|
EGLDisplay gst_gl_display_egl_get_from_native (GstGLDisplayType type, guintptr display);
|
||||||
|
|
||||||
|
#define GST_GL_DISPLAY_EGL_NAME "gst.gl.display.egl"
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue