--- /dev/null
+/*
+ * 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 14
+
+/*
+ * Surface access flags.
+ */
+#define DRM_VIGS_SAF_READ 1
+#define DRM_VIGS_SAF_WRITE 2
+#define DRM_VIGS_SAF_MASK 3
+
+/*
+ * Number of DP framebuffers.
+ */
+#define DRM_VIGS_NUM_DP_FB_BUF 4
+
+/*
+ * DP memory types.
+ */
+#define DRM_VIGS_DP_FB_Y 2
+#define DRM_VIGS_DP_FB_C 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;
+ int scanout;
+ 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_gem_wait
+{
+ uint32_t handle;
+};
+
+struct drm_vigs_surface_info
+{
+ uint32_t handle;
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
+ uint32_t format;
+ int scanout;
+ 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;
+};
+
+struct drm_vigs_surface_convert
+{
+ uint32_t src_handle;
+ uint32_t src_format;
+ uint32_t dst_handle;
+ uint32_t dst_format;
+ int y_invert;
+};
+
+struct drm_vigs_create_fence
+{
+ int send;
+ uint32_t handle;
+ uint32_t seq;
+};
+
+struct drm_vigs_fence_wait
+{
+ uint32_t handle;
+};
+
+struct drm_vigs_fence_signaled
+{
+ uint32_t handle;
+ int signaled;
+};
+
+struct drm_vigs_fence_unref
+{
+ uint32_t handle;
+};
+
+struct drm_vigs_plane_set_zpos
+{
+ uint32_t plane_id;
+ int zpos;
+};
+
+struct drm_vigs_plane_set_transform
+{
+ uint32_t plane_id;
+ int hflip;
+ int vflip;
+ int rotation;
+};
+
+struct drm_vigs_dp_create_surface
+{
+ uint32_t dp_plane;
+ uint32_t dp_fb_buf;
+ uint32_t dp_mem_flag;
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
+ uint32_t format;
+ uint32_t handle;
+ uint32_t size;
+ uint32_t id;
+};
+
+struct drm_vigs_dp_open_surface
+{
+ uint32_t dp_plane;
+ uint32_t dp_fb_buf;
+ uint32_t dp_mem_flag;
+ uint32_t handle;
+};
+
+#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_GEM_WAIT 0x04
+#define DRM_VIGS_SURFACE_INFO 0x05
+#define DRM_VIGS_EXEC 0x06
+#define DRM_VIGS_SURFACE_SET_GPU_DIRTY 0x07
+#define DRM_VIGS_SURFACE_START_ACCESS 0x08
+#define DRM_VIGS_SURFACE_END_ACCESS 0x09
+#define DRM_VIGS_CREATE_FENCE 0x0A
+#define DRM_VIGS_FENCE_WAIT 0x0B
+#define DRM_VIGS_FENCE_SIGNALED 0x0C
+#define DRM_VIGS_FENCE_UNREF 0x0D
+#define DRM_VIGS_PLANE_SET_ZPOS 0x0E
+#define DRM_VIGS_PLANE_SET_TRANSFORM 0x0F
+
+#define DRM_VIGS_DP_CREATE_SURFACE 0x20
+#define DRM_VIGS_DP_OPEN_SURFACE 0x21
+
+#define DRM_VIGS_SURFACE_CONVERT 0x22
+
+#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_GEM_WAIT DRM_IOW(DRM_COMMAND_BASE + \
+ DRM_VIGS_GEM_WAIT, struct drm_vigs_gem_wait)
+#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)
+#define DRM_IOCTL_VIGS_SURFACE_CONVERT DRM_IOW(DRM_COMMAND_BASE + \
+ DRM_VIGS_SURFACE_CONVERT, struct drm_vigs_surface_convert)
+#define DRM_IOCTL_VIGS_CREATE_FENCE DRM_IOWR(DRM_COMMAND_BASE + \
+ DRM_VIGS_CREATE_FENCE, struct drm_vigs_create_fence)
+#define DRM_IOCTL_VIGS_FENCE_WAIT DRM_IOW(DRM_COMMAND_BASE + \
+ DRM_VIGS_FENCE_WAIT, struct drm_vigs_fence_wait)
+#define DRM_IOCTL_VIGS_FENCE_SIGNALED DRM_IOWR(DRM_COMMAND_BASE + \
+ DRM_VIGS_FENCE_SIGNALED, struct drm_vigs_fence_signaled)
+#define DRM_IOCTL_VIGS_FENCE_UNREF DRM_IOW(DRM_COMMAND_BASE + \
+ DRM_VIGS_FENCE_UNREF, struct drm_vigs_fence_unref)
+#define DRM_IOCTL_VIGS_PLANE_SET_ZPOS DRM_IOW(DRM_COMMAND_BASE + \
+ DRM_VIGS_PLANE_SET_ZPOS, struct drm_vigs_plane_set_zpos)
+#define DRM_IOCTL_VIGS_PLANE_SET_TRANSFORM DRM_IOW(DRM_COMMAND_BASE + \
+ DRM_VIGS_PLANE_SET_TRANSFORM, struct drm_vigs_plane_set_transform)
+
+#define DRM_IOCTL_VIGS_DP_CREATE_SURFACE DRM_IOWR(DRM_COMMAND_BASE + \
+ DRM_VIGS_DP_CREATE_SURFACE, struct drm_vigs_dp_create_surface)
+#define DRM_IOCTL_VIGS_DP_OPEN_SURFACE DRM_IOWR(DRM_COMMAND_BASE + \
+ DRM_VIGS_DP_OPEN_SURFACE, struct drm_vigs_dp_open_surface)
+
+#endif
--- /dev/null
+/* 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.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/mman.h>
+#include <linux/stddef.h>
+
+#include <xf86drm.h>
+#include <xf86atomic.h>
+
+#include "libdrm_macros.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;
+};
+
+struct vigs_drm_fence_impl
+{
+ struct vigs_drm_fence base;
+
+ atomic_t ref_count;
+};
+
+static void vigs_drm_gem_close(struct vigs_drm_device *dev, uint32_t handle)
+{
+ struct drm_gem_close req =
+ {
+ .handle = handle,
+ };
+ int ret;
+
+ if (handle) {
+ ret = drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
+ if (ret) {
+ fprintf(stderr, "DRM_IOCTL_GEM_CLOSE %d failed(%d)\n", handle, ret);
+ }
+ }
+}
+
+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;
+}
+
+drm_public 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;
+}
+
+drm_public void vigs_drm_device_destroy(struct vigs_drm_device *dev)
+{
+ free(dev);
+}
+
+drm_public 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;
+}
+
+drm_public 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);
+}
+
+drm_public 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);
+}
+
+drm_public 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;
+}
+
+drm_public 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;
+}
+
+drm_public void vigs_drm_gem_unmap(struct vigs_drm_gem *gem)
+{
+ if (!gem->vaddr) {
+ return;
+ }
+
+ munmap(gem->vaddr, gem->size);
+ gem->vaddr = NULL;
+}
+
+drm_public int vigs_drm_gem_wait(struct vigs_drm_gem *gem)
+{
+ struct drm_vigs_gem_wait req =
+ {
+ .handle = gem->handle,
+ };
+ int ret;
+
+ ret = drmIoctl(gem->dev->fd, DRM_IOCTL_VIGS_GEM_WAIT, &req);
+
+ if (ret != 0) {
+ return -errno;
+ }
+
+ return 0;
+}
+
+drm_public int vigs_drm_surface_create(struct vigs_drm_device *dev,
+ uint32_t width,
+ uint32_t height,
+ uint32_t stride,
+ uint32_t format,
+ int scanout,
+ 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,
+ .scanout = scanout,
+ };
+ 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.scanout = scanout;
+ sfc_impl->base.id = req.id;
+
+ *sfc = &sfc_impl->base;
+
+ return 0;
+
+fail2:
+ free(sfc_impl);
+fail1:
+ *sfc = NULL;
+
+ return ret;
+}
+
+drm_public 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.scanout = info_req.scanout;
+ 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;
+}
+
+drm_public 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;
+}
+
+drm_public 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;
+}
+
+drm_public 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;
+}
+
+drm_public int vigs_drm_surface_convert(struct vigs_drm_surface *src,
+ uint32_t src_format,
+ struct vigs_drm_surface *dst,
+ uint32_t dst_format,
+ int y_invert)
+{
+ struct drm_vigs_surface_convert req =
+ {
+ .src_handle = src->gem.handle,
+ .src_format = src_format,
+ .dst_handle = dst->gem.handle,
+ .dst_format = dst_format,
+ .y_invert = y_invert
+ };
+ int ret;
+
+ ret = drmIoctl(dst->gem.dev->fd, DRM_IOCTL_VIGS_SURFACE_CONVERT, &req);
+
+ return (ret != 0) ? -errno : 0;
+}
+
+drm_public 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;
+}
+
+drm_public 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;
+}
+
+drm_public 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;
+}
+
+drm_public int vigs_drm_fence_create(struct vigs_drm_device *dev,
+ int send,
+ struct vigs_drm_fence **fence)
+{
+ struct vigs_drm_fence_impl *fence_impl;
+ struct drm_vigs_create_fence req =
+ {
+ .send = send
+ };
+ int ret;
+
+ fence_impl = calloc(sizeof(*fence_impl), 1);
+
+ if (!fence_impl) {
+ ret = -ENOMEM;
+ goto fail1;
+ }
+
+ ret = drmIoctl(dev->fd, DRM_IOCTL_VIGS_CREATE_FENCE, &req);
+
+ if (ret != 0) {
+ ret = -errno;
+ goto fail2;
+ }
+
+ atomic_set(&fence_impl->ref_count, 1);
+ fence_impl->base.dev = dev;
+ fence_impl->base.handle = req.handle;
+ fence_impl->base.seq = req.seq;
+ fence_impl->base.signaled = 0;
+
+ *fence = &fence_impl->base;
+
+ return 0;
+
+fail2:
+ free(fence_impl);
+fail1:
+ *fence = NULL;
+
+ return ret;
+}
+
+drm_public void vigs_drm_fence_ref(struct vigs_drm_fence *fence)
+{
+ struct vigs_drm_fence_impl *fence_impl;
+
+ if (!fence) {
+ return;
+ }
+
+ fence_impl = vigs_containerof(fence, struct vigs_drm_fence_impl, base);
+
+ atomic_inc(&fence_impl->ref_count);
+}
+
+drm_public void vigs_drm_fence_unref(struct vigs_drm_fence *fence)
+{
+ struct vigs_drm_fence_impl *fence_impl;
+ struct drm_vigs_fence_unref req;
+ int ret;
+
+ if (!fence) {
+ return;
+ }
+
+ fence_impl = vigs_containerof(fence, struct vigs_drm_fence_impl, base);
+
+ assert(atomic_read(&fence_impl->ref_count) > 0);
+ if (!atomic_dec_and_test(&fence_impl->ref_count)) {
+ return;
+ }
+
+ req.handle = fence->handle;
+
+ ret = drmIoctl(fence->dev->fd, DRM_IOCTL_VIGS_FENCE_UNREF, &req);
+ if (ret)
+ fprintf(stderr, "DRM_IOCTL_VIGS_FENCE_UNREF failed(%d)\n", ret);
+
+ free(fence_impl);
+}
+
+drm_public int vigs_drm_fence_wait(struct vigs_drm_fence *fence)
+{
+ struct drm_vigs_fence_wait req =
+ {
+ .handle = fence->handle
+ };
+ int ret;
+
+ ret = drmIoctl(fence->dev->fd, DRM_IOCTL_VIGS_FENCE_WAIT, &req);
+
+ return (ret != 0) ? -errno : 0;
+}
+
+drm_public int vigs_drm_fence_check(struct vigs_drm_fence *fence)
+{
+ struct drm_vigs_fence_signaled req =
+ {
+ .handle = fence->handle
+ };
+ int ret;
+
+ if (fence->signaled) {
+ return 0;
+ }
+
+ ret = drmIoctl(fence->dev->fd, DRM_IOCTL_VIGS_FENCE_SIGNALED, &req);
+
+ if (ret != 0) {
+ return -errno;
+ }
+
+ fence->signaled = req.signaled;
+
+ return 0;
+}
+
+drm_public int vigs_drm_plane_set_zpos(struct vigs_drm_device *dev,
+ uint32_t plane_id,
+ int zpos)
+{
+ struct drm_vigs_plane_set_zpos req =
+ {
+ .plane_id = plane_id,
+ .zpos = zpos
+ };
+ int ret;
+
+ ret = drmIoctl(dev->fd, DRM_IOCTL_VIGS_PLANE_SET_ZPOS, &req);
+
+ return (ret != 0) ? -errno : 0;
+}
+
+drm_public int vigs_drm_plane_set_transform(struct vigs_drm_device *dev,
+ uint32_t plane_id,
+ int hflip,
+ int vflip,
+ vigs_drm_rotation rotation)
+{
+ struct drm_vigs_plane_set_transform req =
+ {
+ .plane_id = plane_id,
+ .hflip = hflip,
+ .vflip = vflip,
+ .rotation = rotation
+ };
+ int ret;
+
+ ret = drmIoctl(dev->fd, DRM_IOCTL_VIGS_PLANE_SET_TRANSFORM, &req);
+
+ return (ret != 0) ? -errno : 0;
+}
+
+drm_public int vigs_drm_dp_surface_create(struct vigs_drm_device *dev,
+ uint32_t dp_plane,
+ uint32_t dp_fb_buf,
+ uint32_t dp_mem_flag,
+ 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_dp_create_surface req =
+ {
+ .dp_plane = dp_plane,
+ .dp_fb_buf = dp_fb_buf,
+ .dp_mem_flag = dp_mem_flag,
+ .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_DP_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.scanout = 0;
+ sfc_impl->base.id = req.id;
+
+ *sfc = &sfc_impl->base;
+
+ return 0;
+
+fail2:
+ free(sfc_impl);
+fail1:
+ *sfc = NULL;
+
+ return ret;
+}
+
+drm_public int vigs_drm_dp_surface_open(struct vigs_drm_device *dev,
+ uint32_t dp_plane,
+ uint32_t dp_fb_buf,
+ uint32_t dp_mem_flag,
+ struct vigs_drm_surface **sfc)
+{
+ struct vigs_drm_surface_impl *sfc_impl;
+ struct drm_vigs_dp_open_surface req =
+ {
+ .dp_plane = dp_plane,
+ .dp_fb_buf = dp_fb_buf,
+ .dp_mem_flag = dp_mem_flag
+ };
+ 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_VIGS_DP_OPEN_SURFACE, &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,
+ 0);
+
+ 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.scanout = info_req.scanout;
+ 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;
+}
+
+drm_public int vigs_drm_prime_export_fd(struct vigs_drm_device *dev,
+ struct vigs_drm_surface *sfc,
+ int *prime_fd)
+{
+ struct drm_prime_handle req = {
+ .handle = sfc->gem.handle,
+ .flags = DRM_CLOEXEC,
+ };
+ int ret;
+
+ ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &req);
+
+ if (ret) {
+ ret = -errno;
+ goto fail;
+ }
+
+ *prime_fd = req.fd;
+
+fail:
+ return ret;
+}
+
+drm_public int vigs_drm_prime_import_fd(struct vigs_drm_device *dev,
+ int prime_fd,
+ struct vigs_drm_surface **sfc)
+{
+ struct vigs_drm_surface_impl *sfc_impl;
+ struct drm_vigs_surface_info info_req;
+ struct drm_prime_handle req = {
+ .fd = prime_fd,
+ };
+ int ret;
+
+ ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &req);
+
+ if (ret) {
+ ret = -errno;
+ goto err;
+ }
+
+ sfc_impl = calloc(sizeof(*sfc_impl), 1);
+
+ if (!sfc_impl) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ memset(&info_req, 0, sizeof(info_req));
+ info_req.handle = req.handle;
+
+ ret = drmIoctl(dev->fd, DRM_IOCTL_VIGS_SURFACE_INFO, &info_req);
+
+ if (ret) {
+ ret = -errno;
+ goto err_free_sfc_impl;
+ }
+
+ vigs_drm_gem_impl_init((struct vigs_drm_gem_impl*)sfc_impl,
+ dev,
+ req.handle,
+ info_req.size,
+ 0 /* 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.scanout = info_req.scanout;
+ sfc_impl->base.id = info_req.id;
+
+ *sfc = &sfc_impl->base;
+
+ return 0;
+
+err_free_sfc_impl:
+ free(sfc_impl);
+
+err:
+ return ret;
+}
--- /dev/null
+/* 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;
+
+/*
+ * Rotations.
+ */
+typedef enum
+{
+ vigs_drm_rotation_0 = 0x0,
+ vigs_drm_rotation_90 = 0x1,
+ vigs_drm_rotation_180 = 0x2,
+ vigs_drm_rotation_270 = 0x3,
+} vigs_drm_rotation;
+
+/*
+ * 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;
+ int scanout;
+ uint32_t id;
+};
+
+struct vigs_drm_execbuffer
+{
+ struct vigs_drm_gem gem;
+};
+
+struct vigs_drm_fence
+{
+ /* VIGS device object. */
+ struct vigs_drm_device *dev;
+
+ /* a handle to fence object. */
+ uint32_t handle;
+
+ /* fence sequence number. */
+ uint32_t seq;
+
+ /* is fence signaled ? updated on 'vigs_drm_fence_check'. */
+ int signaled;
+};
+
+/*
+ * 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);
+
+int vigs_drm_gem_wait(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,
+ int scanout,
+ 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);
+
+int vigs_drm_surface_convert(struct vigs_drm_surface *src,
+ uint32_t src_format,
+ struct vigs_drm_surface *dst,
+ uint32_t dst_format,
+ int y_invert);
+
+/*
+ * @}
+ */
+
+/*
+ * 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);
+
+/*
+ * @}
+ */
+
+/*
+ * Fence functions.
+ * @{
+ */
+
+int vigs_drm_fence_create(struct vigs_drm_device *dev,
+ int send,
+ struct vigs_drm_fence **fence);
+
+/*
+ * Passing NULL won't hurt, this is for convenience.
+ */
+void vigs_drm_fence_ref(struct vigs_drm_fence *fence);
+
+/*
+ * Passing NULL won't hurt, this is for convenience.
+ */
+void vigs_drm_fence_unref(struct vigs_drm_fence *fence);
+
+int vigs_drm_fence_wait(struct vigs_drm_fence *fence);
+
+int vigs_drm_fence_check(struct vigs_drm_fence *fence);
+
+/*
+ * @}
+ */
+
+/*
+ * Plane functions.
+ * @{
+ */
+
+int vigs_drm_plane_set_zpos(struct vigs_drm_device *dev,
+ uint32_t plane_id,
+ int zpos);
+
+int vigs_drm_plane_set_transform(struct vigs_drm_device *dev,
+ uint32_t plane_id,
+ int hflip,
+ int vflip,
+ vigs_drm_rotation rotation);
+
+/*
+ * @}
+ */
+
+/*
+ * DP functions.
+ * @{
+ */
+
+int vigs_drm_dp_surface_create(struct vigs_drm_device *dev,
+ uint32_t dp_plane,
+ uint32_t dp_fb_buf,
+ uint32_t dp_mem_flag,
+ uint32_t width,
+ uint32_t height,
+ uint32_t stride,
+ uint32_t format,
+ struct vigs_drm_surface **sfc);
+
+int vigs_drm_dp_surface_open(struct vigs_drm_device *dev,
+ uint32_t dp_plane,
+ uint32_t dp_fb_buf,
+ uint32_t dp_mem_flag,
+ struct vigs_drm_surface **sfc);
+
+/*
+ * @}
+ */
+
+/*
+ * PRIME functions.
+ * @{
+ */
+
+int vigs_drm_prime_export_fd(struct vigs_drm_device *dev,
+ struct vigs_drm_surface *sfc,
+ int *prime_fd);
+
+int vigs_drm_prime_import_fd(struct vigs_drm_device *dev,
+ int prime_fd,
+ struct vigs_drm_surface **sfc);
+
+/*
+ * @}
+ */
+
+#ifdef __cplusplus
+};
+#endif /* __cplusplus */
+
+#endif