From e9327d4928df2fe75ffa25a117c1ccd8d790ddd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 17 Feb 2017 12:24:58 +0200 Subject: [PATCH] gl: Add support for Vivante EGL FB windowing system This is very similar to how dispmanx on the Raspberry Pi works. Based on a patch by Haihua Hu from https://github.com/Freescale/meta-freescale/tree/master/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad https://bugzilla.gnome.org/show_bug.cgi?id=778825 --- configure.ac | 53 +++- gst-libs/gst/gl/Makefile.am | 5 + gst-libs/gst/gl/gstgldisplay.c | 16 ++ gst-libs/gst/gl/gstgldisplay.h | 1 + gst-libs/gst/gl/gstglwindow.c | 8 + gst-libs/gst/gl/viv-fb/Makefile.am | 25 ++ gst-libs/gst/gl/viv-fb/gstgldisplay_viv_fb.c | 102 ++++++++ gst-libs/gst/gl/viv-fb/gstgldisplay_viv_fb.h | 67 +++++ .../gst/gl/viv-fb/gstglwindow_viv_fb_egl.c | 246 ++++++++++++++++++ .../gst/gl/viv-fb/gstglwindow_viv_fb_egl.h | 66 +++++ 10 files changed, 588 insertions(+), 1 deletion(-) create mode 100644 gst-libs/gst/gl/viv-fb/Makefile.am create mode 100644 gst-libs/gst/gl/viv-fb/gstgldisplay_viv_fb.c create mode 100644 gst-libs/gst/gl/viv-fb/gstgldisplay_viv_fb.h create mode 100644 gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.c create mode 100644 gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.h diff --git a/configure.ac b/configure.ac index 2fa8dd67ab..2f69e89633 100644 --- a/configure.ac +++ b/configure.ac @@ -677,6 +677,7 @@ HAVE_GL=no HAVE_GLES2=no HAVE_GLES3_H=no HAVE_WAYLAND_EGL=no +HAVE_VIV_FB_EGL=no HAVE_EGL_RPI=no @@ -714,6 +715,37 @@ case $host in old_LIBS=$LIBS old_CFLAGS=$CFLAGS + if test "x$HAVE_EGL" = "xyes"; then + AC_CHECK_LIB([EGL], [fbGetDisplay], [HAVE_VIV_FB_EGL=yes]) + fi + + dnl FIXME: Mali EGL depends on GLESv1 or GLESv2 + AC_CHECK_HEADER([EGL/fbdev_window.h], + [ + LIBS="$LIBS -lUMP" + AC_CHECK_LIB([Mali], [mali_image_create], + [ + LIBS="$LIBS -lMali" + AC_CHECK_LIB([GLESv2], [glEnable], + [ + AC_CHECK_HEADER([GLES2/gl2.h], + [ + AC_CHECK_LIB([EGL], [eglGetProcAddress], + [ + AC_CHECK_HEADER([EGL/egl.h], + [ + HAVE_EGL=yes + HAVE_GLES2=yes + EGL_LIBS="-lMali -lUMP" + EGL_CFLAGS="" + AC_DEFINE(USE_EGL_MALI_FB, [1], [Use Mali FB EGL platform]) + ]) + ]) + ]) + ]) + ]) + ]) + dnl FIXME: EGL of RPi depends on GLESv1 or GLESv2 dnl FIXME: GLESv2 of RPi depends on EGL... WTF! LIBS="$LIBS -lvcos -lvchiq_arm" @@ -993,6 +1025,16 @@ case $host in fi fi + if test "x$HAVE_VIV_FB_EGL" = "xyes"; then + if test "x$NEED_EGL" = "xno" -o "x$HAVE_EGL" = "xno"; then + AC_MSG_WARN([EGL is required by the Vivante EGL FB backend]) + else + HAVE_WINDOW_VIV_FB=yes + GL_LIBS="$GL_LIBS" + GL_CFLAGS="$GL_CFLAGS" + fi + fi + if test "x$HAVE_EGL_RPI" = "xyes"; then if test "x$NEED_DISPMANX" != "xno"; then HAVE_WINDOW_DISPMANX=yes @@ -1007,7 +1049,7 @@ case $host in fi else if test "x$NEED_EGL" != "xno"; then - if test "x$HAVE_WINDOW_WAYLAND" = "xyes" -o "x$HAVE_WINDOW_X11" = "xyes" -o "x$HAVE_WINDOW_DISPMANX" = "xyes"; then + if test "x$HAVE_WINDOW_WAYLAND" = "xyes" -o "x$HAVE_WINDOW_X11" = "xyes" -o "x$HAVE_WINDOW_DISPMANX" = "xyes" -o "x$HAVE_WINDOW_VIV_FB" = "xyes"; then GL_LIBS="$GL_LIBS -lEGL $EGL_LIBS" GL_CFLAGS="$GL_CFLAGS $EGL_CFLAGS" USE_EGL=yes @@ -1159,6 +1201,7 @@ GST_GL_HAVE_WINDOW_WAYLAND=0 GST_GL_HAVE_WINDOW_ANDROID=0 GST_GL_HAVE_WINDOW_DISPMANX=0 GST_GL_HAVE_WINDOW_EAGL=0 +GST_GL_HAVE_WINDOW_VIV_FB=0 if test "x$HAVE_WINDOW_X11" = "xyes"; then GL_WINDOWS="x11 $GL_WINDOWS" @@ -1188,6 +1231,10 @@ if test "x$HAVE_WINDOW_EAGL" = "xyes"; then GL_WINDOWS="eagl $GL_WINDOWS" GST_GL_HAVE_WINDOW_EAGL=1 fi +if test "x$HAVE_WINDOW_VIV_FB" = "xyes"; then + GL_WINDOWS="viv-fb $GL_WINDOWS" + GST_GL_HAVE_WINDOW_VIV_FB=1 +fi GL_CONFIG_DEFINES="$GL_CONFIG_DEFINES #define GST_GL_HAVE_WINDOW_X11 $GST_GL_HAVE_WINDOW_X11 @@ -1197,6 +1244,7 @@ GL_CONFIG_DEFINES="$GL_CONFIG_DEFINES #define GST_GL_HAVE_WINDOW_ANDROID $GST_GL_HAVE_WINDOW_ANDROID #define GST_GL_HAVE_WINDOW_DISPMANX $GST_GL_HAVE_WINDOW_DISPMANX #define GST_GL_HAVE_WINDOW_EAGL $GST_GL_HAVE_WINDOW_EAGL +#define GST_GL_HAVE_WINDOW_VIV_FB $GST_GL_HAVE_WINDOW_VIV_FB " dnl PLATFORM's @@ -1272,6 +1320,7 @@ if test "x$GL_APIS" = "x" -o "x$GL_PLATFORMS" = "x" -o "x$GL_WINDOWS" = "x"; the HAVE_WINDOW_ANDROID=no HAVE_WINDOW_COCOA=no HAVE_WINDOW_EAGL=no + HAVE_WINDOW_VIV_FB=no fi AC_SUBST(GL_APIS) @@ -1290,6 +1339,7 @@ AM_CONDITIONAL(HAVE_WINDOW_DISPMANX, test "x$HAVE_WINDOW_DISPMANX" = "xyes") AM_CONDITIONAL(HAVE_WINDOW_WAYLAND, test "x$HAVE_WINDOW_WAYLAND" = "xyes") AM_CONDITIONAL(HAVE_WINDOW_ANDROID, test "x$HAVE_WINDOW_ANDROID" = "xyes") AM_CONDITIONAL(HAVE_WINDOW_EAGL, test "x$HAVE_WINDOW_EAGL" = "xyes") +AM_CONDITIONAL(HAVE_WINDOW_VIV_FB, test "x$HAVE_WINDOW_VIV_FB" = "xyes") AM_CONDITIONAL(USE_OPENGL, test "x$USE_OPENGL" = "xyes") AM_CONDITIONAL(USE_GLES2, test "x$USE_GLES2" = "xyes") @@ -3522,6 +3572,7 @@ gst-libs/gst/gl/egl/Makefile gst-libs/gst/gl/wayland/Makefile gst-libs/gst/gl/win32/Makefile gst-libs/gst/gl/x11/Makefile +gst-libs/gst/gl/viv-fb/Makefile gst-libs/gst/insertbin/Makefile gst-libs/gst/interfaces/Makefile gst-libs/gst/codecparsers/Makefile diff --git a/gst-libs/gst/gl/Makefile.am b/gst-libs/gst/gl/Makefile.am index 9b21785dd7..89f925391d 100644 --- a/gst-libs/gst/gl/Makefile.am +++ b/gst-libs/gst/gl/Makefile.am @@ -119,6 +119,11 @@ SUBDIRS += eagl libgstgl_@GST_API_VERSION@_la_LIBADD += eagl/libgstgl-eagl.la endif +if HAVE_WINDOW_VIV_FB +SUBDIRS += viv-fb +libgstgl_@GST_API_VERSION@_la_LIBADD += viv-fb/libgstgl-viv-fb.la +endif + if USE_EGL SUBDIRS += egl libgstgl_@GST_API_VERSION@_la_LIBADD += egl/libgstgl-egl.la diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c index 34a6567b25..299eca63c4 100644 --- a/gst-libs/gst/gl/gstgldisplay.c +++ b/gst-libs/gst/gl/gstgldisplay.c @@ -70,6 +70,9 @@ #include #include #endif +#if GST_GL_HAVE_WINDOW_VIV_FB +#include +#endif GST_DEBUG_CATEGORY_STATIC (gst_context); GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug); @@ -296,6 +299,19 @@ gst_gl_display_new (void) if (!display && (!user_choice || g_strstr_len (user_choice, 7, "wayland"))) display = GST_GL_DISPLAY (gst_gl_display_wayland_new (NULL)); #endif +#if GST_GL_HAVE_WINDOW_VIV_FB + if (!display && (!user_choice || g_strstr_len (user_choice, 2, "viv-fb"))) { + const gchar *disp_idx_str = NULL; + gint disp_idx = 0; + disp_idx_str = g_getenv ("GST_GL_VIV_FB"); + if (disp_idx_str) { + gint64 v = g_ascii_strtoll (disp_idx_str, NULL, 10); + if (v >= G_MININT && v <= G_MAXINT) + disp_idx = v; + } + display = GST_GL_DISPLAY (gst_gl_display_viv_fb_new (disp_idx)); + } +#endif #if GST_GL_HAVE_PLATFORM_EGL if (!display && (!platform_choice || g_strstr_len (platform_choice, 3, "egl"))) diff --git a/gst-libs/gst/gl/gstgldisplay.h b/gst-libs/gst/gl/gstgldisplay.h index 2dd275d0d4..deac9dfe4b 100644 --- a/gst-libs/gst/gl/gstgldisplay.h +++ b/gst-libs/gst/gl/gstgldisplay.h @@ -61,6 +61,7 @@ typedef enum GST_GL_DISPLAY_TYPE_WIN32 = (1 << 3), GST_GL_DISPLAY_TYPE_DISPMANX = (1 << 4), GST_GL_DISPLAY_TYPE_EGL = (1 << 5), + GST_GL_DISPLAY_TYPE_VIV_FB = (1 << 6), GST_GL_DISPLAY_TYPE_ANY = G_MAXUINT32 } GstGLDisplayType; diff --git a/gst-libs/gst/gl/gstglwindow.c b/gst-libs/gst/gl/gstglwindow.c index b2fd04496c..c1dae2d17d 100644 --- a/gst-libs/gst/gl/gstglwindow.c +++ b/gst-libs/gst/gl/gstglwindow.c @@ -58,6 +58,9 @@ #if GST_GL_HAVE_WINDOW_EAGL #include "eagl/gstglwindow_eagl.h" #endif +#if GST_GL_HAVE_WINDOW_VIV_FB +#include "viv-fb/gstglwindow_viv_fb_egl.h" +#endif #if GST_GL_HAVE_WINDOW_DISPMANX #include "dispmanx/gstglwindow_dispmanx_egl.h" #endif @@ -271,6 +274,11 @@ gst_gl_window_new (GstGLDisplay * display) if (!window && (!user_choice || g_strstr_len (user_choice, 4, "eagl"))) window = GST_GL_WINDOW (gst_gl_window_eagl_new (display)); #endif +#if GST_GL_HAVE_WINDOW_VIV_FB + if (!window && (!user_choice || g_strstr_len (user_choice, 2, "viv-fb"))) + window = GST_GL_WINDOW (gst_gl_window_viv_fb_egl_new (display)); +#endif + if (!window) { /* subclass returned a NULL window */ GST_WARNING ("Could not create window. user specified %s, creating dummy" diff --git a/gst-libs/gst/gl/viv-fb/Makefile.am b/gst-libs/gst/gl/viv-fb/Makefile.am new file mode 100644 index 0000000000..22294b1302 --- /dev/null +++ b/gst-libs/gst/gl/viv-fb/Makefile.am @@ -0,0 +1,25 @@ +## Process this file with automake to produce Makefile.in + +noinst_LTLIBRARIES = libgstgl-viv-fb.la + +libgstgl_viv_fb_la_SOURCES = \ + gstgldisplay_viv_fb.c \ + gstglwindow_viv_fb_egl.c + +noinst_HEADERS = \ + gstgldisplay_viv_fb.h \ + gstglwindow_viv_fb_egl.h + +libgstgl_viv_fbincludedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/gl/viv-fb + +libgstgl_viv_fb_la_CFLAGS = \ + -I$(top_srcdir)/gst-libs \ + -I$(top_builddir)/gst-libs \ + $(GL_CFLAGS) \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(GST_CFLAGS) + +libgstgl_viv_fb_la_LDFLAGS = \ + $(GST_LIB_LDFLAGS) \ + $(GST_ALL_LDFLAGS) diff --git a/gst-libs/gst/gl/viv-fb/gstgldisplay_viv_fb.c b/gst-libs/gst/gl/viv-fb/gstgldisplay_viv_fb.c new file mode 100644 index 0000000000..6820203180 --- /dev/null +++ b/gst-libs/gst/gl/viv-fb/gstgldisplay_viv_fb.c @@ -0,0 +1,102 @@ +/* + * GStreamer + * Copyright (C) 2014 Matthew Waters + * Copyright (C) 2015 Freescale Semiconductor + * Copyright (C) 2017 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstgldisplay_viv_fb.h" + +GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug); +#define GST_CAT_DEFAULT gst_gl_display_debug + +G_DEFINE_TYPE (GstGLDisplayVivFB, gst_gl_display_viv_fb, GST_TYPE_GL_DISPLAY); + +static void gst_gl_display_viv_fb_finalize (GObject * object); +static guintptr gst_gl_display_viv_fb_get_handle (GstGLDisplay * display); + +static void +gst_gl_display_viv_fb_class_init (GstGLDisplayVivFBClass * klass) +{ + GST_GL_DISPLAY_CLASS (klass)->get_handle = + GST_DEBUG_FUNCPTR (gst_gl_display_viv_fb_get_handle); + + G_OBJECT_CLASS (klass)->finalize = gst_gl_display_viv_fb_finalize; +} + +static void +gst_gl_display_viv_fb_init (GstGLDisplayVivFB * display_viv_fb) +{ + GstGLDisplay *display = (GstGLDisplay *) display_viv_fb; + + display->type = GST_GL_DISPLAY_TYPE_VIV_FB; + + display_viv_fb->disp_idx = 0; + display_viv_fb->display = NULL; +} + +static void +gst_gl_display_viv_fb_finalize (GObject * object) +{ + GstGLDisplayVivFB *display_viv_fb = GST_GL_DISPLAY_VIV_FB (object); + + if (display_viv_fb->display) + fbDestroyDisplay (display_viv_fb->display); + + G_OBJECT_CLASS (gst_gl_display_viv_fb_parent_class)->finalize (object); +} + +/** + * gst_gl_display_viv_fb_new: + * @disp_idx: a display index + * + * Create a new #GstGLDisplayVivFB from the FB display index. + * + * Returns: (transfer full): a new #GstGLDisplayVivFB or %NULL + */ +GstGLDisplayVivFB * +gst_gl_display_viv_fb_new (gint disp_idx) +{ + GstGLDisplayVivFB *display; + + GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay"); + + GST_DEBUG ("creating Vivante FB EGL display %d", disp_idx); + + display = g_object_new (GST_TYPE_GL_DISPLAY_VIV_FB, NULL); + display->disp_idx = disp_idx; + display->display = fbGetDisplayByIndex (display->disp_idx); + if (!display->display) { + GST_ERROR ("Failed to open Vivante FB display %d", disp_idx); + return NULL; + } + + GST_DEBUG ("Created Vivante FB EGL display %p", (gpointer) display->display); + + return display; +} + +static guintptr +gst_gl_display_viv_fb_get_handle (GstGLDisplay * display) +{ + return (guintptr) GST_GL_DISPLAY_VIV_FB (display)->display; +} diff --git a/gst-libs/gst/gl/viv-fb/gstgldisplay_viv_fb.h b/gst-libs/gst/gl/viv-fb/gstgldisplay_viv_fb.h new file mode 100644 index 0000000000..9ce1dce849 --- /dev/null +++ b/gst-libs/gst/gl/viv-fb/gstgldisplay_viv_fb.h @@ -0,0 +1,67 @@ +/* + * GStreamer + * Copyright (C) 2014 Matthew Waters + * Copyright (C) 2015 Freescale Semiconductor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_GL_DISPLAY_VIV_FB_H__ +#define __GST_GL_DISPLAY_VIV_FB_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +GType gst_gl_display_viv_fb_get_type (void); + +#define GST_TYPE_GL_DISPLAY_VIV_FB (gst_gl_display_viv_fb_get_type()) +#define GST_GL_DISPLAY_VIV_FB(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_DISPLAY_VIV_FB,GstGLDisplayVivFB)) +#define GST_GL_DISPLAY_VIV_FB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_GL_DISPLAY_VIV_FB,GstGLDisplayVivFBClass)) +#define GST_IS_GL_DISPLAY_VIV_FB(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_DISPLAY_VIV_FB)) +#define GST_IS_GL_DISPLAY_VIV_FB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_GL_DISPLAY_VIV_FB)) +#define GST_GL_DISPLAY_VIV_FB_CAST(obj) ((GstGLDisplayVivFB*)(obj)) + +typedef struct _GstGLDisplayVivFB GstGLDisplayVivFB; +typedef struct _GstGLDisplayVivFBClass GstGLDisplayVivFBClass; + +/** + * GstGLDisplayVivFB: + * + * the contents of a #GstGLDisplayVivFB are private and should only be accessed + * through the provided API + */ +struct _GstGLDisplayVivFB +{ + GstGLDisplay parent; + + /* */ + gint disp_idx; + EGLNativeDisplayType display; +}; + +struct _GstGLDisplayVivFBClass +{ + GstGLDisplayClass object_class; +}; + +GstGLDisplayVivFB *gst_gl_display_viv_fb_new (gint disp_idx); + +G_END_DECLS + +#endif /* __GST_GL_DISPLAY_VIV_FB_H__ */ diff --git a/gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.c b/gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.c new file mode 100644 index 0000000000..6d0598b5d6 --- /dev/null +++ b/gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.c @@ -0,0 +1,246 @@ +/* + * GStreamer + * Copyright (C) 2008 Julien Isorce + * Copyright (C) 2012 Matthew Waters + * Copyright (C) 2015 Freescale Semiconductor + * Copyright (C) 2017 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "../gstgl_fwd.h" +#include + +#include "gstglwindow_viv_fb_egl.h" + +#define GST_CAT_DEFAULT gst_gl_window_debug + +#define gst_gl_window_viv_fb_egl_parent_class parent_class +G_DEFINE_TYPE (GstGLWindowVivFBEGL, gst_gl_window_viv_fb_egl, + GST_GL_TYPE_WINDOW); + +static guintptr gst_gl_window_viv_fb_egl_get_window_handle (GstGLWindow * + window); +static guintptr gst_gl_window_viv_fb_egl_get_display (GstGLWindow * window); +static void gst_gl_window_viv_fb_egl_set_window_handle (GstGLWindow * window, + guintptr handle); +static void gst_gl_window_viv_fb_egl_close (GstGLWindow * window); +static gboolean gst_gl_window_viv_fb_egl_open (GstGLWindow * window, + GError ** error); +static void gst_gl_window_viv_fb_egl_draw (GstGLWindow * window); +static gboolean +gst_gl_window_viv_fb_egl_set_render_rectangle (GstGLWindow * window, + gint x, gint y, gint width, gint height); + +static void +gst_gl_window_viv_fb_egl_class_init (GstGLWindowVivFBEGLClass * klass) +{ + GstGLWindowClass *window_class = (GstGLWindowClass *) klass; + + window_class->get_window_handle = + GST_DEBUG_FUNCPTR (gst_gl_window_viv_fb_egl_get_window_handle); + window_class->get_display = + GST_DEBUG_FUNCPTR (gst_gl_window_viv_fb_egl_get_display); + window_class->set_window_handle = + GST_DEBUG_FUNCPTR (gst_gl_window_viv_fb_egl_set_window_handle); + window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_viv_fb_egl_close); + window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_viv_fb_egl_open); + window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_viv_fb_egl_draw); + window_class->set_render_rectangle = + GST_DEBUG_FUNCPTR (gst_gl_window_viv_fb_egl_set_render_rectangle); +} + +static void +gst_gl_window_viv_fb_egl_init (GstGLWindowVivFBEGL * window) +{ +} + +/* Must be called in the gl thread */ +GstGLWindowVivFBEGL * +gst_gl_window_viv_fb_egl_new (GstGLDisplay * display) +{ + if ((gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_VIV_FB) == + 0) + /* we require a Vivante FB display to create windows */ + return NULL; + + return g_object_new (GST_GL_TYPE_WINDOW_VIV_FB_EGL, NULL); +} + +static void +gst_gl_window_viv_fb_egl_close (GstGLWindow * window) +{ + GstGLWindowVivFBEGL *window_egl = GST_GL_WINDOW_VIV_FB_EGL (window); + + if (window_egl->win_id && !window_egl->external_window) { + fbDestroyWindow (window_egl->win_id); + window_egl->win_id = 0; + } + + GST_GL_WINDOW_CLASS (parent_class)->close (window); +} + +static guintptr +gst_gl_window_viv_fb_egl_get_display (GstGLWindow * window) +{ + return gst_gl_display_get_handle (window->display); +} + +static gboolean +gst_gl_window_viv_fb_egl_open (GstGLWindow * window, GError ** error) +{ + GstGLWindowVivFBEGL *window_egl = GST_GL_WINDOW_VIV_FB_EGL (window); + EGLNativeDisplayType display; + + display = (EGLNativeDisplayType) gst_gl_window_get_display (window); + + window_egl->win_id = fbCreateWindow (display, -1, -1, 0, 0); + window_egl->external_window = FALSE; + if (!window_egl->win_id) { + g_set_error (error, GST_GL_WINDOW_ERROR, + GST_GL_WINDOW_ERROR_RESOURCE_UNAVAILABLE, "Can't create window"); + return FALSE; + } + + fbGetWindowGeometry (window_egl->win_id, NULL, NULL, + &window_egl->window_width, &window_egl->window_height); + window_egl->render_rectangle.x = 0; + window_egl->render_rectangle.y = 0; + window_egl->render_rectangle.w = window_egl->window_width; + window_egl->render_rectangle.h = window_egl->window_height; + gst_gl_window_resize (window, window_egl->window_width, + window_egl->window_height); + + GST_DEBUG + ("Opened Vivante FB display succesfully, resolution is (%dx%d), display %p, window %p.", + window_egl->window_width, window_egl->window_height, (gpointer) display, + (gpointer) window_egl->win_id); + + return GST_GL_WINDOW_CLASS (parent_class)->open (window, error); +} + +static guintptr +gst_gl_window_viv_fb_egl_get_window_handle (GstGLWindow * window) +{ + return (guintptr) GST_GL_WINDOW_VIV_FB_EGL (window)->win_id; +} + +static void +gst_gl_window_viv_fb_egl_set_window_handle (GstGLWindow * window, + guintptr handle) +{ + GstGLWindowVivFBEGL *window_egl = GST_GL_WINDOW_VIV_FB_EGL (window); + gint width, height; + + if (window_egl->win_id) + fbDestroyWindow (window_egl->win_id); + window_egl->win_id = (EGLNativeWindowType) handle; + window_egl->external_window = handle != 0; + + fbGetWindowGeometry (window_egl->win_id, NULL, NULL, &width, &height); + gst_gl_window_resize (window, width, height); +} + +static void +draw_cb (gpointer data) +{ + GstGLWindowVivFBEGL *window_egl = data; + GstGLWindow *window = GST_GL_WINDOW (window_egl); + GstGLContext *context = gst_gl_window_get_context (window); + GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context); + const GstGLFuncs *gl; + gint viewport_dim[4]; + + gl = context->gl_vtable; + + if (window->queue_resize) { + guint width, height; + + gst_gl_window_get_surface_dimensions (window, &width, &height); + gst_gl_window_resize (window, width, height); + + gl->GetIntegerv (GL_VIEWPORT, viewport_dim); + viewport_dim[0] += window_egl->render_rectangle.x; + viewport_dim[1] -= window_egl->render_rectangle.y; + viewport_dim[2] -= window_egl->render_rectangle.x; + viewport_dim[3] -= window_egl->render_rectangle.y; + gl->Viewport (viewport_dim[0], + viewport_dim[1], viewport_dim[2], viewport_dim[3]); + } + + if (window->draw) + window->draw (window->draw_data); + + context_class->swap_buffers (context); + + gst_object_unref (context); +} + +static void +gst_gl_window_viv_fb_egl_draw (GstGLWindow * window) +{ + gst_gl_window_send_message (window, (GstGLWindowCB) draw_cb, window); +} + +typedef struct +{ + GstGLWindowVivFBEGL *window_egl; + GstVideoRectangle rect; +} SetRenderRectangleData; + +static void +_free_set_render_rectangle (SetRenderRectangleData * render) +{ + if (render) { + if (render->window_egl) + gst_object_unref (render->window_egl); + g_free (render); + } +} + +static void +_set_render_rectangle (gpointer data) +{ + SetRenderRectangleData *render = data; + + GST_LOG_OBJECT (render->window_egl, "setting render rectangle %i,%i+%ix%i", + render->rect.x, render->rect.y, render->rect.w, render->rect.h); + + render->window_egl->render_rectangle = render->rect; + gst_gl_window_resize (GST_GL_WINDOW (render->window_egl), render->rect.w, + render->rect.h); +} + +static gboolean +gst_gl_window_viv_fb_egl_set_render_rectangle (GstGLWindow * window, + gint x, gint y, gint width, gint height) +{ + GstGLWindowVivFBEGL *window_egl = GST_GL_WINDOW_VIV_FB_EGL (window); + SetRenderRectangleData *render; + + render = g_new0 (SetRenderRectangleData, 1); + render->window_egl = gst_object_ref (window_egl); + render->rect.x = x; + render->rect.y = y; + render->rect.w = width; + render->rect.h = height; + + gst_gl_window_send_message_async (window, + (GstGLWindowCB) _set_render_rectangle, render, + (GDestroyNotify) _free_set_render_rectangle); + + return TRUE; +} diff --git a/gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.h b/gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.h new file mode 100644 index 0000000000..5ce15ac559 --- /dev/null +++ b/gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.h @@ -0,0 +1,66 @@ +/* + * GStreamer + * Copyright (C) 2012 Matthew Waters + * Copyright (C) 2015 Freescale Semiconductor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_GL_WINDOW_VIV_FB_EGL_H__ +#define __GST_GL_WINDOW_VIV_FB_EGL_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_GL_TYPE_WINDOW_VIV_FB_EGL (gst_gl_window_viv_fb_egl_get_type()) +#define GST_GL_WINDOW_VIV_FB_EGL(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_GL_TYPE_WINDOW_VIV_FB_EGL, GstGLWindowVivFBEGL)) +#define GST_GL_WINDOW_VIV_FB_EGL_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_GL_TYPE_WINDOW_VIV_FB_EGL, GstGLWindowVivFBEGLClass)) +#define GST_GL_IS_WINDOW_VIV_FB_EGL(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_GL_TYPE_WINDOW_VIV_FB_EGL)) +#define GST_GL_IS_WINDOW_VIV_FB_EGL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_GL_TYPE_WINDOW_VIV_FB_EGL)) +#define GST_GL_WINDOW_VIV_FB_EGL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_GL_TYPE_WINDOW_VIV_FB_EGL, GstGLWindowVivFBEGL_Class)) + +typedef struct _GstGLWindowVivFBEGL GstGLWindowVivFBEGL; +typedef struct _GstGLWindowVivFBEGLClass GstGLWindowVivFBEGLClass; + +struct _GstGLWindowVivFBEGL { + /*< private >*/ + GstGLWindow parent; + + /* */ + EGLNativeWindowType win_id; + gboolean external_window; + gint window_width, window_height; + + GstVideoRectangle render_rectangle; +}; + +struct _GstGLWindowVivFBEGLClass { + /*< private >*/ + GstGLWindowClass parent_class; + + /*< private >*/ + gpointer _reserved[GST_PADDING]; +}; + +GType gst_gl_window_viv_fb_egl_get_type (void); + +GstGLWindowVivFBEGL * gst_gl_window_viv_fb_egl_new (GstGLDisplay * display); + +G_END_DECLS + +#endif /* __GST_GL_WINDOW_VIV_FB_EGL_H__ */