diff options
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | configure.ac | 34 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/Makefile.am | 53 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapidisplay_wayland.c | 414 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapidisplay_wayland.h | 94 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapidisplay_wayland_priv.h | 60 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapiobject_priv.h | 22 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapiwindow_wayland.c | 302 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapiwindow_wayland.h | 89 |
9 files changed, 1068 insertions, 1 deletions
@@ -4,6 +4,7 @@ Copyright (C) 2011-2012 Intel Corporation Copyright (C) 2011 Collabora Version 0.4.0 - DD.Aug.2012 +* Add support for Wayland * Drop FFmpeg-based decoders Version 0.3.7 - 26.Jun.2012 diff --git a/configure.ac b/configure.ac index 7ef92f34..86c4f7b5 100644 --- a/configure.ac +++ b/configure.ac @@ -45,10 +45,12 @@ m4_define([gst_plugins_bad_version], m4_define([va_api_version], [0.30.4]) m4_define([va_api_x11_version], [0.31.0]) m4_define([va_api_glx_version], [0.32.0]) +m4_define([va_api_wld_version], [0.34.0]) # libva package version number m4_define([libva_x11_package_version], [1.0.3]) m4_define([libva_glx_package_version], [1.0.9]) +m4_define([libva_wld_package_version], [1.2.0]) # gtk-doc version number # XXX: introspection annotations require gtk-doc >= 1.12 @@ -110,6 +112,11 @@ AC_ARG_ENABLE(glx, [enable OpenGL/X11 output @<:@default=yes@:>@]), [], [enable_glx="yes"]) +AC_ARG_ENABLE(wayland, + AC_HELP_STRING([--enable-wayland], + [enable Wayland output @<:@default=yes@:>@]), + [], [enable_wayland="yes"]) + dnl Check for basic libraries AC_CHECK_LIB(m, tan) @@ -319,6 +326,20 @@ if test "$enable_glx" = "yes" -a $HAVE_GL -eq 1 -a $USE_X11 -eq 1; then LIBS="$saved_LIBS" fi +dnl Check for Wayland +USE_WAYLAND=0 +if test "$enable_wayland" = "yes"; then + PKG_CHECK_MODULES(WAYLAND, [wayland-client], + [USE_WAYLAND=1], [USE_WAYLAND=0]) + + if test $USE_WAYLAND -eq 1; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $WAYLAND_CFLAGS" + AC_CHECK_HEADERS([wayland-client.h], [:], [USE_WAYLAND=0]) + CPPFLAGS="$saved_CPPFLAGS" + fi +fi + dnl --------------------------------------------------------------------------- dnl -- VA-API -- dnl --------------------------------------------------------------------------- @@ -382,11 +403,17 @@ AC_CACHE_CHECK([for JPEG decoding API], LIBS="$saved_LIBS" ]) +dnl VA/Wayland API +if test "$enable_wayland" = "yes"; then + PKG_CHECK_MODULES([LIBVA_WAYLAND], [libva-wayland >= va_api_wld_version], + [:], [USE_WAYLAND=0]) +fi + dnl --------------------------------------------------------------------------- dnl -- Generate files and summary -- dnl --------------------------------------------------------------------------- -case ":$USE_X11:$USE_GLX:" in +case ":$USE_X11:$USE_GLX:$USE_WAYLAND:" in *:1:*) ;; *) @@ -406,6 +433,10 @@ AC_DEFINE_UNQUOTED(USE_GLX, $USE_GLX, [Defined to 1 if GLX is enabled]) AM_CONDITIONAL(USE_GLX, test $USE_GLX -eq 1) +AC_DEFINE_UNQUOTED(USE_WAYLAND, $USE_WAYLAND, + [Defined to 1 if WAYLAND is enabled]) +AM_CONDITIONAL(USE_WAYLAND, test $USE_WAYLAND -eq 1) + pkgconfigdir=${libdir}/pkgconfig AC_SUBST(pkgconfigdir) @@ -456,6 +487,7 @@ yesno() { VIDEO_OUTPUTS="" AS_IF([test $USE_X11 -eq 1], [VIDEO_OUTPUTS="$VIDEO_OUTPUTS x11"]) AS_IF([test $USE_GLX -eq 1], [VIDEO_OUTPUTS="$VIDEO_OUTPUTS glx"]) +AS_IF([test $USE_WAYLAND -eq 1], [VIDEO_OUTPUTS="$VIDEO_OUTPUTS wayland"]) echo echo $PACKAGE configuration summary: diff --git a/gst-libs/gst/vaapi/Makefile.am b/gst-libs/gst/vaapi/Makefile.am index 1ddf17fd..fc84e496 100644 --- a/gst-libs/gst/vaapi/Makefile.am +++ b/gst-libs/gst/vaapi/Makefile.am @@ -3,6 +3,10 @@ lib_LTLIBRARIES = \ libgstvaapi-x11-@GST_MAJORMINOR@.la \ $(NULL) +if USE_WAYLAND +lib_LTLIBRARIES += libgstvaapi-wayland-@GST_MAJORMINOR@.la +endif + if USE_GLX lib_LTLIBRARIES += libgstvaapi-glx-@GST_MAJORMINOR@.la endif @@ -124,6 +128,23 @@ libgstvaapi_x11_source_priv_h = \ gstvaapiutils_x11.h \ $(NULL) +libgstvaapi_wayland_source_c = \ + gstvaapidisplay_wayland.c \ + gstvaapiutils.c \ + gstvaapiwindow_wayland.c \ + $(NULL) + +libgstvaapi_wayland_source_h = \ + gstvaapidisplay_wayland.h \ + gstvaapiwindow_wayland.h \ + $(NULL) + +libgstvaapi_wayland_source_priv_h = \ + gstvaapicompat.h \ + gstvaapidisplay_wayland_priv.h \ + gstvaapiutils.h \ + $(NULL) + libgstvaapi_glx_source_c = \ gstvaapidisplay_glx.c \ gstvaapitexture.c \ @@ -217,6 +238,38 @@ libgstvaapi_x11_@GST_MAJORMINOR@_la_LDFLAGS = \ $(GST_ALL_LDFLAGS) \ $(NULL) +libgstvaapi_wayland_@GST_MAJORMINOR@_la_SOURCES = \ + $(libgstvaapi_wayland_source_c) \ + $(libgstvaapi_wayland_source_priv_h) \ + $(NULL) + +libgstvaapi_wayland_@GST_MAJORMINOR@include_HEADERS = \ + $(libgstvaapi_wayland_source_h) \ + $(NULL) + +libgstvaapi_wayland_@GST_MAJORMINOR@includedir = \ + $(libgstvaapi_includedir) + +libgstvaapi_wayland_@GST_MAJORMINOR@_la_CFLAGS = \ + -DGST_USE_UNSTABLE_API \ + -I$(top_srcdir)/gst-libs \ + $(GLIB_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(WAYLAND_CFLAGS) \ + $(LIBVA_WAYLAND_CFLAGS) \ + $(NULL) + +libgstvaapi_wayland_@GST_MAJORMINOR@_la_LIBADD = \ + $(GLIB_LIBS) \ + $(WAYLAND_LIBS) \ + $(LIBVA_WAYLAND_LIBS) \ + libgstvaapi-@GST_MAJORMINOR@.la \ + $(NULL) + +libgstvaapi_wayland_@GST_MAJORMINOR@_la_LDFLAGS = \ + $(GST_ALL_LDFLAGS) \ + $(NULL) + libgstvaapi_glx_@GST_MAJORMINOR@_la_SOURCES = \ $(libgstvaapi_glx_source_c) \ $(libgstvaapi_glx_source_priv_h) \ diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_wayland.c b/gst-libs/gst/vaapi/gstvaapidisplay_wayland.c new file mode 100644 index 00000000..0407c96c --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapidisplay_wayland.c @@ -0,0 +1,414 @@ +/* + * gstvaapidisplay_wayland.c - VA/Wayland display abstraction + * + * Copyright (C) 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +/** + * SECTION:gstvaapidisplay_wayland + * @short_description: VA/Wayland display abstraction + */ + +#include "sysdeps.h" +#include <string.h> +#include "gstvaapidisplay_priv.h" +#include "gstvaapidisplay_wayland.h" +#include "gstvaapidisplay_wayland_priv.h" + +#define DEBUG 1 +#include "gstvaapidebug.h" + +G_DEFINE_TYPE(GstVaapiDisplayWayland, + gst_vaapi_display_wayland, + GST_VAAPI_TYPE_DISPLAY); + +enum { + PROP_0, + + PROP_DISPLAY_NAME, + PROP_WL_DISPLAY +}; + +static inline const gchar * +get_default_display_name(void) +{ + static const gchar *g_display_name; + + if (!g_display_name) + g_display_name = getenv("WAYLAND_DISPLAY"); + return g_display_name; +} + +static gboolean +compare_display_name(gconstpointer a, gconstpointer b, gpointer user_data) +{ + const gchar *display_name; + + /* XXX: handle screen number? */ + if (a && b) + return strcmp(a, b) == 0; + + /* Match "" or default display name */ + if (a) + display_name = a; + else if (b) + display_name = b; + else + return TRUE; + + if (*display_name == '\0') + return TRUE; + if (strcmp(display_name, get_default_display_name()) == 0) + return TRUE; + return FALSE; +} + +static void +gst_vaapi_display_wayland_finalize(GObject *object) +{ + G_OBJECT_CLASS(gst_vaapi_display_wayland_parent_class)->finalize(object); +} + +static void +set_display_name(GstVaapiDisplayWayland *display, const gchar *display_name) +{ + GstVaapiDisplayWaylandPrivate * const priv = display->priv; + + g_free(priv->display_name); + + if (display_name) + priv->display_name = g_strdup(display_name); + else + priv->display_name = NULL; +} + +static void +gst_vaapi_display_wayland_set_property( + GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec +) +{ + GstVaapiDisplayWayland * const display = GST_VAAPI_DISPLAY_WAYLAND(object); + + switch (prop_id) { + case PROP_DISPLAY_NAME: + set_display_name(display, g_value_get_string(value)); + break; + case PROP_WL_DISPLAY: + display->priv->wl_display = g_value_get_pointer(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} +static void +gst_vaapi_display_wayland_get_property( + GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec +) +{ + GstVaapiDisplayWayland * const display = GST_VAAPI_DISPLAY_WAYLAND(object); + + switch (prop_id) { + case PROP_DISPLAY_NAME: + g_value_set_string(value, display->priv->display_name); + break; + case PROP_WL_DISPLAY: + g_value_set_pointer(value, gst_vaapi_display_wayland_get_display(display)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +gst_vaapi_display_wayland_constructed(GObject *object) +{ + GstVaapiDisplayWayland * const display = GST_VAAPI_DISPLAY_WAYLAND(object); + GstVaapiDisplayWaylandPrivate * const priv = display->priv; + GstVaapiDisplayCache * const cache = gst_vaapi_display_get_cache(); + const GstVaapiDisplayInfo *info; + GObjectClass *parent_class; + const gchar *display_name; + + priv->create_display = priv->wl_display == NULL; + + /* Don't create Wayland display if there is one in the cache already */ + if (priv->create_display) { + info = gst_vaapi_display_cache_lookup_by_name( + cache, + priv->display_name, + compare_display_name, NULL + ); + if (info) { + priv->wl_display = info->native_display; + priv->create_display = FALSE; + } + } + + /* Reset display-name if the user provided his own Wayland display */ + if (!priv->create_display) { + /* XXX: get socket name */ + GST_WARNING("wayland: get display name"); + display_name = NULL; + set_display_name(display, display_name); + } + + parent_class = G_OBJECT_CLASS(gst_vaapi_display_wayland_parent_class); + if (parent_class->constructed) + parent_class->constructed(object); +} + +static void +display_handle_global( + struct wl_display *display, + uint32_t id, + const char *interface, + uint32_t version, + void *data +) +{ + GstVaapiDisplayWaylandPrivate * const priv = data; + + if (strcmp(interface, "wl_compositor") == 0) + priv->compositor = wl_display_bind(display, id, &wl_compositor_interface); + else if (strcmp(interface, "wl_shell") == 0) + priv->shell = wl_display_bind(display, id, &wl_shell_interface); +} + +static int +event_mask_update(uint32_t mask, void *data) +{ + GstVaapiDisplayWaylandPrivate * const priv = data; + + priv->event_mask = mask; + return 0; +} + +static gboolean +gst_vaapi_display_wayland_open_display(GstVaapiDisplay * display) +{ + GstVaapiDisplayWaylandPrivate * const priv = + GST_VAAPI_DISPLAY_WAYLAND(display)->priv; + + if (!priv->create_display) + return priv->wl_display != NULL; + + priv->wl_display = wl_display_connect(priv->display_name); + if (!priv->wl_display) + return FALSE; + + wl_display_set_user_data(priv->wl_display, priv); + wl_display_add_global_listener(priv->wl_display, display_handle_global, priv); + priv->event_fd = wl_display_get_fd(priv->wl_display, event_mask_update, priv); + wl_display_iterate(priv->wl_display, priv->event_mask); + wl_display_roundtrip(priv->wl_display); + + if (!priv->compositor) { + GST_ERROR("failed to bind compositor interface"); + return FALSE; + } + + if (!priv->shell) { + GST_ERROR("failed to bind shell interface"); + return FALSE; + } + return TRUE; +} + +static void +gst_vaapi_display_wayland_close_display(GstVaapiDisplay * display) +{ + GstVaapiDisplayWaylandPrivate * const priv = + GST_VAAPI_DISPLAY_WAYLAND(display)->priv; + + if (priv->compositor) { + wl_compositor_destroy(priv->compositor); + priv->compositor = NULL; + } + + if (priv->wl_display) { + wl_display_disconnect(priv->wl_display); + priv->wl_display = NULL; + } + + if (priv->display_name) { + g_free(priv->display_name); + priv->display_name = NULL; + } +} + +static gboolean +gst_vaapi_display_wayland_get_display_info( + GstVaapiDisplay *display, + GstVaapiDisplayInfo *info +) +{ + GstVaapiDisplayWaylandPrivate * const priv = + GST_VAAPI_DISPLAY_WAYLAND(display)->priv; + GstVaapiDisplayCache *cache; + const GstVaapiDisplayInfo *cached_info; + + /* Return any cached info even if child has its own VA display */ + cache = gst_vaapi_display_get_cache(); + if (!cache) + return FALSE; + cached_info = + gst_vaapi_display_cache_lookup_by_native_display(cache, priv->wl_display); + if (cached_info) { + *info = *cached_info; + return TRUE; + } + + /* Otherwise, create VA display if there is none already */ + info->native_display = priv->wl_display; + info->display_name = priv->display_name; + if (!info->va_display) { + info->va_display = vaGetDisplayWl(priv->wl_display); + if (!info->va_display) + return FALSE; + info->display_type = GST_VAAPI_DISPLAY_TYPE_WAYLAND; + } + return TRUE; +} + +static void +gst_vaapi_display_wayland_class_init(GstVaapiDisplayWaylandClass * klass) +{ + GObjectClass * const object_class = G_OBJECT_CLASS(klass); + GstVaapiDisplayClass * const dpy_class = GST_VAAPI_DISPLAY_CLASS(klass); + + g_type_class_add_private(klass, sizeof(GstVaapiDisplayWaylandPrivate)); + + object_class->finalize = gst_vaapi_display_wayland_finalize; + object_class->set_property = gst_vaapi_display_wayland_set_property; + object_class->get_property = gst_vaapi_display_wayland_get_property; + object_class->constructed = gst_vaapi_display_wayland_constructed; + + dpy_class->open_display = gst_vaapi_display_wayland_open_display; + dpy_class->close_display = gst_vaapi_display_wayland_close_display; + dpy_class->get_display = gst_vaapi_display_wayland_get_display_info; + + /** + * GstVaapiDisplayWayland:wayland-display: + * + * The Wayland #wl_display that was created by + * gst_vaapi_display_wayland_new() or that was bound from + * gst_vaapi_display_wayland_new_with_display(). + */ + g_object_class_install_property + (object_class, + PROP_WL_DISPLAY, + g_param_spec_pointer("wl-display", + "Wayland display", + "Wayland display", + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); + + /** + * GstVaapiDisplayWayland:display-name: + * + * The Wayland display name. + */ + g_object_class_install_property + (object_class, + PROP_DISPLAY_NAME, + g_param_spec_string("display-name", + "Wayland display name", + "Wayland display name", + NULL, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); +} + +static void +gst_vaapi_display_wayland_init(GstVaapiDisplayWayland *display) +{ + GstVaapiDisplayWaylandPrivate *priv = + GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE(display); + + display->priv = priv; + priv->create_display = TRUE; + priv->display_name = NULL; + priv->wl_display = NULL; + priv->compositor = NULL; + priv->shell = NULL; + priv->event_fd = -1; + priv->event_mask = 0; +} + +/** + * gst_vaapi_display_wayland_new: + * @display_name: the Wayland display name + * + * Opens an Wayland #wl_display using @display_name and returns a + * newly allocated #GstVaapiDisplay object. The Wayland display will + * be cloed when the reference count of the object reaches zero. + * + * Return value: a newly allocated #GstVaapiDisplay object + */ +GstVaapiDisplay * +gst_vaapi_display_wayland_new(const gchar *display_name) +{ + return g_object_new(GST_VAAPI_TYPE_DISPLAY_WAYLAND, + "display-name", display_name, + NULL); +} + +/** + * gst_vaapi_display_wayland_new_with_display: + * @wl_display: an Wayland #wl_display + * + * Creates a #GstVaapiDisplay based on the Wayland @wl_display + * display. The caller still owns the display and must call + * wl_display_disconnect() when all #GstVaapiDisplay references are + * released. Doing so too early can yield undefined behaviour. + * + * Return value: a newly allocated #GstVaapiDisplay object + */ +GstVaapiDisplay * +gst_vaapi_display_wayland_new_with_display(struct wl_display *wl_display) +{ + g_return_val_if_fail(wl_display, NULL); + + return g_object_new(GST_VAAPI_TYPE_DISPLAY_WAYLAND, + "wl-display", wl_display, + NULL); +} + +/** + * gst_vaapi_display_wayland_get_display: + * @display: a #GstVaapiDisplayWayland + * + * Returns the underlying Wayland #wl_display that was created by + * gst_vaapi_display_wayland_new() or that was bound from + * gst_vaapi_display_wayland_new_with_display(). + * + * Return value: the Wayland #wl_display attached to @display + */ +struct wl_display * +gst_vaapi_display_wayland_get_display(GstVaapiDisplayWayland *display) +{ + g_return_val_if_fail(GST_VAAPI_IS_DISPLAY_WAYLAND(display), NULL); + + return display->priv->wl_display; +} diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_wayland.h b/gst-libs/gst/vaapi/gstvaapidisplay_wayland.h new file mode 100644 index 00000000..c5fc0f63 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapidisplay_wayland.h @@ -0,0 +1,94 @@ +/* + * gstvaapidisplay_wayland.h - VA/Wayland display abstraction + * + * Copyright (C) 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef GST_VAAPI_DISPLAY_WAYLAND_H +#define GST_VAAPI_DISPLAY_WAYLAND_H + +#include <va/va_wayland.h> +#include <gst/vaapi/gstvaapidisplay.h> + +G_BEGIN_DECLS + +#define GST_VAAPI_TYPE_DISPLAY_WAYLAND \ + (gst_vaapi_display_wayland_get_type()) + +#define GST_VAAPI_DISPLAY_WAYLAND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + GST_VAAPI_TYPE_DISPLAY_WAYLAND, \ + GstVaapiDisplayWayland)) + +#define GST_VAAPI_DISPLAY_WAYLAND_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), \ + GST_VAAPI_TYPE_DISPLAY_WAYLAND, \ + GstVaapiDisplayWaylandClass)) + +#define GST_VAAPI_IS_DISPLAY_WAYLAND(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_DISPLAY_WAYLAND)) + +#define GST_VAAPI_IS_DISPLAY_WAYLAND_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_DISPLAY_WAYLAND)) + +#define GST_VAAPI_DISPLAY_WAYLAND_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), \ + GST_VAAPI_TYPE_DISPLAY_WAYLAND, \ + GstVaapiDisplayWaylandClass)) + +typedef struct _GstVaapiDisplayWayland GstVaapiDisplayWayland; +typedef struct _GstVaapiDisplayWaylandPrivate GstVaapiDisplayWaylandPrivate; +typedef struct _GstVaapiDisplayWaylandClass GstVaapiDisplayWaylandClass; + +/** + * GstVaapiDisplayWayland: + * + * VA/Wayland display wrapper. + */ +struct _GstVaapiDisplayWayland { + /*< private >*/ + GstVaapiDisplay parent_instance; + + GstVaapiDisplayWaylandPrivate *priv; +}; + +/** + * GstVaapiDisplayWaylandClass: + * + * VA/Wayland display wrapper clas. + */ +struct _GstVaapiDisplayWaylandClass { + /*< private >*/ + GstVaapiDisplayClass parent_class; +}; + +GType +gst_vaapi_display_wayland_get_type(void) G_GNUC_CONST; + +GstVaapiDisplay * +gst_vaapi_display_wayland_new(const gchar *display_name); + +GstVaapiDisplay * +gst_vaapi_display_wayland_new_with_display(struct wl_display *wl_display); + +struct wl_display * +gst_vaapi_display_wayland_get_display(GstVaapiDisplayWayland *display); + +G_END_DECLS + +#endif /* GST_VAAPI_DISPLAY_WAYLAND_H */ diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_wayland_priv.h b/gst-libs/gst/vaapi/gstvaapidisplay_wayland_priv.h new file mode 100644 index 00000000..04a72db6 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapidisplay_wayland_priv.h @@ -0,0 +1,60 @@ +/* + * gstvaapidisplay_wayland_priv.h - Internal VA/Wayland interface + * + * Copyright (C) 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef GST_VAAPI_DISPLAY_WAYLAND_PRIV_H +#define GST_VAAPI_DISPLAY_WAYLAND_PRIV_H + +#include <gst/vaapi/gstvaapidisplay_wayland.h> + +G_BEGIN_DECLS + +#define GST_VAAPI_DISPLAY_WAYLAND_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), \ + GST_VAAPI_TYPE_DISPLAY_WAYLAND, \ + GstVaapiDisplayWaylandPrivate)) + +#define GST_VAAPI_DISPLAY_WAYLAND_CAST(display) \ + ((GstVaapiDisplayWayland *)(display)) + +/** + * GST_VAAPI_DISPLAY_WL_DISPLAY: + * @display: a #GstVaapiDisplay + * + * Macro that evaluates to the underlying Wayland #wl_display object + * of @display + */ +#undef GST_VAAPI_DISPLAY_WL_DISPLAY +#define GST_VAAPI_DISPLAY_WL_DISPLAY(display) \ + GST_VAAPI_DISPLAY_WAYLAND_CAST(display)->priv->wl_display + +struct _GstVaapiDisplayWaylandPrivate { + gchar *display_name; + struct wl_display *wl_display; + struct wl_compositor *compositor; + struct wl_shell *shell; + gint event_fd; + guint32 event_mask; + guint create_display : 1; +}; + +G_END_DECLS + +#endif /* GST_VAAPI_DISPLAY_WAYLAND_PRIV_H */ diff --git a/gst-libs/gst/vaapi/gstvaapiobject_priv.h b/gst-libs/gst/vaapi/gstvaapiobject_priv.h index d84b7b0d..aa1b1109 100644 --- a/gst-libs/gst/vaapi/gstvaapiobject_priv.h +++ b/gst-libs/gst/vaapi/gstvaapiobject_priv.h @@ -76,6 +76,17 @@ G_BEGIN_DECLS GST_VAAPI_DISPLAY_GLX_CAST(GST_VAAPI_OBJECT_DISPLAY(object)) /** + * GST_VAAPI_OBJECT_DISPLAY_WAYLAND: + * @object: a #GstVaapiObject + * + * Macro that evaluates to the #GstVaapiDisplayWayland the @object is + * bound to. This is an internal macro that does not do any run-time + * type check and requires #include "gstvaapidisplay_wayland_priv.h" + */ +#define GST_VAAPI_OBJECT_DISPLAY_WAYLAND(object) \ + GST_VAAPI_DISPLAY_WAYLAND_CAST(GST_VAAPI_OBJECT_DISPLAY(object)) + +/** * GST_VAAPI_OBJECT_VADISPLAY: * @object: a #GstVaapiObject * @@ -109,6 +120,17 @@ G_BEGIN_DECLS GST_VAAPI_DISPLAY_XSCREEN(GST_VAAPI_OBJECT_DISPLAY(object)) /** + * GST_VAAPI_OBJECT_WL_DISPLAY: + * @object: a #GstVaapiObject + * + * Macro that evaluates to the underlying #wl_display of @display. + * This is an internal macro that does not do any run-time type check + * and requires #include "gstvaapidisplay_wayland_priv.h". + */ +#define GST_VAAPI_OBJECT_WL_DISPLAY(object) \ + GST_VAAPI_DISPLAY_WL_DISPLAY(GST_VAAPI_OBJECT_DISPLAY(object)) + +/** * GST_VAAPI_OBJECT_LOCK_DISPLAY: * @object: a #GstVaapiObject * diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_wayland.c b/gst-libs/gst/vaapi/gstvaapiwindow_wayland.c new file mode 100644 index 00000000..69634146 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapiwindow_wayland.c @@ -0,0 +1,302 @@ +/* + * gstvaapiwindow_wayland.c - VA/Wayland window abstraction + * + * Copyright (C) 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +/** + * SECTION:gstvaapiwindow_wayland + * @short_description: VA/Wayland window abstraction + */ + +#include "sysdeps.h" +#include <string.h> +#include "gstvaapicompat.h" +#include "gstvaapiwindow_wayland.h" +#include "gstvaapidisplay_wayland.h" +#include "gstvaapidisplay_wayland_priv.h" +#include "gstvaapiutils.h" +#include "gstvaapi_priv.h" + +#define DEBUG 1 +#include "gstvaapidebug.h" + +G_DEFINE_TYPE(GstVaapiWindowWayland, + gst_vaapi_window_wayland, + GST_VAAPI_TYPE_WINDOW); + +#define GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj), \ + GST_VAAPI_TYPE_WINDOW_WAYLAND, \ + GstVaapiWindowWaylandPrivate)) + +struct _GstVaapiWindowWaylandPrivate { + struct wl_shell_surface *shell_surface; + struct wl_surface *surface; + struct wl_buffer *buffer; + guint redraw_pending : 1; +}; + +static gboolean +gst_vaapi_window_wayland_show(GstVaapiWindow *window) +{ + GST_WARNING("unimplemented GstVaapiWindowWayland::show()"); + + return TRUE; +} + +static gboolean +gst_vaapi_window_wayland_hide(GstVaapiWindow *window) +{ + GST_WARNING("unimplemented GstVaapiWindowWayland::hide()"); + + return TRUE; +} + +static gboolean +gst_vaapi_window_wayland_create( + GstVaapiWindow *window, + guint *width, + guint *height +) +{ + GstVaapiWindowWaylandPrivate * const priv = + GST_VAAPI_WINDOW_WAYLAND(window)->priv; + GstVaapiDisplayWaylandPrivate * const priv_display = + GST_VAAPI_OBJECT_DISPLAY_WAYLAND(window)->priv; + + GST_DEBUG("create window, size %ux%u", *width, *height); + + g_return_val_if_fail(priv_display->compositor != NULL, FALSE); + g_return_val_if_fail(priv_display->shell != NULL, FALSE); + + priv->surface = wl_compositor_create_surface(priv_display->compositor); + if (!priv->surface) + return FALSE; + + priv->shell_surface = + wl_shell_get_shell_surface(priv_display->shell, priv->surface); + if (!priv->shell_surface) + return FALSE; + + wl_shell_surface_set_toplevel(priv->shell_surface); + wl_shell_surface_set_fullscreen( + priv->shell_surface, + WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, + 0, + NULL + ); + + priv->redraw_pending = FALSE; + return TRUE; +} + +static void +gst_vaapi_window_wayland_destroy(GstVaapiWindow * window) +{ + GstVaapiWindowWaylandPrivate * const priv = + GST_VAAPI_WINDOW_WAYLAND(window)->priv; + + if (priv->shell_surface) { + wl_shell_surface_destroy(priv->shell_surface); + priv->shell_surface = NULL; + } + + if (priv->surface) { + wl_surface_destroy(priv->surface); + priv->surface = NULL; + } + + if (priv->buffer) { + wl_buffer_destroy(priv->buffer); + priv->buffer = NULL; + } +} + +static gboolean +gst_vaapi_window_wayland_resize( + GstVaapiWindow * window, + guint width, + guint height +) +{ + GST_DEBUG("resize window, new size %ux%u", width, height); + return TRUE; +} + +static void +frame_redraw_callback(void *data, struct wl_callback *callback, uint32_t time) +{ + GstVaapiWindowWaylandPrivate * const priv = data; + + priv->redraw_pending = FALSE; + wl_buffer_destroy(priv->buffer); + priv->buffer = NULL; + wl_callback_destroy(callback); +} + +static const struct wl_callback_listener frame_callback_listener = { + frame_redraw_callback +}; + +static gboolean +gst_vaapi_window_wayland_render( + GstVaapiWindow *window, + GstVaapiSurface *surface, + const GstVaapiRectangle *src_rect, + const GstVaapiRectangle *dst_rect, + guint flags +) +{ + GstVaapiWindowWaylandPrivate * const priv = + GST_VAAPI_WINDOW_WAYLAND(window)->priv; + GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(window); + struct wl_display * const wl_display = GST_VAAPI_OBJECT_WL_DISPLAY(window); + struct wl_buffer *buffer; + struct wl_callback *callback; + guint width, height; + VASurfaceID surface_id; + VAStatus status; + + /* XXX: use VPP to support unusual source and destination rectangles */ + gst_vaapi_surface_get_size(surface, &width, &height); + if (src_rect->x != 0 || + src_rect->y != 0 || + src_rect->width != width || + src_rect->height != height) { + GST_ERROR("unsupported source rectangle for rendering"); + return FALSE; + } + + if (0 && (dst_rect->width != width || dst_rect->height != height)) { + GST_ERROR("unsupported target rectangle for rendering"); + return FALSE; + } + + surface_id = GST_VAAPI_OBJECT_ID(surface); + if (surface_id == VA_INVALID_ID) + return FALSE; + + GST_VAAPI_OBJECT_LOCK_DISPLAY(window); + + /* Wait for the previous frame to complete redraw */ + if (priv->redraw_pending) + wl_display_iterate(wl_display, WL_DISPLAY_READABLE); + + status = vaGetSurfaceBufferWl( + GST_VAAPI_DISPLAY_VADISPLAY(display), + surface_id, + &buffer + ); + if (!vaapi_check_status(status, "vaGetSurfaceBufferWl()")) + return FALSE; + + /* XXX: attach to the specified target rectangle */ + wl_surface_attach(priv->surface, buffer, 0, 0); + wl_surface_damage(priv->surface, 0, 0, width, height); + + wl_display_iterate(wl_display, WL_DISPLAY_WRITABLE); + priv->redraw_pending = TRUE; + priv->buffer = buffer; + + callback = wl_surface_frame(priv->surface); + wl_callback_add_listener(callback, &frame_callback_listener, priv); + GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window); + return TRUE; +} + +static void +gst_vaapi_window_wayland_finalize(GObject *object) +{ + G_OBJECT_CLASS(gst_vaapi_window_wayland_parent_class)->finalize(object); +} + +static void +gst_vaapi_window_wayland_constructed(GObject *object) +{ + GObjectClass *parent_class; + + parent_class = G_OBJECT_CLASS(gst_vaapi_window_wayland_parent_class); + if (parent_class->constructed) + parent_class->constructed(object); +} + +static void +gst_vaapi_window_wayland_class_init(GstVaapiWindowWaylandClass * klass) +{ + GObjectClass * const object_class = G_OBJECT_CLASS(klass); + GstVaapiWindowClass * const window_class = GST_VAAPI_WINDOW_CLASS(klass); + + g_type_class_add_private(klass, sizeof(GstVaapiWindowWaylandPrivate)); + + object_class->finalize = gst_vaapi_window_wayland_finalize; + object_class->constructed = gst_vaapi_window_wayland_constructed; + + window_class->create = gst_vaapi_window_wayland_create; + window_class->destroy = gst_vaapi_window_wayland_destroy; + window_class->show = gst_vaapi_window_wayland_show; + window_class->hide = gst_vaapi_window_wayland_hide; + window_class->render = gst_vaapi_window_wayland_render; + window_class->resize = gst_vaapi_window_wayland_resize; +} + +static void +gst_vaapi_window_wayland_init(GstVaapiWindowWayland * window) +{ + GstVaapiWindowWaylandPrivate *priv = + GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE(window); + + window->priv = priv; + priv->shell_surface = NULL; + priv->surface = NULL; + priv->buffer = NULL; + priv->redraw_pending = FALSE; +} + +/** + * gst_vaapi_window_wayland_new: + * @display: a #GstVaapiDisplay + * @width: the requested window width, in pixels + * @height: the requested windo height, in pixels + * + * Creates a window with the specified @width and @height. The window + * will be attached to the @display and remains invisible to the user + * until gst_vaapi_window_show() is called. + * + * Return value: the newly allocated #GstVaapiWindow object + */ +GstVaapiWindow * +gst_vaapi_window_wayland_new( + GstVaapiDisplay *display, + guint width, + guint height +) +{ + GST_DEBUG("new window, size %ux%u", width, height); + + g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL); + g_return_val_if_fail(width > 0, NULL); + g_return_val_if_fail(height > 0, NULL); + + return g_object_new(GST_VAAPI_TYPE_WINDOW_WAYLAND, + "display", display, + "id", GST_VAAPI_ID(0), + "width", width, + "height", height, + NULL); +} diff --git a/gst-libs/gst/vaapi/gstvaapiwindow_wayland.h b/gst-libs/gst/vaapi/gstvaapiwindow_wayland.h new file mode 100644 index 00000000..d711fb77 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapiwindow_wayland.h @@ -0,0 +1,89 @@ +/* + * gstvaapiwindow_wayland.h - VA/Wayland window abstraction + * + * Copyright (C) 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef GST_VAAPI_WINDOW_WAYLAND_H +#define GST_VAAPI_WINDOW_WAYLAND_H + +#include <wayland-client.h> +#include <gst/vaapi/gstvaapidisplay.h> +#include <gst/vaapi/gstvaapiwindow.h> + +G_BEGIN_DECLS + +#define GST_VAAPI_TYPE_WINDOW_WAYLAND \ + (gst_vaapi_window_wayland_get_type()) + +#define GST_VAAPI_WINDOW_WAYLAND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + GST_VAAPI_TYPE_WINDOW_WAYLAND, \ + GstVaapiWindowWayland)) + +#define GST_VAAPI_WINDOW_WAYLAND_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), \ + GST_VAAPI_TYPE_WINDOW_WAYLAND, \ + GstVaapiWindowWaylandClass)) + +#define GST_VAAPI_IS_WINDOW_WAYLAND(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_WINDOW_WAYLAND)) + +#define GST_VAAPI_IS_WINDOW_WAYLAND_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_WINDOW_WAYLAND)) + +#define GST_VAAPI_WINDOW_WAYLAND_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), \ + GST_VAAPI_TYPE_WINDOW_WAYLAND, \ + GstVaapiWindowWaylandClass)) + +typedef struct _GstVaapiWindowWayland GstVaapiWindowWayland; +typedef struct _GstVaapiWindowWaylandPrivate GstVaapiWindowWaylandPrivate; +typedef struct _GstVaapiWindowWaylandClass GstVaapiWindowWaylandClass; + +/** + * GstVaapiWindowWayland: + * + * A Wayland window abstraction. + */ +struct _GstVaapiWindowWayland { + /*< private >*/ + GstVaapiWindow parent_instance; + + GstVaapiWindowWaylandPrivate *priv; +}; + +/** + * GstVaapiWindowWaylandClass: + * + * An Wayland #Window wrapper class. + */ +struct _GstVaapiWindowWaylandClass { + /*< private >*/ + GstVaapiWindowClass parent_class; +}; + +GType +gst_vaapi_window_wayland_get_type(void) G_GNUC_CONST; + +GstVaapiWindow * +gst_vaapi_window_wayland_new(GstVaapiDisplay *display, guint width, guint height); + +G_END_DECLS + +#endif /* GST_VAAPI_WINDOW_WAYLAND_H */ |