diff options
author | Derek Foreman <derekf@osg.samsung.com> | 2016-06-02 07:06:26 -0500 |
---|---|---|
committer | Derek Foreman <derekf@osg.samsung.com> | 2016-06-03 11:05:28 -0500 |
commit | 821aada3c442af82339b01df036fa13aa086491a (patch) | |
tree | c8a8be7ef1e1842db4112f56b0a608f1fbe5833b | |
parent | 0f07f67b127ae2c1810b7955f049ff53584a53fc (diff) | |
download | efl-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.c | 99 | ||||
-rw-r--r-- | src/static_libs/libdrm/exynos_drm.h | 172 | ||||
-rw-r--r-- | src/static_libs/libdrm/exynos_drmif.h | 112 |
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_ */ |