summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerek Foreman <derekf@osg.samsung.com>2016-06-02 07:06:26 -0500
committerDerek Foreman <derekf@osg.samsung.com>2016-06-03 11:05:28 -0500
commit821aada3c442af82339b01df036fa13aa086491a (patch)
treec8a8be7ef1e1842db4112f56b0a608f1fbe5833b
parent0f07f67b127ae2c1810b7955f049ff53584a53fc (diff)
downloadefl-821aada3c442af82339b01df036fa13aa086491a.tar.gz
wayland_shm: Add exynos allocator for dmabuf
Allows clients on exynos hardware to allocate GEM buffer objects to back DMAbuf buffers.
-rw-r--r--src/modules/evas/engines/wayland_shm/evas_dmabuf.c99
-rw-r--r--src/static_libs/libdrm/exynos_drm.h172
-rw-r--r--src/static_libs/libdrm/exynos_drmif.h112
3 files changed, 383 insertions, 0 deletions
diff --git a/src/modules/evas/engines/wayland_shm/evas_dmabuf.c b/src/modules/evas/engines/wayland_shm/evas_dmabuf.c
index 60093aeaba..3cb112c7e0 100644
--- a/src/modules/evas/engines/wayland_shm/evas_dmabuf.c
+++ b/src/modules/evas/engines/wayland_shm/evas_dmabuf.c
@@ -10,6 +10,10 @@
#include <intel_bufmgr.h>
#include <i915_drm.h>
+#include <exynos_drm.h>
+#include <exynos_drmif.h>
+#include <sys/mman.h>
+
#include "linux-dmabuf-unstable-v1-client-protocol.h"
#define SYM(lib, xx) \
@@ -88,6 +92,11 @@ drm_intel_bo *(*sym_drm_intel_bo_alloc_tiled)(drm_intel_bufmgr *mgr, const char
void (*sym_drm_intel_bo_unreference)(drm_intel_bo *bo) = NULL;
int (*sym_drmPrimeHandleToFD)(int fd, uint32_t handle, uint32_t flags, int *prime_fd);
+struct exynos_device *(*sym_exynos_device_create)(int fd) = NULL;
+struct exynos_bo *(*sym_exynos_bo_create)(struct exynos_device *dev, size_t size, uint32_t flags) = NULL;
+void *(*sym_exynos_bo_map)(struct exynos_bo *bo) = NULL;
+void (*sym_exynos_bo_destroy)(struct exynos_bo *bo) = NULL;
+
static Buffer_Handle *
_intel_alloc(Buffer_Manager *self, const char *name, int w, int h, unsigned long *stride, int32_t *fd)
{
@@ -179,6 +188,95 @@ err:
return EINA_FALSE;
}
+static Buffer_Handle *
+_exynos_alloc(Buffer_Manager *self, const char *name EINA_UNUSED, int w, int h, unsigned long *stride, int32_t *fd)
+{
+ size_t size = w * h * 4;
+ struct exynos_bo *out;
+
+ *stride = w * 4;
+ out = sym_exynos_bo_create(self->priv, size, 0);
+ if (!out) return NULL;
+ /* First try to allocate an mmapable buffer with O_RDWR,
+ * if that fails retry unmappable - if the compositor is
+ * using GL it won't need to mmap the buffer and this can
+ * work - otherwise it'll reject this buffer and we'll
+ * have to fall back to shm rendering.
+ */
+ if (sym_drmPrimeHandleToFD(drm_fd, out->handle,
+ DRM_CLOEXEC | O_RDWR, fd) != 0)
+ if (sym_drmPrimeHandleToFD(drm_fd, out->handle,
+ DRM_CLOEXEC, fd) != 0) goto err;
+
+ return (Buffer_Handle *)out;
+
+err:
+ sym_exynos_bo_destroy(out);
+ return NULL;
+}
+
+static void *
+_exynos_map(Dmabuf_Buffer *buf)
+{
+ struct exynos_bo *bo;
+ void *ptr;
+
+ bo = (struct exynos_bo *)buf->bh;
+ ptr = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, buf->fd, 0);
+ if (ptr == MAP_FAILED) return NULL;
+ return ptr;
+}
+
+static void
+_exynos_unmap(Dmabuf_Buffer *buf)
+{
+ struct exynos_bo *bo;
+
+ bo = (struct exynos_bo *)buf->bh;
+ munmap(buf->mapping, bo->size);
+}
+
+static void
+_exynos_discard(Dmabuf_Buffer *buf)
+{
+ struct exynos_bo *bo;
+
+ bo = (struct exynos_bo *)buf->bh;
+ sym_exynos_bo_destroy(bo);
+}
+
+static Eina_Bool
+_exynos_buffer_manager_setup(int fd)
+{
+ Eina_Bool fail = EINA_FALSE;
+ void *drm_exynos_lib;
+
+ drm_exynos_lib = dlopen("libdrm_exynos.so", RTLD_LAZY | RTLD_GLOBAL);
+ if (!drm_exynos_lib) return EINA_FALSE;
+
+ SYM(drm_exynos_lib, exynos_device_create);
+ SYM(drm_exynos_lib, exynos_bo_create);
+ SYM(drm_exynos_lib, exynos_bo_map);
+ SYM(drm_exynos_lib, exynos_bo_destroy);
+ SYM(drm_exynos_lib, drmPrimeHandleToFD);
+
+ if (fail) goto err;
+
+ buffer_manager->priv = sym_exynos_device_create(fd);
+ if (!buffer_manager->priv) goto err;
+
+ buffer_manager->alloc = _exynos_alloc;
+ buffer_manager->map = _exynos_map;
+ buffer_manager->unmap = _exynos_unmap;
+ buffer_manager->discard = _exynos_discard;
+
+ return EINA_TRUE;
+
+err:
+ dlclose(drm_exynos_lib);
+ return EINA_FALSE;
+}
+
static Buffer_Manager *
_buffer_manager_get(void)
{
@@ -194,6 +292,7 @@ _buffer_manager_get(void)
if (fd < 0) goto err_drm;
success = _intel_buffer_manager_setup(fd);
+ if (!success) success = _exynos_buffer_manager_setup(fd);
if (!success) goto err_bm;
drm_fd = fd;
diff --git a/src/static_libs/libdrm/exynos_drm.h b/src/static_libs/libdrm/exynos_drm.h
new file mode 100644
index 0000000000..c3af0ac5f6
--- /dev/null
+++ b/src/static_libs/libdrm/exynos_drm.h
@@ -0,0 +1,172 @@
+/* exynos_drm.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ * Joonyoung Shim <jy0922.shim@samsung.com>
+ * Seung-Woo Kim <sw0312.kim@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 _EXYNOS_DRM_H_
+#define _EXYNOS_DRM_H_
+
+#include "drm.h"
+
+/**
+ * User-desired buffer creation information structure.
+ *
+ * @size: user-desired memory allocation size.
+ * - this size value would be page-aligned internally.
+ * @flags: user request for setting memory type or cache attributes.
+ * @handle: returned a handle to created gem object.
+ * - this handle will be set by gem module of kernel side.
+ */
+struct drm_exynos_gem_create {
+ uint64_t size;
+ unsigned int flags;
+ unsigned int handle;
+};
+
+/**
+ * A structure to gem information.
+ *
+ * @handle: a handle to gem object created.
+ * @flags: flag value including memory type and cache attribute and
+ * this value would be set by driver.
+ * @size: size to memory region allocated by gem and this size would
+ * be set by driver.
+ */
+struct drm_exynos_gem_info {
+ unsigned int handle;
+ unsigned int flags;
+ uint64_t size;
+};
+
+/**
+ * A structure for user connection request of virtual display.
+ *
+ * @connection: indicate whether doing connetion or not by user.
+ * @extensions: if this value is 1 then the vidi driver would need additional
+ * 128bytes edid data.
+ * @edid: the edid data pointer from user side.
+ */
+struct drm_exynos_vidi_connection {
+ unsigned int connection;
+ unsigned int extensions;
+ uint64_t edid;
+};
+
+/* memory type definitions. */
+enum e_drm_exynos_gem_mem_type {
+ /* Physically Continuous memory and used as default. */
+ EXYNOS_BO_CONTIG = 0 << 0,
+ /* Physically Non-Continuous memory. */
+ EXYNOS_BO_NONCONTIG = 1 << 0,
+ /* non-cachable mapping and used as default. */
+ EXYNOS_BO_NONCACHABLE = 0 << 1,
+ /* cachable mapping. */
+ EXYNOS_BO_CACHABLE = 1 << 1,
+ /* write-combine mapping. */
+ EXYNOS_BO_WC = 1 << 2,
+ EXYNOS_BO_MASK = EXYNOS_BO_NONCONTIG | EXYNOS_BO_CACHABLE |
+ EXYNOS_BO_WC
+};
+
+struct drm_exynos_g2d_get_ver {
+ __u32 major;
+ __u32 minor;
+};
+
+struct drm_exynos_g2d_cmd {
+ __u32 offset;
+ __u32 data;
+};
+
+enum drm_exynos_g2d_buf_type {
+ G2D_BUF_USERPTR = 1 << 31,
+};
+
+enum drm_exynos_g2d_event_type {
+ G2D_EVENT_NOT,
+ G2D_EVENT_NONSTOP,
+ G2D_EVENT_STOP, /* not yet */
+};
+
+struct drm_exynos_g2d_userptr {
+ unsigned long userptr;
+ unsigned long size;
+};
+
+struct drm_exynos_g2d_set_cmdlist {
+ __u64 cmd;
+ __u64 cmd_buf;
+ __u32 cmd_nr;
+ __u32 cmd_buf_nr;
+
+ /* for g2d event */
+ __u64 event_type;
+ __u64 user_data;
+};
+
+struct drm_exynos_g2d_exec {
+ __u64 async;
+};
+
+#define DRM_EXYNOS_GEM_CREATE 0x00
+/* Reserved 0x04 ~ 0x05 for exynos specific gem ioctl */
+#define DRM_EXYNOS_GEM_GET 0x04
+#define DRM_EXYNOS_VIDI_CONNECTION 0x07
+
+/* G2D */
+#define DRM_EXYNOS_G2D_GET_VER 0x20
+#define DRM_EXYNOS_G2D_SET_CMDLIST 0x21
+#define DRM_EXYNOS_G2D_EXEC 0x22
+
+#define DRM_IOCTL_EXYNOS_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \
+ DRM_EXYNOS_GEM_CREATE, struct drm_exynos_gem_create)
+
+#define DRM_IOCTL_EXYNOS_GEM_GET DRM_IOWR(DRM_COMMAND_BASE + \
+ DRM_EXYNOS_GEM_GET, struct drm_exynos_gem_info)
+
+#define DRM_IOCTL_EXYNOS_VIDI_CONNECTION DRM_IOWR(DRM_COMMAND_BASE + \
+ DRM_EXYNOS_VIDI_CONNECTION, struct drm_exynos_vidi_connection)
+
+#define DRM_IOCTL_EXYNOS_G2D_GET_VER DRM_IOWR(DRM_COMMAND_BASE + \
+ DRM_EXYNOS_G2D_GET_VER, struct drm_exynos_g2d_get_ver)
+#define DRM_IOCTL_EXYNOS_G2D_SET_CMDLIST DRM_IOWR(DRM_COMMAND_BASE + \
+ DRM_EXYNOS_G2D_SET_CMDLIST, struct drm_exynos_g2d_set_cmdlist)
+#define DRM_IOCTL_EXYNOS_G2D_EXEC DRM_IOWR(DRM_COMMAND_BASE + \
+ DRM_EXYNOS_G2D_EXEC, struct drm_exynos_g2d_exec)
+
+/* EXYNOS specific events */
+#define DRM_EXYNOS_G2D_EVENT 0x80000000
+
+struct drm_exynos_g2d_event {
+ struct drm_event base;
+ __u64 user_data;
+ __u32 tv_sec;
+ __u32 tv_usec;
+ __u32 cmdlist_no;
+ __u32 reserved;
+};
+
+#endif
diff --git a/src/static_libs/libdrm/exynos_drmif.h b/src/static_libs/libdrm/exynos_drmif.h
new file mode 100644
index 0000000000..626e39985a
--- /dev/null
+++ b/src/static_libs/libdrm/exynos_drmif.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Authors:
+ * Inki Dae <inki.dae@samsung.com>
+ */
+
+#ifndef EXYNOS_DRMIF_H_
+#define EXYNOS_DRMIF_H_
+
+#include <xf86drm.h>
+#include <stdint.h>
+#include "exynos_drm.h"
+
+struct exynos_device {
+ int fd;
+};
+
+/*
+ * Exynos Buffer Object structure.
+ *
+ * @dev: exynos device object allocated.
+ * @handle: a gem handle to gem object created.
+ * @flags: indicate memory allocation and cache attribute types.
+ * @size: size to the buffer created.
+ * @vaddr: user space address to a gem buffer mmaped.
+ * @name: a gem global handle from flink request.
+ */
+struct exynos_bo {
+ struct exynos_device *dev;
+ uint32_t handle;
+ uint32_t flags;
+ size_t size;
+ void *vaddr;
+ uint32_t name;
+};
+
+#define EXYNOS_EVENT_CONTEXT_VERSION 1
+
+/*
+ * Exynos Event Context structure.
+ *
+ * @base: base context (for core events).
+ * @version: version info similar to the one in 'drmEventContext'.
+ * @g2d_event_handler: handler for G2D events.
+ */
+struct exynos_event_context {
+ drmEventContext base;
+
+ int version;
+
+ void (*g2d_event_handler)(int fd, unsigned int cmdlist_no,
+ unsigned int tv_sec, unsigned int tv_usec,
+ void *user_data);
+};
+
+/*
+ * device related functions:
+ */
+struct exynos_device * exynos_device_create(int fd);
+void exynos_device_destroy(struct exynos_device *dev);
+
+/*
+ * buffer-object related functions:
+ */
+struct exynos_bo * exynos_bo_create(struct exynos_device *dev,
+ size_t size, uint32_t flags);
+int exynos_bo_get_info(struct exynos_device *dev, uint32_t handle,
+ size_t *size, uint32_t *flags);
+void exynos_bo_destroy(struct exynos_bo *bo);
+struct exynos_bo * exynos_bo_from_name(struct exynos_device *dev, uint32_t name);
+int exynos_bo_get_name(struct exynos_bo *bo, uint32_t *name);
+uint32_t exynos_bo_handle(struct exynos_bo *bo);
+void * exynos_bo_map(struct exynos_bo *bo);
+int exynos_prime_handle_to_fd(struct exynos_device *dev, uint32_t handle,
+ int *fd);
+int exynos_prime_fd_to_handle(struct exynos_device *dev, int fd,
+ uint32_t *handle);
+
+/*
+ * Virtual Display related functions:
+ */
+int exynos_vidi_connection(struct exynos_device *dev, uint32_t connect,
+ uint32_t ext, void *edid);
+
+/*
+ * event handling related functions:
+ */
+int exynos_handle_event(struct exynos_device *dev,
+ struct exynos_event_context *ctx);
+
+
+#endif /* EXYNOS_DRMIF_H_ */