[Libva] [Driver PATCH 2/5] add wayland support

Zhao Halley halley.zhao at intel.com
Tue Jun 5 02:12:09 PDT 2012


From: Gwenole Beauchesne <gwenole.beauchesne at intel.com>

---
 configure.ac              |   56 +++++++
 src/Makefile.am           |    7 +
 src/i965_drv_video.c      |    7 +
 src/i965_render_wayland.c |  372 +++++++++++++++++++++++++++++++++++++++++++++
 src/i965_render_wayland.h |   33 ++++
 5 files changed, 475 insertions(+), 0 deletions(-)
 mode change 100644 => 100755 configure.ac
 create mode 100755 src/i965_render_wayland.c
 create mode 100755 src/i965_render_wayland.h

diff --git a/configure.ac b/configure.ac
old mode 100644
new mode 100755
index 5717ce2..8805ffd
--- a/configure.ac
+++ b/configure.ac
@@ -41,6 +41,11 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])], [
     AC_SUBST(AM_DEFAULT_VERBOSITY)
 ])
 
+AC_ARG_ENABLE([wayland],
+    [AC_HELP_STRING([--enable-wayland],
+                    [build with Wayland support @<:@default=yes@:>@])],
+    [], [enable_wayland="yes"])
+
 AC_DISABLE_STATIC
 AC_PROG_LIBTOOL
 AC_PROG_CC
@@ -90,6 +95,53 @@ fi
 AC_MSG_RESULT([$LIBVA_DRIVERS_PATH])
 AC_SUBST(LIBVA_DRIVERS_PATH)
 
