EGLint egl_minor;
gboolean need_surface = TRUE;
guintptr external_gl_context = 0;
- GstGLDisplay *display;
+ guintptr egl_display;
egl = GST_GL_CONTEXT_EGL (context);
window = gst_gl_context_get_window (context);
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->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->display_egl = gst_gl_display_egl_from_gl_display (display);
+ if (!egl->display_egl) {
+ g_set_error (error, GST_GL_CONTEXT_ERROR,
+ GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE,
+ "Failed to create EGLDisplay from native display");
+ goto failure;
}
- 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)) {
GST_INFO ("egl initialized, version: %d.%d", egl_major, egl_minor);
#endif
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_IS_GL_WINDOW_WAYLAND_EGL (context->window)) {
gst_gl_window_wayland_egl_create_window ((GstGLWindowWaylandEGL *)
egl->window_handle = 0;
eglReleaseThread ();
+
+ if (egl->display_egl) {
+ gst_object_unref (egl->display_egl);
+ egl->display_egl = NULL;
+ }
}
static gboolean
GST_DEBUG_CATEGORY_STATIC (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);
static void gst_gl_display_egl_finalize (GObject * 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:
*
* Create a new #GstGLDisplayEGL using the default EGL_DEFAULT_DISPLAY.
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);
+ ret->display =
+ gst_gl_display_egl_get_from_native (GST_GL_DISPLAY_TYPE_ANY, 0);
if (!ret->display) {
GST_ERROR ("Failed to open EGL display connection");
* Creates a new display connection from a EGLDisplay.
*
* Returns: (transfer full): a new #GstGLDisplayEGL
+ *
+ * Since: 1.12
*/
GstGLDisplayEGL *
gst_gl_display_egl_new_with_egl_display (EGLDisplay display)
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
gst_gl_display_egl_get_handle (GstGLDisplay * display)
{