Blame gst-libs/gst/gl/egl/gstgldisplay_egl.c

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
}