Add initial support for VA/Wayland.
authorSreerenj Balachandran <sreerenj.balachandran@intel.com>
Thu, 19 Jul 2012 08:27:23 +0000 (10:27 +0200)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Wed, 25 Jul 2012 13:31:42 +0000 (15:31 +0200)
Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
NEWS
configure.ac
gst-libs/gst/vaapi/Makefile.am
gst-libs/gst/vaapi/gstvaapidisplay_wayland.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay_wayland.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapidisplay_wayland_priv.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiobject_priv.h
gst-libs/gst/vaapi/gstvaapiwindow_wayland.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiwindow_wayland.h [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 118610a..39e6572 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -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
index 7ef92f3..86c4f7b 100644 (file)
@@ -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:
index 1ddf17f..fc84e49 100644 (file)
@@ -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 (file)
index 0000000..0407c96
--- /dev/null
@@ -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 (file)
index 0000000..c5fc0f6
--- /dev/null
@@ -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 (file)
index 0000000..04a72db
--- /dev/null
@@ -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 */
index d84b7b0..aa1b110 100644 (file)
@@ -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 (file)
index 0000000..6963414
--- /dev/null
@@ -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 (file)
index 0000000..d711fb7
--- /dev/null
@@ -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 */