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: 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 --- 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-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.c | 246 ++++++++++++++++++++++++ gst-libs/gst/gl/viv-fb/gstglwindow_viv_fb_egl.h | 66 +++++++ 5 files changed, 506 insertions(+) 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 (limited to 'gst-libs/gst/gl/viv-fb') 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 000000000..22294b130 --- /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 000000000..682020318 --- /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 000000000..9ce1dce84 --- /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 000000000..6d0598b5d --- /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 000000000..5ce15ac55 --- /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__ */ -- cgit v1.2.1