libdrm_vigs added
authorjinhyung.jo <jinhyung.jo@samsung.com>
Thu, 26 Sep 2013 05:58:40 +0000 (14:58 +0900)
committerQuanxian Wang <quanxian.wang@intel.com>
Wed, 15 Oct 2014 04:06:14 +0000 (12:06 +0800)
Change-Id: Ie67c19bdb4a6f9e2190dbb4d3f825e878fca3635
Signed-off-by: Stanislav Vorobiov <s.vorobiov@samsung.com>
Signed-off-by: Jinhyung Jo <jinhyung.jo@samsung.com>
Makefile.am
configure.ac
include/drm/Makefile.am [new file with mode: 0644]
include/drm/vigs_drm.h [new file with mode: 0644]
packaging/libdrm.spec
vigs/Makefile.am [new file with mode: 0644]
vigs/libdrm_vigs.pc.in [new file with mode: 0644]
vigs/vigs.c [new file with mode: 0644]
vigs/vigs.h [new file with mode: 0644]

index 3952a88..efb9aa2 100644 (file)
@@ -53,7 +53,11 @@ if HAVE_FREEDRENO
 FREEDRENO_SUBDIR = freedreno
 endif
 
-SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) $(FREEDRENO_SUBDIR) tests man
+if HAVE_VIGS
+VIGS_SUBDIR = vigs
+endif
+
+SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) $(FREEDRENO_SUBDIR) $(VIGS_SUBDIR) tests include man
 
 libdrm_la_LTLIBRARIES = libdrm.la
 libdrm_ladir = $(libdir)
index ee59b03..7e9d2fc 100644 (file)
@@ -98,6 +98,11 @@ AC_ARG_ENABLE(freedreno-experimental-api,
              [Enable support for freedreno's experimental API (default: disabled)]),
              [FREEDRENO=$enableval], [FREEDRENO=no])
 
+AC_ARG_ENABLE(vigs,
+            AS_HELP_STRING([--disable-vigs],
+            [Enable support for VIGS's API (default: enabled)]),
+            [VIGS=$enableval], [VIGS=yes])
+
 AC_ARG_ENABLE(install-test-programs,
                  AS_HELP_STRING([--enable-install-test-programs],
                  [Install test programs (default: no)]),
@@ -355,11 +360,101 @@ else
 fi
 AM_CONDITIONAL([HAVE_MANPAGES_STYLESHEET], [test "x$HAVE_MANPAGES_STYLESHEET" = "xyes"])
 
+if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno" -o "x$OMAP" != "xno" -o "x$FREEDRENO" != "xno" -o "x$VIGS" != "xno"; then
+    # Check for atomic intrinsics
+    AC_CACHE_CHECK([for native atomic primitives], drm_cv_atomic_primitives,
+    [
+           drm_cv_atomic_primitives="none"
+
+           AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+    int atomic_add(int i) { return __sync_fetch_and_add (&i, 1); }
+    int atomic_cmpxchg(int i, int j, int k) { return __sync_val_compare_and_swap (&i, j, k); }
+                                            ]],[[]])],
+                           [drm_cv_atomic_primitives="Intel"],[])
+
+           if test "x$drm_cv_atomic_primitives" = "xnone"; then
+                   AC_CHECK_HEADER([atomic_ops.h], drm_cv_atomic_primitives="libatomic-ops")
+           fi
+
+           # atomic functions defined in <atomic.h> & libc on Solaris
+           if test "x$drm_cv_atomic_primitives" = "xnone"; then
+                   AC_CHECK_FUNC([atomic_cas_uint],
+                                 drm_cv_atomic_primitives="Solaris")
+           fi
+
+    ])
+    if test "x$drm_cv_atomic_primitives" = xIntel; then
+           AC_DEFINE(HAVE_LIBDRM_ATOMIC_PRIMITIVES, 1,
+                     [Enable if your compiler supports the Intel __sync_* atomic primitives])
+    fi
+    if test "x$drm_cv_atomic_primitives" = "xlibatomic-ops"; then
+           AC_DEFINE(HAVE_LIB_ATOMIC_OPS, 1, [Enable if you have libatomic-ops-dev installed])
+    fi
+
+    if test "x$drm_cv_atomic_primitives" = "xnone"; then
+           if test "x$INTEL" != "xauto"; then
+                   if test "x$INTEL" != "xno"; then
+                        AC_MSG_ERROR([libdrm_intel depends upon atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package, or, failing both of those, disable support for Intel GPUs by passing --disable-intel to ./configure])
+                   fi
+           else
+                   AC_MSG_WARN([Disabling libdrm_intel. It depends on atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package.])
+                   INTEL=no
+           fi
+           if test "x$RADEON" != "xauto"; then
+                   if test "x$RADEON" != "xno"; then
+                        AC_MSG_ERROR([libdrm_radeon depends upon atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package, or, failing both of those, disable support for Radeon support by passing --disable-radeon to ./configure])
+                   fi
+           else
+                   AC_MSG_WARN([Disabling libdrm_radeon. It depends on atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package.])
+                   RADEON=no
+           fi
+           if test "x$NOUVEAU" != "xauto"; then
+                   if test "x$NOUVEAU" != "xno"; then
+                        AC_MSG_ERROR([libdrm_nouveau depends upon atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package, or, failing both of those, disable support for NVIDIA GPUs by passing --disable-nouveau to ./configure])
+                   fi
+           else
+                   AC_MSG_WARN([Disabling libdrm_nouveau. It depends on atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package.])
+                   NOUVEAU=no
+           fi
+    else
+           if test "x$INTEL" != "xno"; then
+                   case $host_cpu in
+                           i?86|x86_64) INTEL=yes ;;
+                           *) INTEL=no ;;
+                   esac
+           fi
+           if test "x$RADEON" != "xno"; then
+                   RADEON=yes
+           fi
+           if test "x$NOUVEAU" != "xno"; then
+                   NOUVEAU=yes
+           fi
+    fi
+fi
+
+if test "x$VIGS" != "xno"; then
+       AC_DEFINE(HAVE_VIGS, 1, [Have VIGS])
+fi
+
+if test "x$INTEL" != "xno"; then
+       PKG_CHECK_MODULES(PCIACCESS, [pciaccess >= 0.10])
+fi
+AC_SUBST(PCIACCESS_CFLAGS)
+AC_SUBST(PCIACCESS_LIBS)
+
 PKG_CHECK_MODULES(VALGRIND, [valgrind], [have_valgrind=yes], [have_valgrind=no])
 if test "x$have_valgrind" = "xyes"; then
        AC_DEFINE([HAVE_VALGRIND], 1, [Use valgrind intrinsics to suppress false warnings])
 fi
 