+# Check for EGL
+if test "$enable_wayland" = "yes"; then
+    enable_egl="yes"
+fi
+
+USE_EGL="no"
+EGL_CFLAGS=""
+EGL_LIBS=""
+if test "$enable_egl" = "yes"; then
+    saved_CFLAGS="$CFLAGS"
+    saved_LIBS="$LIBS"
+    PKG_CHECK_MODULES([EGL], [egl], [], [EGL_LIBS="-lEGL"])
+    CFLAGS="$CFLAGS $EGL_CFLAGS"
+    LIBS="$LIBS $EGL_LIBS"
+    AC_CHECK_HEADERS([EGL/egl.h])
+    AC_CHECK_LIB(EGL, eglGetDisplay, [USE_EGL="yes"])
+    CFLAGS="$saved_CFLAGS"
+    LIBS="$saved_LIBS"
+fi
+AC_SUBST(EGL_CFLAGS)
+AC_SUBST(EGL_LIBS)
+AM_CONDITIONAL(USE_EGL, test "$USE_EGL" = "yes")
+
+# Check for Wayland
+USE_WAYLAND=0
+USE_WAYLAND_DRM=0
+WAYLAND_DRM_CFLAGS=""
+WAYLAND_DRM_LIBS=""
+if test "$enable_wayland" = "yes"; then
+    PKG_CHECK_MODULES([WAYLAND], [wayland-client], [USE_WAYLAND=1], [])
+    if test "$USE_EGL" = "yes"; then
+        USE_WAYLAND_DRM=1
+        WAYLAND_DRM_CFLAGS="$DRM_CFLAGS"
+	WAYLAND_DRM_LIBS="$DRM_LIBS $EGL_LIBS"
+    fi
+fi
+AC_DEFINE_UNQUOTED(USE_WAYLAND, $USE_WAYLAND,
+    [Defined to 1 if building the Wayland windowing system])
+AM_CONDITIONAL(USE_WAYLAND, test $USE_WAYLAND -eq 1)
+
+AC_SUBST([WAYLAND_DRM_CFLAGS])
+AC_SUBST([WAYLAND_DRM_LIBS])
+AC_DEFINE_UNQUOTED(USE_WAYLAND_DRM, $USE_WAYLAND_DRM,
+    [Defined to 1 if building the Wayland windowing system with DRM support])
+AM_CONDITIONAL(USE_WAYLAND_DRM, test $USE_WAYLAND_DRM -eq 1)
+
+
 AC_OUTPUT([
     Makefile
     debian.upstream/Makefile 
@@ -109,9 +161,13 @@ AC_OUTPUT([
 ])
 
 dnl Print summary
+WINSYS=""
+AS_IF([test $USE_WAYLAND -eq 1], [WINSYS="wayland $WINSYS"])
+
 echo
 echo $PACKAGE configuration summary:
 echo
 echo VA-API version ................... : $VA_VERSION_STR
 echo VA-API drivers path .............. : $LIBVA_DRIVERS_PATH
+echo Windowing systems ................ : $WINSYS
 echo
diff --git a/src/Makefile.am b/src/Makefile.am
index bb0b033..fc9a12b 100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -102,6 +102,13 @@ source_h = \
 	object_heap.h           \
 	$(NULL)
 
+if USE_WAYLAND
+source_c			+= i965_render_wayland.c
+source_h			+= i965_render_wayland.h
+driver_cflags			+= $(WAYLAND_CFLAGS) $(WAYLAND_DRM_CFLAGS)
+driver_libs			+= $(WAYLAND_LIBS) $(WAYLAND_DRM_LIBS)
+endif
+
 i965_drv_video_la_LTLIBRARIES	= i965_drv_video.la
 i965_drv_video_ladir		= $(LIBVA_DRIVERS_PATH)
 i965_drv_video_la_CFLAGS	= $(driver_cflags)
diff --git a/src/i965_drv_video.c b/src/i965_drv_video.c
index 81b0738..79f96f3 100755
--- a/src/i965_drv_video.c
+++ b/src/i965_drv_video.c
@@ -44,6 +44,9 @@
 #include "i965_defines.h"
 #include "i965_drv_video.h"
 
+#if USE_WAYLAND
+# include "i965_render_wayland.h"
+#endif
 #define CONFIG_ID_OFFSET                0x01000000
 #define CONTEXT_ID_OFFSET               0x02000000
 #define SURFACE_ID_OFFSET               0x04000000
@@ -1910,6 +1913,10 @@ i965_Init(VADriverContextP ctx)
 
     if (intel_driver_init(ctx) == False)
         return VA_STATUS_ERROR_UNKNOWN;
+#if USE_WAYLAND
+    if (!i965_render_wayland_init(ctx))
+        return VA_STATUS_ERROR_UNKNOWN;
+#endif
 
     if (IS_G4X(i965->intel.device_id))
         i965->codec_info = &g4x_hw_codec_info;
diff --git a/src/i965_render_wayland.c b/src/i965_render_wayland.c
new file mode 100755
index 0000000..26d7ba0
--- /dev/null
+++ b/src/i965_render_wayland.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2012 Intel Corporation. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <va/va_backend.h>
+#include <va/va_backend_wayland.h>
+#include <wayland-client.h>
+#include <wayland-drm-client-protocol.h>
+#include "intel_driver.h"
+#include "i965_render_wayland.h"
+#include "i965_drv_video.h"
+
+#define VA_WL_FORMAT_RGBA (WL_DRM_FORMAT_XRGB8888)
+
+struct va_wl_surface {
+    struct wl_drm      *wl_drm;
+    struct wl_surface  *wl_surface;
+    struct wl_buffer   *wl_buffer;
+    struct intel_region region;
+    unsigned int        name;
+    unsigned int        format;
+    unsigned int        width;
+    unsigned int        height;
+};
+
+static void
+va_surface_reset_buffer(
+    VADriverContextP      ctx,
+    struct va_wl_surface *va_wl_surface
+)
+{
+    struct intel_region * const region = &va_wl_surface->region;
+
+    if (va_wl_surface->wl_buffer) {
+#if 0
+        /* XXX: automatically destroyed on next wl_surface_attach()? */
+        wl_buffer_destroy(va_wl_surface->wl_buffer);
+#endif
+        va_wl_surface->wl_buffer = NULL;
+    }
+
+    if (region->bo) {
+        dri_bo_unreference(region->bo);
+        region->bo = NULL;
+    }
+
+    va_wl_surface->name   = 0;
+    va_wl_surface->format = 0;
+    va_wl_surface->width  = 0;
+    va_wl_surface->height = 0;
+    memset(region, 0, sizeof(*region));
+}
+
+static VAStatus
+va_wayland_create_surface(
+    VADriverContextP       ctx,
+    struct wl_surface     *wl_surface,
+    struct va_wl_surface **out_va_wl_surface
+)
+{
+    struct va_wl_surface *va_wl_surface;
+    uint32_t id;
+
+    if (ctx->display_type != VA_DISPLAY_WAYLAND)
+        return VA_STATUS_ERROR_INVALID_DISPLAY;
+    if (!wl_surface)
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+    if (!out_va_wl_surface)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    va_wl_surface = calloc(1, sizeof(*va_wl_surface));
+    if (!va_wl_surface)
+        return VA_STATUS_ERROR_ALLOCATION_FAILED;
+
+    id = wl_display_get_global(ctx->native_dpy, "wl_drm", 1);
+    if (!id) {
+        wl_display_roundtrip(ctx->native_dpy);
+        id = wl_display_get_global(ctx->native_dpy, "wl_drm", 1);
+        if (!id)
+            return VA_STATUS_ERROR_INVALID_DISPLAY;
+    }
+
+    va_wl_surface->wl_drm =
+        wl_display_bind(ctx->native_dpy, id, &wl_drm_interface);
+    if (!va_wl_surface->wl_drm)
+        return VA_STATUS_ERROR_INVALID_DISPLAY;
+
+    va_wl_surface->wl_surface   = wl_surface;
+    va_wl_surface->wl_buffer    = NULL;
+    va_wl_surface->format       = 0;
+    va_wl_surface->width        = 0;
+    va_wl_surface->height       = 0;
+
+    *out_va_wl_surface = va_wl_surface;
+    return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+va_wayland_destroy_surface(
+    VADriverContextP       ctx,
+    struct va_wl_surface  *va_wl_surface
+)
+{
+    if (ctx->display_type != VA_DISPLAY_WAYLAND)
+        return VA_STATUS_ERROR_INVALID_DISPLAY;
+    if (!va_wl_surface)
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+
+    va_surface_reset_buffer(ctx, va_wl_surface);
+
+    if (va_wl_surface->wl_drm) {
+        wl_drm_destroy(va_wl_surface->wl_drm);
+        va_wl_surface->wl_drm = NULL;
+    }
+
+    free(va_wl_surface);
+    return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+va_surface_relink_buffer(
+    VADriverContextP      ctx,
+    struct va_wl_surface *va_wl_surface
+)
+{
+    struct i965_driver_data * const i965 = i965_driver_data(ctx);
+    struct i965_render_state * const render_state = &i965->render_state;
+    struct intel_region *region = render_state->draw_region;
+    uint32_t name;
+
+    if (region) {
+        if (!region->bo || dri_bo_flink(region->bo, &name) != 0)
+            return VA_STATUS_ERROR_INVALID_BUFFER;
+
+        if (name != va_wl_surface->name) {
+            dri_bo_unreference(region->bo);
+            region->bo = NULL;
+        }
+    }
+    else {
+        region = calloc(1, sizeof(*region));
+        if (!region)
+            return VA_STATUS_ERROR_ALLOCATION_FAILED;
+        render_state->draw_region = region;
+    }
+
+    if (!region->bo) {
+        *region = va_wl_surface->region;
+
+        region->bo = intel_bo_gem_create_from_name(
+            i965->intel.bufmgr,
+            "render buffer",
+            va_wl_surface->name
+        );
+        assert(region->bo);
+        if (!region->bo)
+            return VA_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+    return VA_STATUS_SUCCESS;
+}
+
+static bool
+va_surface_create_buffer_rgb(
+    VADriverContextP       ctx,
+    struct va_wl_surface  *va_wl_surface,
+    struct object_surface *obj_surface
+)
+{
+    struct i965_driver_data * const i965 = i965_driver_data(ctx);
+    struct intel_region * const region = &va_wl_surface->region;
+
+    region->x           = 0;
+    region->y           = 0;
+    region->width       = ALIGN(obj_surface->orig_width,  16);
+    region->height      = ALIGN(obj_surface->orig_height, 16);
+    region->cpp         = 4;
+    region->pitch       = ALIGN(region->cpp * region->width, 64);
+
+    region->bo = drm_intel_bo_alloc_for_render(
+        i965->intel.bufmgr,
+        "render buffer",
+        region->pitch * region->height,
+        0
+    );
+    if (!region->bo)
+        return false;
+
+    dri_bo_get_tiling(region->bo, &region->tiling, &region->swizzle);
+    if (dri_bo_flink(region->bo, &va_wl_surface->name) != 0) {
+        fprintf(stderr, "libva: error: flink failed for bo %p\n", region->bo);
+        return false;
+    }
+
+    va_wl_surface->format = VA_WL_FORMAT_RGBA;
+    va_wl_surface->width  = obj_surface->orig_width;
+    va_wl_surface->height = obj_surface->orig_height;
+    return true;
+}
+
+static VAStatus
+va_attach_rgb_surface(
+    VADriverContextP       ctx,
+    struct va_wl_surface  *va_wl_surface,
+    struct object_surface *obj_surface,
+    unsigned int           flags
+)
+{
+    struct intel_region * const region = &va_wl_surface->region;
+    VAStatus va_status;
+    VASurfaceID va_surface;
+    VARectangle src_rect, dst_rect;
+    unsigned int pp_flags;
+
+    /* Check local buffer */
+    if (va_wl_surface->format != VA_WL_FORMAT_RGBA        ||
+        va_wl_surface->width  != obj_surface->orig_width  ||
+        va_wl_surface->height != obj_surface->orig_height) {
+        va_surface_reset_buffer(ctx, va_wl_surface);
+        if (!va_surface_create_buffer_rgb(ctx, va_wl_surface, obj_surface))
+            return VA_STATUS_ERROR_ALLOCATION_FAILED;
+    }
+    assert(region->bo);
+
+    /* Check buffer link */
+    va_status = va_surface_relink_buffer(ctx, va_wl_surface);
+    if (va_status != VA_STATUS_SUCCESS)
+        return va_status;
+
+    /* Render to RGBA surface */
+    va_surface      = obj_surface->base.id;
+    src_rect.x      = 0;
+    src_rect.y      = 0;
+    src_rect.width  = obj_surface->orig_width;
+    src_rect.height = obj_surface->orig_height;
+    dst_rect        = src_rect;
+
+    pp_flags = 0;
+    if ((flags & VA_FILTER_SCALING_MASK) == VA_FILTER_SCALING_NL_ANAMORPHIC)
+        pp_flags |= I965_PP_FLAG_AVS;
+    if (flags & VA_TOP_FIELD)
+        pp_flags |= I965_PP_FLAG_TOP_FIELD;
+    else if (flags & VA_BOTTOM_FIELD)
+        pp_flags |= I965_PP_FLAG_BOTTOM_FIELD;
+
+    intel_render_put_surface(ctx, va_surface, &src_rect, &dst_rect, pp_flags);
+    if (obj_surface->subpic != VA_INVALID_ID)
+        intel_render_put_subpicture(ctx, va_surface, &src_rect, &dst_rect);
+    return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+va_wayland_attach_surface_unlocked(
+    VADriverContextP       ctx,
+    struct va_wl_surface  *va_wl_surface,
+    struct object_surface *obj_surface,
+    unsigned int           flags
+)
+{
+    VAStatus va_status;
+
+    va_status = va_attach_rgb_surface(ctx, va_wl_surface, obj_surface, flags);
+    if (va_status != VA_STATUS_SUCCESS)
+        return va_status;
+
+    if (!va_wl_surface->wl_buffer) {
+        va_wl_surface->wl_buffer = wl_drm_create_buffer(
+            va_wl_surface->wl_drm,
+            va_wl_surface->name,
+            va_wl_surface->width,
+            va_wl_surface->height,
+            va_wl_surface->region.pitch,
+            va_wl_surface->format
+        );
+        if (!va_wl_surface->wl_buffer)
+            return VA_STATUS_ERROR_ALLOCATION_FAILED;
+
+        wl_surface_attach(
+            va_wl_surface->wl_surface,
+            va_wl_surface->wl_buffer,
+            0, 0
+        );
+    }
+
+    wl_surface_damage(
+        va_wl_surface->wl_surface,
+        0, 0, va_wl_surface->width, va_wl_surface->height
+    );
+
+    obj_surface->flags |= SURFACE_DISPLAYED;
+
+    if ((obj_surface->flags & SURFACE_ALL_MASK) == SURFACE_DISPLAYED) {
+        dri_bo_unreference(obj_surface->bo);
+        obj_surface->bo = NULL;
+        obj_surface->flags &= ~SURFACE_REF_DIS_MASK;
+
+        if (obj_surface->free_private_data)
+            obj_surface->free_private_data(&obj_surface->private_data);
+    }
+    return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+va_wayland_attach_surface(
+    VADriverContextP       ctx,
+    struct va_wl_surface  *va_wl_surface,
+    VASurfaceID            va_surface,
+    unsigned int           flags
+)
+{
+    struct i965_driver_data * const i965 = i965_driver_data(ctx);
+    struct object_surface *obj_surface; 
+    VAStatus va_status;
+
+    if (ctx->display_type != VA_DISPLAY_WAYLAND)
+        return VA_STATUS_ERROR_INVALID_DISPLAY;
+    if (!va_wl_surface)
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+
+    obj_surface = SURFACE(va_surface);
+    if (!obj_surface || !obj_surface->bo)
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+
+    _i965LockMutex(&i965->render_mutex);
+    va_status = va_wayland_attach_surface_unlocked(
+        ctx,
+        va_wl_surface,
+        obj_surface,
+        flags
+    );
+    _i965UnlockMutex(&i965->render_mutex);
+    return va_status;
+}
+
+bool
+i965_render_wayland_init(VADriverContextP ctx)
+{
+    struct VADriverVTableWayland * const vtable = ctx->vtable_wayland;
+
+    if (ctx->display_type != VA_DISPLAY_WAYLAND)
+        return true;
+
+    if (!vtable)
+        return false;
+
+    vtable->vaCreateSurfaceWL   = va_wayland_create_surface;
+    vtable->vaDestroySurfaceWL  = va_wayland_destroy_surface;
+    vtable->vaAttachSurfaceWL   = va_wayland_attach_surface;
+    return true;
+}
diff --git a/src/i965_render_wayland.h b/src/i965_render_wayland.h
new file mode 100755
index 0000000..1418c71
--- /dev/null
+++ b/src/i965_render_wayland.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 Intel Corporation. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef I965_RENDER_WAYLAND_H
+#define I965_RENDER_WAYLAND_H
+
+#include <stdbool.h>
+
+bool
+i965_render_wayland_init(VADriverContextP ctx);
+
+#endif /* I965_RENDER_WAYLAND_H */
-- 
1.7.5.4



More information about the Libva mailing list