diff options
author | Julien Isorce <julien.isorce@collabora.co.uk> | 2013-08-30 14:12:37 +0100 |
---|---|---|
committer | Matthew Waters <ystreet00@gmail.com> | 2014-03-15 18:37:01 +0100 |
commit | 561a71c2444c8e1d8d49b32e470d340383468515 (patch) | |
tree | 6fd1a0633a451597f56e62fe2c92db783e50c795 | |
parent | f93b804071f46e83ef739fdfef2f94f6b458be21 (diff) |
[803/906] raspberrypi: add support for dispmanx
See https://bugzilla.gnome.org/show_bug.cgi?id=703342
-rw-r--r-- | gst-libs/gst/gl/Makefile.am | 7 | ||||
-rw-r--r-- | gst-libs/gst/gl/dispmanx/Makefile.am | 21 | ||||
-rw-r--r-- | gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c | 344 | ||||
-rw-r--r-- | gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.h | 74 | ||||
-rw-r--r-- | gst-libs/gst/gl/egl/gstglcontext_egl.c | 3 | ||||
-rw-r--r-- | gst-libs/gst/gl/gstglcontext.c | 36 | ||||
-rw-r--r-- | gst-libs/gst/gl/gstglwindow.c | 7 |
7 files changed, 487 insertions, 5 deletions
diff --git a/gst-libs/gst/gl/Makefile.am b/gst-libs/gst/gl/Makefile.am index 09cb785a9..161967ba3 100644 --- a/gst-libs/gst/gl/Makefile.am +++ b/gst-libs/gst/gl/Makefile.am @@ -2,7 +2,7 @@ lib_LTLIBRARIES = libgstgl-@GST_API_VERSION@.la SUBDIRS = glprototypes -DIST_SUBDIRS = glprototypes android x11 win32 cocoa wayland +DIST_SUBDIRS = glprototypes android x11 win32 cocoa wayland dispmanx noinst_HEADERS = @@ -50,6 +50,11 @@ SUBDIRS += wayland libgstgl_@GST_API_VERSION@_la_LIBADD += wayland/libgstgl-wayland.la endif +if HAVE_WINDOW_DISPMANX +SUBDIRS += dispmanx +libgstgl_@GST_API_VERSION@_la_LIBADD += dispmanx/libgstgl-dispmanx.la +endif + if HAVE_WINDOW_ANDROID SUBDIRS += android libgstgl_@GST_API_VERSION@_la_LIBADD += android/libgstgl-android.la diff --git a/gst-libs/gst/gl/dispmanx/Makefile.am b/gst-libs/gst/gl/dispmanx/Makefile.am new file mode 100644 index 000000000..fd14286ea --- /dev/null +++ b/gst-libs/gst/gl/dispmanx/Makefile.am @@ -0,0 +1,21 @@ +## Process this file with automake to produce Makefile.in + +noinst_LTLIBRARIES = libgstgl-dispmanx.la + +libgstgl_dispmanx_la_SOURCES = \ + gstglwindow_dispmanx_egl.c + +noinst_HEADERS = \ + gstglwindow_dispmanx_egl.h + +libgstgl_dispmanx_la_CFLAGS = \ + -I$(top_srcdir)/gst-libs \ + $(GL_CFLAGS) \ + $(X_CFLAGS) \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(GST_CFLAGS) + +libgstgl_dispmanx_la_LDFLAGS = \ + $(GST_LIB_LDFLAGS) \ + $(GST_ALL_LDFLAGS) diff --git a/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c b/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c new file mode 100644 index 000000000..a3648e852 --- /dev/null +++ b/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c @@ -0,0 +1,344 @@ +/* + * GStreamer + * Copyright (C) 2013 Julien Isorce <julien.isorce@collabora.co.uk> + * + * 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. + */ + +#define GLIB_DISABLE_DEPRECATION_WARNINGS + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "../gstgl_fwd.h" +#include <gst/gl/gstglcontext.h> + +#include "gstglwindow_dispmanx_egl.h" + +#define GST_CAT_DEFAULT gst_gl_window_debug + +#define gst_gl_window_dispmanx_egl_parent_class parent_class +G_DEFINE_TYPE (GstGLWindowDispmanxEGL, gst_gl_window_dispmanx_egl, + GST_GL_TYPE_WINDOW); + +static guintptr gst_gl_window_dispmanx_egl_get_window_handle (GstGLWindow * + window); +static void gst_gl_window_dispmanx_egl_set_window_handle (GstGLWindow * window, + guintptr handle); +static void gst_gl_window_dispmanx_egl_draw (GstGLWindow * window, guint width, + guint height); +static void gst_gl_window_dispmanx_egl_run (GstGLWindow * window); +static void gst_gl_window_dispmanx_egl_quit (GstGLWindow * window); +static void gst_gl_window_dispmanx_egl_send_message (GstGLWindow * window, + GstGLWindowCB callback, gpointer data); +static void gst_gl_window_dispmanx_egl_close (GstGLWindow * window); +static gboolean gst_gl_window_dispmanx_egl_open (GstGLWindow * window, + GError ** error); +static guintptr gst_gl_window_dispmanx_egl_get_display (GstGLWindow * window); + + +static void window_resize (GstGLWindowDispmanxEGL * window_egl, guint width, + guint height); + +static void +gst_gl_window_dispmanx_egl_class_init (GstGLWindowDispmanxEGLClass * klass) +{ + GstGLWindowClass *window_class = (GstGLWindowClass *) klass; + + window_class->get_window_handle = + GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_get_window_handle); + window_class->set_window_handle = + GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_set_window_handle); + window_class->draw_unlocked = + GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_draw); + window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_draw); + window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_run); + window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_quit); + window_class->send_message = + GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_send_message); + window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_close); + window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_open); + window_class->get_display = + GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_get_display); +} + +static void +gst_gl_window_dispmanx_egl_init (GstGLWindowDispmanxEGL * window) +{ +} + +/* Must be called in the gl thread */ +GstGLWindowDispmanxEGL * +gst_gl_window_dispmanx_egl_new (void) +{ + GstGLWindowDispmanxEGL *window; + + GST_DEBUG ("creating Dispmanx EGL window"); + + window = g_object_new (GST_GL_TYPE_WINDOW_DISPMANX_EGL, NULL); + + gst_gl_window_set_need_lock (GST_GL_WINDOW (window), FALSE); + + window->egldisplay = EGL_DEFAULT_DISPLAY; + + window->display = 0; + window->dp_width = 0; + window->dp_height = 0; + window->native.element = 0; + window->native.width = 0; + window->native.height = 0; + + return window; +} + +static void +gst_gl_window_dispmanx_egl_close (GstGLWindow * window) +{ + GstGLWindowDispmanxEGL *window_egl; + DISPMANX_UPDATE_HANDLE_T dispman_update; + + window_egl = GST_GL_WINDOW_DISPMANX_EGL (window); + + if (window_egl->native.element) { + dispman_update = vc_dispmanx_update_start (0); + vc_dispmanx_element_remove (dispman_update, window_egl->native.element); + vc_dispmanx_update_submit_sync (dispman_update); + } + vc_dispmanx_display_close (window_egl->display); + + g_main_loop_unref (window_egl->loop); + window_egl->loop = NULL; + g_main_context_unref (window_egl->main_context); + window_egl->main_context = NULL; +} + +static gboolean +gst_gl_window_dispmanx_egl_open (GstGLWindow * window, GError ** error) +{ + GstGLWindowDispmanxEGL *window_egl = GST_GL_WINDOW_DISPMANX_EGL (window); + gint ret = graphics_get_display_size (0, &window_egl->dp_width, + &window_egl->dp_height); + if (ret < 0) { + GST_ERROR ("Can't open display"); + return FALSE; + } + GST_DEBUG ("Got display size: %dx%d\n", window_egl->dp_width, + window_egl->dp_height); + + window_egl->native.width = 0; + window_egl->native.height = 0; + window_egl->display = vc_dispmanx_display_open (0); + window_egl->native.element = 0; + + window_egl->main_context = g_main_context_new (); + window_egl->loop = g_main_loop_new (window_egl->main_context, FALSE); + + window_resize (window_egl, 16, 16); + + return TRUE; +} + +static void +gst_gl_window_dispmanx_egl_run (GstGLWindow * window) +{ + GstGLWindowDispmanxEGL *window_egl; + + window_egl = GST_GL_WINDOW_DISPMANX_EGL (window); + + GST_LOG ("starting main loop"); + g_main_loop_run (window_egl->loop); + GST_LOG ("exiting main loop"); +} + +static void +gst_gl_window_dispmanx_egl_quit (GstGLWindow * window) +{ + GstGLWindowDispmanxEGL *window_egl; + + window_egl = GST_GL_WINDOW_DISPMANX_EGL (window); + + GST_LOG ("sending quit"); + + g_main_loop_quit (window_egl->loop); + + GST_LOG ("quit sent"); +} + +typedef struct _GstGLMessage +{ + GMutex lock; + GCond cond; + gboolean fired; + + GstGLWindowCB callback; + gpointer data; +} GstGLMessage; + +static gboolean +_run_message (GstGLMessage * message) +{ + g_mutex_lock (&message->lock); + + if (message->callback) + message->callback (message->data); + + message->fired = TRUE; + g_cond_signal (&message->cond); + g_mutex_unlock (&message->lock); + + return FALSE; +} + +static void +gst_gl_window_dispmanx_egl_send_message (GstGLWindow * window, + GstGLWindowCB callback, gpointer data) +{ + GstGLWindowDispmanxEGL *window_egl; + GstGLMessage message; + + window_egl = GST_GL_WINDOW_DISPMANX_EGL (window); + message.callback = callback; + message.data = data; + message.fired = FALSE; + g_mutex_init (&message.lock); + g_cond_init (&message.cond); + + g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message, + &message); + + g_mutex_lock (&message.lock); + + while (!message.fired) + g_cond_wait (&message.cond, &message.lock); + g_mutex_unlock (&message.lock); +} + +static guintptr +gst_gl_window_dispmanx_egl_get_window_handle (GstGLWindow * window) +{ + return (guintptr) & GST_GL_WINDOW_DISPMANX_EGL (window)->native; +} + +static void +gst_gl_window_dispmanx_egl_set_window_handle (GstGLWindow * window, + guintptr handle) +{ +} + +static void +window_resize (GstGLWindowDispmanxEGL * window_egl, guint width, guint height) +{ + GST_DEBUG ("resizing window from %ux%u to %ux%u", + window_egl->native.width, window_egl->native.height, width, height); + + if (window_egl->display) { + VC_RECT_T dst_rect; + VC_RECT_T src_rect; + GstVideoRectangle src, dst, res; + DISPMANX_UPDATE_HANDLE_T dispman_update; + + /* Center width*height frame inside dp_width*dp_height */ + src.w = width; + src.h = height; + src.x = src.y = 0; + dst.w = window_egl->dp_width; + dst.h = window_egl->dp_height; + dst.x = dst.y = 0; + gst_video_sink_center_rect (src, dst, &res, TRUE); + + dst_rect.x = res.x; + dst_rect.y = res.y; + dst_rect.width = res.w; + dst_rect.height = res.h; + + src_rect.x = 0; + src_rect.y = 0; + src_rect.width = width << 16; + src_rect.height = height << 16; + + dispman_update = vc_dispmanx_update_start (0); + + if (window_egl->native.element) { + vc_dispmanx_element_remove (dispman_update, window_egl->native.element); + } + + window_egl->native.element = vc_dispmanx_element_add (dispman_update, + window_egl->display, 0, &dst_rect, 0, &src_rect, + DISPMANX_PROTECTION_NONE, 0, 0, 0); + + vc_dispmanx_update_submit_sync (dispman_update); + + if (GST_GL_WINDOW (window_egl)->resize) + GST_GL_WINDOW (window_egl)-> + resize (GST_GL_WINDOW (window_egl)->resize_data, width, height); + } + + window_egl->native.width = width; + window_egl->native.height = height; +} + +struct draw +{ + GstGLWindowDispmanxEGL *window; + guint width, height; +}; + +static void +draw_cb (gpointer data) +{ + struct draw *draw_data = data; + GstGLWindowDispmanxEGL *window_egl = draw_data->window; + GstGLWindow *window = GST_GL_WINDOW (window_egl); + GstGLContext *context = gst_gl_window_get_context (window); + GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context); + + if (window_egl->native.width != draw_data->width + || window_egl->native.height != draw_data->height) { + GST_DEBUG ("dimensions don't match, attempting resize"); + window_resize (window_egl, draw_data->width, draw_data->height); + } + + if (window->draw) + window->draw (window->draw_data); + + context_class->swap_buffers (context); + + gst_object_unref (context); +} + +static void +gst_gl_window_dispmanx_egl_draw (GstGLWindow * window, guint width, + guint height) +{ + struct draw draw_data; + + draw_data.window = GST_GL_WINDOW_DISPMANX_EGL (window); + draw_data.width = width; + draw_data.height = height; + + gst_gl_window_send_message (window, (GstGLWindowCB) draw_cb, &draw_data); +} + +static guintptr +gst_gl_window_dispmanx_egl_get_display (GstGLWindow * window) +{ + GstGLWindowDispmanxEGL *window_egl; + + window_egl = GST_GL_WINDOW_DISPMANX_EGL (window); + + return (guintptr) window_egl->egldisplay; +} diff --git a/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.h b/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.h new file mode 100644 index 000000000..72e8848fe --- /dev/null +++ b/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.h @@ -0,0 +1,74 @@ +/* + * GStreamer + * Copyright (C) 2013 Julien Isorce <julien.isorce@collabora.co.uk> + * + * 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_DISPMANX_EGL_H__ +#define __GST_GL_WINDOW_DISPMANX_EGL_H__ + +#include <bcm_host.h> +#include <gst/video/gstvideosink.h> + +#include <EGL/egl.h> + +#include <gst/gl/gl.h> + +G_BEGIN_DECLS + +#define GST_GL_TYPE_WINDOW_DISPMANX_EGL (gst_gl_window_dispmanx_egl_get_type()) +#define GST_GL_WINDOW_DISPMANX_EGL(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_GL_TYPE_WINDOW_DISPMANX_EGL, GstGLWindowDispmanxEGL)) +#define GST_GL_WINDOW_DISPMANX_EGL_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_GL_TYPE_WINDOW_DISPMANX_EGL, GstGLWindowDispmanxEGLClass)) +#define GST_GL_IS_WINDOW_DISPMANX_EGL(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_GL_TYPE_WINDOW_DISPMANX_EGL)) +#define GST_GL_IS_WINDOW_DISPMANX_EGL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_GL_TYPE_WINDOW_DISPMANX_EGL)) +#define GST_GL_WINDOW_DISPMANX_EGL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_GL_TYPE_WINDOW_DISPMANX_EGL, GstGLWindowDispmanxEGL_Class)) + +typedef struct _GstGLWindowDispmanxEGL GstGLWindowDispmanxEGL; +typedef struct _GstGLWindowDispmanxEGLClass GstGLWindowDispmanxEGLClass; + +struct _GstGLWindowDispmanxEGL { + /*< private >*/ + GstGLWindow parent; + + EGLDisplay egldisplay; + + DISPMANX_DISPLAY_HANDLE_T display; + uint32_t dp_height; + uint32_t dp_width; + EGL_DISPMANX_WINDOW_T native; + + GMainContext *main_context; + GMainLoop *loop; + + gpointer _reserved[GST_PADDING]; +}; + +struct _GstGLWindowDispmanxEGLClass { + /*< private >*/ + GstGLWindowClass parent_class; + + /*< private >*/ + gpointer _reserved[GST_PADDING]; +}; + +GType gst_gl_window_dispmanx_egl_get_type (void); + +GstGLWindowDispmanxEGL * gst_gl_window_dispmanx_egl_new (void); + +G_END_DECLS + +#endif /* __GST_GL_WINDOW_X11_H__ */ diff --git a/gst-libs/gst/gl/egl/gstglcontext_egl.c b/gst-libs/gst/gl/egl/gstglcontext_egl.c index 6864dd0db..bb7feece6 100644 --- a/gst-libs/gst/gl/egl/gstglcontext_egl.c +++ b/gst-libs/gst/gl/egl/gstglcontext_egl.c @@ -340,7 +340,8 @@ gst_gl_context_egl_create_context (GstGLContext * context, #endif } - window_handle = gst_gl_window_get_window_handle (window); + window_handle = + (EGLNativeWindowType) gst_gl_window_get_window_handle (window); if (window_handle) { egl->egl_surface = diff --git a/gst-libs/gst/gl/gstglcontext.c b/gst-libs/gst/gl/gstglcontext.c index f459de783..e14c1870c 100644 --- a/gst-libs/gst/gl/gstglcontext.c +++ b/gst-libs/gst/gl/gstglcontext.c @@ -250,16 +250,46 @@ gpointer gst_gl_context_default_get_proc_address (GstGLContext * context, const gchar * name) { - static GModule *module = NULL; gpointer ret = NULL; +#ifdef USE_EGL_RPI + static GModule *module_egl = NULL; + static GModule *module_glesv2 = NULL; + + if (!module_egl) + module_egl = g_module_open ("/opt/vc/lib/libEGL.so", G_MODULE_BIND_LAZY); + + if (module_egl) { + if (!g_module_symbol (module_egl, name, &ret)) { + ret = NULL; + } + } + + if (ret) + return ret; + + if (!module_glesv2) + module_glesv2 = + g_module_open ("/opt/vc/lib/libGLESv2.so", G_MODULE_BIND_LAZY); + + if (module_glesv2) { + if (!g_module_symbol (module_glesv2, name, &ret)) { + return NULL; + } + } +#else + static GModule *module = NULL; + if (!module) - module = g_module_open (NULL, G_MODULE_BIND_LAZY); + module = g_module_open (NULL /*"/opt/vc/lib/libGLESv2.so" */ , + G_MODULE_BIND_LAZY); if (module) { - if (!g_module_symbol (module, name, &ret)) + if (!g_module_symbol (module, name, &ret)) { return NULL; + } } +#endif return ret; } diff --git a/gst-libs/gst/gl/gstglwindow.c b/gst-libs/gst/gl/gstglwindow.c index 41d859ea1..929745a9c 100644 --- a/gst-libs/gst/gl/gstglwindow.c +++ b/gst-libs/gst/gl/gstglwindow.c @@ -45,6 +45,9 @@ #if GST_GL_HAVE_WINDOW_ANDROID #include "android/gstglwindow_android_egl.h" #endif +#if GST_GL_HAVE_WINDOW_DISPMANX +#include "dispmanx/gstglwindow_dispmanx_egl.h" +#endif #define USING_OPENGL(display) (display->gl_api & GST_GL_API_OPENGL) #define USING_OPENGL3(display) (display->gl_api & GST_GL_API_OPENGL3) @@ -141,6 +144,10 @@ gst_gl_window_new (GstGLDisplay * display) window = GST_GL_WINDOW (gst_gl_window_cocoa_new ()); } #endif +#if GST_GL_HAVE_WINDOW_DISPMANX + if (!window && (!user_choice || g_strstr_len (user_choice, 8, "dispmanx"))) + window = GST_GL_WINDOW (gst_gl_window_dispmanx_egl_new ()); +#endif #if GST_GL_HAVE_WINDOW_WAYLAND if (!window && (!user_choice || g_strstr_len (user_choice, 7, "wayland"))) window = GST_GL_WINDOW (gst_gl_window_wayland_egl_new ()); |