+AM_CONDITIONAL(HAVE_INTEL, [test "x$INTEL" != "xno"])
+AM_CONDITIONAL(HAVE_RADEON, [test "x$RADEON" != "xno"])
+AM_CONDITIONAL(HAVE_NOUVEAU, [test "x$NOUVEAU" != "xno"])
+if test "x$RADEON" = xyes; then
+       AC_DEFINE(HAVE_RADEON, 1, [Have radeon support])
+fi
+AM_CONDITIONAL(HAVE_VIGS, [test "x$VIGS" != "xno"])
+
 AC_ARG_WITH([kernel-source],
             [AS_HELP_STRING([--with-kernel-source],
               [specify path to linux kernel source])],
@@ -403,6 +498,8 @@ AC_CONFIG_FILES([
        exynos/libdrm_exynos.pc
        freedreno/Makefile
        freedreno/libdrm_freedreno.pc
+       vigs/Makefile
+       vigs/libdrm_vigs.pc
        tests/Makefile
        tests/modeprint/Makefile
        tests/modetest/Makefile
@@ -425,4 +522,5 @@ echo "  Nouveau API    $NOUVEAU"
 echo "  OMAP API       $OMAP"
 echo "  EXYNOS API     $EXYNOS"
 echo "  Freedreno API  $FREEDRENO"
+echo "  VIGS API       $VIGS"
 echo ""
diff --git a/include/drm/Makefile.am b/include/drm/Makefile.am
new file mode 100644 (file)
index 0000000..5f9695f
--- /dev/null
@@ -0,0 +1,45 @@
+#  Copyright 2005 Adam Jackson.
+#
+#  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
+#  on 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
+#  ADAM JACKSON 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.
+
+# XXX airlied says, nothing besides *_drm.h and drm*.h should be necessary.
+# however, r300 and via need their reg headers installed in order to build.
+# better solutions are welcome.
+
+klibdrmincludedir = ${includedir}/libdrm
+klibdrminclude_HEADERS = \
+       drm.h \
+       drm_mode.h \
+       drm_fourcc.h \
+       drm_sarea.h \
+       i915_drm.h \
+       mga_drm.h \
+       nouveau_drm.h \
+       r128_drm.h \
+       radeon_drm.h \
+       savage_drm.h \
+       sis_drm.h \
+       via_drm.h \
+       mach64_drm.h \
+       qxl_drm.h \
+       vigs_drm.h
+
+if HAVE_VMWGFX
+klibdrminclude_HEADERS += vmwgfx_drm.h
+endif
diff --git a/include/drm/vigs_drm.h b/include/drm/vigs_drm.h
new file mode 100644 (file)
index 0000000..a31053e
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * vigs_drm.h
+ */
+
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Authors:
+ * Stanislav Vorobiov <s.vorobiov@samsung.com>
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS 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 _VIGS_DRM_H_
+#define _VIGS_DRM_H_
+
+/*
+ * Bump this whenever driver interface changes.
+ */
+#define DRM_VIGS_DRIVER_VERSION 9
+
+/*
+ * Surface access flags.
+ */
+#define DRM_VIGS_SAF_READ 1
+#define DRM_VIGS_SAF_WRITE 2
+#define DRM_VIGS_SAF_MASK 3
+
+struct drm_vigs_get_protocol_version
+{
+    uint32_t version;
+};
+
+struct drm_vigs_create_surface
+{
+    uint32_t width;
+    uint32_t height;
+    uint32_t stride;
+    uint32_t format;
+    uint32_t handle;
+    uint32_t size;
+    uint32_t id;
+};
+
+struct drm_vigs_create_execbuffer
+{
+    uint32_t size;
+    uint32_t handle;
+};
+
+struct drm_vigs_gem_map
+{
+    uint32_t handle;
+    int track_access;
+    unsigned long address;
+};
+
+struct drm_vigs_surface_info
+{
+    uint32_t handle;
+    uint32_t width;
+    uint32_t height;
+    uint32_t stride;
+    uint32_t format;
+    uint32_t size;
+    uint32_t id;
+};
+
+struct drm_vigs_exec
+{
+    uint32_t handle;
+};
+
+struct drm_vigs_surface_set_gpu_dirty
+{
+    uint32_t handle;
+};
+
+struct drm_vigs_surface_start_access
+{
+    unsigned long address;
+    uint32_t saf;
+};
+
+struct drm_vigs_surface_end_access
+{
+    unsigned long address;
+    int sync;
+};
+
+#define DRM_VIGS_GET_PROTOCOL_VERSION 0x00
+#define DRM_VIGS_CREATE_SURFACE 0x01
+#define DRM_VIGS_CREATE_EXECBUFFER 0x02
+#define DRM_VIGS_GEM_MAP 0x03
+#define DRM_VIGS_SURFACE_INFO 0x04
+#define DRM_VIGS_EXEC 0x05
+#define DRM_VIGS_SURFACE_SET_GPU_DIRTY 0x06
+#define DRM_VIGS_SURFACE_START_ACCESS 0x07
+#define DRM_VIGS_SURFACE_END_ACCESS 0x08
+
+#define DRM_IOCTL_VIGS_GET_PROTOCOL_VERSION DRM_IOR(DRM_COMMAND_BASE + \
+            DRM_VIGS_GET_PROTOCOL_VERSION, struct drm_vigs_get_protocol_version)
+#define DRM_IOCTL_VIGS_CREATE_SURFACE DRM_IOWR(DRM_COMMAND_BASE + \
+            DRM_VIGS_CREATE_SURFACE, struct drm_vigs_create_surface)
+#define DRM_IOCTL_VIGS_CREATE_EXECBUFFER DRM_IOWR(DRM_COMMAND_BASE + \
+            DRM_VIGS_CREATE_EXECBUFFER, struct drm_vigs_create_execbuffer)
+#define DRM_IOCTL_VIGS_GEM_MAP DRM_IOWR(DRM_COMMAND_BASE + \
+            DRM_VIGS_GEM_MAP, struct drm_vigs_gem_map)
+#define DRM_IOCTL_VIGS_SURFACE_INFO DRM_IOWR(DRM_COMMAND_BASE + \
+            DRM_VIGS_SURFACE_INFO, struct drm_vigs_surface_info)
+#define DRM_IOCTL_VIGS_EXEC DRM_IOW(DRM_COMMAND_BASE + \
+            DRM_VIGS_EXEC, struct drm_vigs_exec)
+#define DRM_IOCTL_VIGS_SURFACE_SET_GPU_DIRTY DRM_IOW(DRM_COMMAND_BASE + \
+            DRM_VIGS_SURFACE_SET_GPU_DIRTY, struct drm_vigs_surface_set_gpu_dirty)
+#define DRM_IOCTL_VIGS_SURFACE_START_ACCESS DRM_IOW(DRM_COMMAND_BASE + \
+            DRM_VIGS_SURFACE_START_ACCESS, struct drm_vigs_surface_start_access)
+#define DRM_IOCTL_VIGS_SURFACE_END_ACCESS DRM_IOW(DRM_COMMAND_BASE + \
+            DRM_VIGS_SURFACE_END_ACCESS, struct drm_vigs_surface_end_access)
+
+#endif
index 63e5f9b..d7b27b3 100644 (file)
@@ -78,6 +78,7 @@ make %{?_smp_mflags}
 %manifest %{name}.manifest
 %{_libdir}/libdrm.so.*
 %{_libdir}/libdrm_exynos.so.*
+%{_libdir}/libdrm_vigs.so.*
 
 %files devel
 %manifest %{name}.manifest
@@ -94,6 +95,7 @@ make %{?_smp_mflags}
 %endif
 %{_libdir}/libkms.so
 %{_libdir}/libdrm_exynos.so
+%{_libdir}/libdrm_vigs.so
 %{_libdir}/pkgconfig/*
 
 
diff --git a/vigs/Makefile.am b/vigs/Makefile.am
new file mode 100644 (file)
index 0000000..dd35bc4
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# Update "-version-number M:m:r" whenever library interface changes.
+# Only "M" part has to be updated.
+#
+
+AM_CFLAGS = \
+       $(WARN_CFLAGS) \
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/vigs \
+       $(PTHREADSTUBS_CFLAGS) \
+       -I$(top_srcdir)/include/drm
+
+libdrm_vigs_la_LTLIBRARIES = libdrm_vigs.la
+libdrm_vigs_ladir = $(libdir)
+libdrm_vigs_la_LDFLAGS = -version-number 4:0:0 -no-undefined
+libdrm_vigs_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
+
+libdrm_vigs_la_SOURCES = vigs.c
+
+libdrm_vigsincludedir = ${includedir}/libdrm
+libdrm_vigsinclude_HEADERS = vigs.h
+
+pkgconfigdir = @pkgconfigdir@
+pkgconfig_DATA = libdrm_vigs.pc
diff --git a/vigs/libdrm_vigs.pc.in b/vigs/libdrm_vigs.pc.in
new file mode 100644 (file)
index 0000000..676e82d
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libdrm_vigs
+Description: Userspace interface to VIGS kernel DRM services
+Version: 2.4.35
+Libs: -L${libdir} -ldrm_vigs
+Cflags: -I${includedir} -I${includedir}/libdrm -I${includedir}/vigs
+Requires.private: libdrm
diff --git a/vigs/vigs.c b/vigs/vigs.c
new file mode 100644 (file)
index 0000000..5530d48
--- /dev/null
@@ -0,0 +1,516 @@
+/* vigs.c
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Authors:
+ * Stanislav Vorobiov <s.vorobiov@samsung.com>
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/mman.h>
+#include <linux/stddef.h>
+
+#include <xf86drm.h>
+#include <xf86atomic.h>
+
+#include "vigs.h"
+#include "vigs_drm.h"
+
+#define vigs_offsetof(type, member) ((size_t)&((type*)0)->member)
+
+#define vigs_containerof(ptr, type, member) ((type*)((char*)(ptr) - vigs_offsetof(type, member)))
+
+struct vigs_drm_gem_info
+{
+    atomic_t ref_count;
+};
+
+struct vigs_drm_gem_impl
+{
+    struct vigs_drm_gem_info info;
+
+    struct vigs_drm_gem gem;
+};
+
+struct vigs_drm_surface_impl
+{
+    struct vigs_drm_gem_info gem_info;
+
+    struct vigs_drm_surface base;
+};
+
+struct vigs_drm_execbuffer_impl
+{
+    struct vigs_drm_gem_info gem_info;
+
+    struct vigs_drm_execbuffer base;
+};
+
+static void vigs_drm_gem_close(struct vigs_drm_device *dev, uint32_t handle)
+{
+    struct drm_gem_close req =
+    {
+        .handle = handle,
+    };
+
+    if (handle) {
+        drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
+    }
+}
+
+static void vigs_drm_gem_impl_init(struct vigs_drm_gem_impl *gem_impl,
+                                   struct vigs_drm_device *dev,
+                                   uint32_t handle,
+                                   uint32_t size,
+                                   uint32_t name)
+{
+    atomic_set(&gem_impl->info.ref_count, 1);
+    gem_impl->gem.dev = dev;
+    gem_impl->gem.size = size;
+    gem_impl->gem.handle = handle;
+    gem_impl->gem.name = name;
+}
+
+int vigs_drm_device_create(int fd, struct vigs_drm_device **dev)
+{
+    drmVersionPtr version;
+    uint32_t major;
+    int ret;
+
+    *dev = calloc(sizeof(**dev), 1);
+
+    if (!*dev) {
+        ret = -ENOMEM;
+        goto fail1;
+    }
+
+    version = drmGetVersion(fd);
+
+    if (!version) {
+        ret = -EINVAL;
+        goto fail2;
+    }
+
+    major = version->version_major;
+
+    drmFreeVersion(version);
+
+    if (major != DRM_VIGS_DRIVER_VERSION) {
+        ret = -EINVAL;
+        goto fail2;
+    }
+
+    (*dev)->fd = fd;
+
+    return 0;
+
+fail2:
+    free(*dev);
+fail1:
+    *dev = NULL;
+
+    return ret;
+}
+
+void vigs_drm_device_destroy(struct vigs_drm_device *dev)
+{
+    free(dev);
+}
+
+int vigs_drm_device_get_protocol_version(struct vigs_drm_device *dev,
+                                         uint32_t *protocol_version)
+{
+    struct drm_vigs_get_protocol_version req;
+    int ret;
+
+    ret = drmIoctl(dev->fd, DRM_IOCTL_VIGS_GET_PROTOCOL_VERSION, &req);
+
+    if (ret != 0) {
+        return -errno;
+    }
+
+    if (protocol_version) {
+        *protocol_version = req.version;
+    }
+
+    return 0;
+}
+
+void vigs_drm_gem_ref(struct vigs_drm_gem *gem)
+{
+    struct vigs_drm_gem_impl *gem_impl;
+
+    if (!gem) {
+        return;
+    }
+
+    gem_impl = vigs_containerof(gem, struct vigs_drm_gem_impl, gem);
+
+    atomic_inc(&gem_impl->info.ref_count);
+}
+
+void vigs_drm_gem_unref(struct vigs_drm_gem *gem)
+{
+    struct vigs_drm_gem_impl *gem_impl;
+
+    if (!gem) {
+        return;
+    }
+
+    gem_impl = vigs_containerof(gem, struct vigs_drm_gem_impl, gem);
+
+    assert(atomic_read(&gem_impl->info.ref_count) > 0);
+    if (!atomic_dec_and_test(&gem_impl->info.ref_count)) {
+        return;
+    }
+
+    if (gem->vaddr) {
+        munmap(gem->vaddr, gem->size);
+    }
+
+    vigs_drm_gem_close(gem->dev, gem->handle);
+
+    free(gem_impl);
+}
+
+int vigs_drm_gem_get_name(struct vigs_drm_gem *gem)
+{
+    struct drm_gem_flink req =
+    {
+        .handle = gem->handle,
+    };
+    int ret;
+
+    if (gem->name) {
+        return 0;
+    }
+
+    ret = drmIoctl(gem->dev->fd, DRM_IOCTL_GEM_FLINK, &req);
+
+    if (ret != 0) {
+        return -errno;
+    }
+
+    gem->name = req.name;
+
+    return 0;
+}
+
+int vigs_drm_gem_map(struct vigs_drm_gem *gem, int track_access)
+{
+    struct drm_vigs_gem_map req =
+    {
+        .handle = gem->handle,
+        .track_access = track_access
+    };
+    int ret;
+
+    if (gem->vaddr) {
+        return 0;
+    }
+
+    ret = drmIoctl(gem->dev->fd, DRM_IOCTL_VIGS_GEM_MAP, &req);
+
+    if (ret != 0) {
+        return -errno;
+    }
+
+    gem->vaddr = (void*)req.address;
+
+    return 0;
+}
+
+void vigs_drm_gem_unmap(struct vigs_drm_gem *gem)
+{
+    if (!gem->vaddr) {
+        return;
+    }
+
+    munmap(gem->vaddr, gem->size);
+    gem->vaddr = NULL;
+}
+
+int vigs_drm_surface_create(struct vigs_drm_device *dev,
+                            uint32_t width,
+                            uint32_t height,
+                            uint32_t stride,
+                            uint32_t format,
+                            struct vigs_drm_surface **sfc)
+{
+    struct vigs_drm_surface_impl *sfc_impl;
+    struct drm_vigs_create_surface req =
+    {
+        .width = width,
+        .height = height,
+        .stride = stride,
+        .format = format,
+    };
+    int ret;
+
+    sfc_impl = calloc(sizeof(*sfc_impl), 1);
+
+    if (!sfc_impl) {
+        ret = -ENOMEM;
+        goto fail1;
+    }
+
+    ret = drmIoctl(dev->fd, DRM_IOCTL_VIGS_CREATE_SURFACE, &req);
+
+    if (ret != 0) {
+        ret = -errno;
+        goto fail2;
+    }
+
+    vigs_drm_gem_impl_init((struct vigs_drm_gem_impl*)sfc_impl,
+                           dev,
+                           req.handle,
+                           req.size,
+                           0);
+
+    sfc_impl->base.width = width;
+    sfc_impl->base.height = height;
+    sfc_impl->base.stride = stride;
+    sfc_impl->base.format = format;
+    sfc_impl->base.id = req.id;
+
+    *sfc = &sfc_impl->base;
+
+    return 0;
+
+fail2:
+    free(sfc_impl);
+fail1:
+    *sfc = NULL;
+
+    return ret;
+}
+
+int vigs_drm_surface_open(struct vigs_drm_device *dev,
+                          uint32_t name,
+                          struct vigs_drm_surface **sfc)
+{
+    struct vigs_drm_surface_impl *sfc_impl;
+    struct drm_gem_open req =
+    {
+        .name = name,
+    };
+    struct drm_vigs_surface_info info_req;
+    int ret;
+
+    sfc_impl = calloc(sizeof(*sfc_impl), 1);
+
+    if (!sfc_impl) {
+        ret = -ENOMEM;
+        goto fail1;
+    }
+
+    ret = drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req);
+
+    if (ret != 0) {
+        ret = -errno;
+        goto fail2;
+    }
+
+    info_req.handle = req.handle;
+
+    ret = drmIoctl(dev->fd, DRM_IOCTL_VIGS_SURFACE_INFO, &info_req);
+
+    if (ret != 0) {
+        ret = -errno;
+        goto fail3;
+    }
+
+    vigs_drm_gem_impl_init((struct vigs_drm_gem_impl*)sfc_impl,
+                           dev,
+                           req.handle,
+                           info_req.size,
+                           name);
+
+    sfc_impl->base.width = info_req.width;
+    sfc_impl->base.height = info_req.height;
+    sfc_impl->base.stride = info_req.stride;
+    sfc_impl->base.format = info_req.format;
+    sfc_impl->base.id = info_req.id;
+
+    *sfc = &sfc_impl->base;
+
+    return 0;
+
+fail3:
+    vigs_drm_gem_close(dev, req.handle);
+fail2:
+    free(sfc_impl);
+fail1:
+    *sfc = NULL;
+
+    return ret;
+}
+
+int vigs_drm_surface_set_gpu_dirty(struct vigs_drm_surface *sfc)
+{
+    struct drm_vigs_surface_set_gpu_dirty req =
+    {
+        .handle = sfc->gem.handle
+    };
+    int ret;
+
+    ret = drmIoctl(sfc->gem.dev->fd, DRM_IOCTL_VIGS_SURFACE_SET_GPU_DIRTY, &req);
+
+    return (ret != 0) ? -errno : 0;
+}
+
+int vigs_drm_surface_start_access(struct vigs_drm_surface *sfc,
+                                  uint32_t saf)
+{
+    struct drm_vigs_surface_start_access req =
+    {
+        .address = (unsigned long)sfc->gem.vaddr,
+        .saf = saf
+    };
+    int ret;
+
+    ret = drmIoctl(sfc->gem.dev->fd, DRM_IOCTL_VIGS_SURFACE_START_ACCESS, &req);
+
+    return (ret != 0) ? -errno : 0;
+}
+
+int vigs_drm_surface_end_access(struct vigs_drm_surface *sfc,
+                                int sync)
+{
+    struct drm_vigs_surface_end_access req =
+    {
+        .address = (unsigned long)sfc->gem.vaddr,
+        .sync = sync
+    };
+    int ret;
+
+    ret = drmIoctl(sfc->gem.dev->fd, DRM_IOCTL_VIGS_SURFACE_END_ACCESS, &req);
+
+    return (ret != 0) ? -errno : 0;
+}
+
+int vigs_drm_execbuffer_create(struct vigs_drm_device *dev,
+                               uint32_t size,
+                               struct vigs_drm_execbuffer **execbuffer)
+{
+    struct vigs_drm_execbuffer_impl *execbuffer_impl;
+    struct drm_vigs_create_execbuffer req =
+    {
+        .size = size
+    };
+    int ret;
+
+    execbuffer_impl = calloc(sizeof(*execbuffer_impl), 1);
+
+    if (!execbuffer_impl) {
+        ret = -ENOMEM;
+        goto fail1;
+    }
+
+    ret = drmIoctl(dev->fd, DRM_IOCTL_VIGS_CREATE_EXECBUFFER, &req);
+
+    if (ret != 0) {
+        ret = -errno;
+        goto fail2;
+    }
+
+    vigs_drm_gem_impl_init((struct vigs_drm_gem_impl*)execbuffer_impl,
+                           dev,
+                           req.handle,
+                           req.size,
+                           0);
+
+    *execbuffer = &execbuffer_impl->base;
+
+    return 0;
+
+fail2:
+    free(execbuffer_impl);
+fail1:
+    *execbuffer = NULL;
+
+    return ret;
+}
+
+int vigs_drm_execbuffer_open(struct vigs_drm_device *dev,
+                             uint32_t name,
+                             struct vigs_drm_execbuffer **execbuffer)
+{
+    struct vigs_drm_execbuffer_impl *execbuffer_impl;
+    struct drm_gem_open req =
+    {
+        .name = name,
+    };
+    int ret;
+
+    execbuffer_impl = calloc(sizeof(*execbuffer_impl), 1);
+
+    if (!execbuffer_impl) {
+        ret = -ENOMEM;
+        goto fail1;
+    }
+
+    ret = drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req);
+
+    if (ret != 0) {
+        ret = -errno;
+        goto fail2;
+    }
+
+    vigs_drm_gem_impl_init((struct vigs_drm_gem_impl*)execbuffer_impl,
+                           dev,
+                           req.handle,
+                           req.size,
+                           name);
+
+    *execbuffer = &execbuffer_impl->base;
+
+    return 0;
+
+fail2:
+    free(execbuffer_impl);
+fail1:
+    *execbuffer = NULL;
+
+    return ret;
+}
+
+int vigs_drm_execbuffer_exec(struct vigs_drm_execbuffer *execbuffer)
+{
+    struct drm_vigs_exec req =
+    {
+        .handle = execbuffer->gem.handle
+    };
+    int ret;
+
+    ret = drmIoctl(execbuffer->gem.dev->fd, DRM_IOCTL_VIGS_EXEC, &req);
+
+    return (ret != 0) ? -errno : 0;
+}
diff --git a/vigs/vigs.h b/vigs/vigs.h
new file mode 100644 (file)
index 0000000..681031a
--- /dev/null
@@ -0,0 +1,192 @@
+/* vigs.h
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Authors:
+ * Stanislav Vorobiov <s.vorobiov@samsung.com>
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS 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 __VIGS_H__
+#define __VIGS_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Surface formats.
+ */
+typedef enum
+{
+    vigs_drm_surface_bgrx8888 = 0x0,
+    vigs_drm_surface_bgra8888 = 0x1,
+} vigs_drm_surface_format;
+
+/*
+ * Surface access flags.
+ */
+#define VIGS_DRM_SAF_READ 1
+#define VIGS_DRM_SAF_WRITE 2
+
+struct vigs_drm_device
+{
+    /* DRM fd. */
+    int fd;
+};
+
+struct vigs_drm_gem
+{
+    /* VIGS device object. */
+    struct vigs_drm_device *dev;
+
+    /* size of the buffer created. */
+    uint32_t size;
+
+    /* a gem handle to gem object created. */
+    uint32_t handle;
+
+    /* a gem global handle from flink request. initially 0. */
+    uint32_t name;
+
+    /* user space address to a gem buffer mmaped. initially NULL. */
+    void *vaddr;
+};
+
+struct vigs_drm_surface
+{
+    struct vigs_drm_gem gem;
+
+    uint32_t width;
+    uint32_t height;
+    uint32_t stride;
+    uint32_t format;
+    uint32_t id;
+};
+
+struct vigs_drm_execbuffer
+{
+    struct vigs_drm_gem gem;
+};
+
+/*
+ * All functions return 0 on success and < 0 on error, i.e. kernel style:
+ * return -ENOMEM;
+ */
+
+/*
+ * Device functions.
+ * @{
+ */
+
+/*
+ * Returns -EINVAL on driver version mismatch.
+ */
+int vigs_drm_device_create(int fd, struct vigs_drm_device **dev);
+
+void vigs_drm_device_destroy(struct vigs_drm_device *dev);
+
+int vigs_drm_device_get_protocol_version(struct vigs_drm_device *dev,
+                                         uint32_t *protocol_version);
+
+/*
+ * @}
+ */
+
+/*
+ * GEM functions.
+ * @{
+ */
+
+/*
+ * Passing NULL won't hurt, this is for convenience.
+ */
+void vigs_drm_gem_ref(struct vigs_drm_gem *gem);
+
+/*
+ * Passing NULL won't hurt, this is for convenience.
+ */
+void vigs_drm_gem_unref(struct vigs_drm_gem *gem);
+
+int vigs_drm_gem_get_name(struct vigs_drm_gem *gem);
+
+int vigs_drm_gem_map(struct vigs_drm_gem *gem, int track_access);
+
+void vigs_drm_gem_unmap(struct vigs_drm_gem *gem);
+
+/*
+ * @}
+ */
+
+/*
+ * Surface functions.
+ * @{
+ */
+
+int vigs_drm_surface_create(struct vigs_drm_device *dev,
+                            uint32_t width,
+                            uint32_t height,
+                            uint32_t stride,
+                            uint32_t format,
+                            struct vigs_drm_surface **sfc);
+
+int vigs_drm_surface_open(struct vigs_drm_device *dev,
+                          uint32_t name,
+                          struct vigs_drm_surface **sfc);
+
+int vigs_drm_surface_set_gpu_dirty(struct vigs_drm_surface *sfc);
+
+int vigs_drm_surface_start_access(struct vigs_drm_surface *sfc,
+                                  uint32_t saf);
+
+int vigs_drm_surface_end_access(struct vigs_drm_surface *sfc,
+                                int sync);
+
+/*
+ * @}
+ */
+
+/*
+ * Execbuffer functions.
+ * @{
+ */
+
+int vigs_drm_execbuffer_create(struct vigs_drm_device *dev,
+                               uint32_t size,
+                               struct vigs_drm_execbuffer **execbuffer);
+
+int vigs_drm_execbuffer_open(struct vigs_drm_device *dev,
+                             uint32_t name,
+                             struct vigs_drm_execbuffer **execbuffer);
+
+int vigs_drm_execbuffer_exec(struct vigs_drm_execbuffer *execbuffer);
+
+/*
+ * @}
+ */
+
+#ifdef __cplusplus
+};
+#endif /* __cplusplus */
+
+#endif