summaryrefslogtreecommitdiff
path: root/src/tbm_backend_shm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tbm_backend_shm.c')
-rw-r--r--src/tbm_backend_shm.c936
1 files changed, 936 insertions, 0 deletions
diff --git a/src/tbm_backend_shm.c b/src/tbm_backend_shm.c
new file mode 100644
index 0000000..98b51d5
--- /dev/null
+++ b/src/tbm_backend_shm.c
@@ -0,0 +1,936 @@
+/**************************************************************************
+
+ libtbm_shm
+
+ Copyright 2012 Samsung Electronics co., Ltd. All Rights Reserved.
+
+ Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@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, 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.
+
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/ipc.h>
+#include <linux/unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <hal-common.h>
+#include <hal-tbm-types.h>
+#include <hal-tbm-interface.h>
+#include "tbm_backend_log.h"
+
+#define TBM_COLOR_FORMAT_COUNT 4
+#define STRERR_BUFSIZE 128
+
+#define SIZE_ALIGN(value, base) (((value) + ((base) - 1)) & ~((base) - 1))
+
+#define TBM_SURFACE_ALIGNMENT_PLANE (64)
+#define TBM_SURFACE_ALIGNMENT_PITCH_RGB (64)
+#define TBM_SURFACE_ALIGNMENT_PITCH_YUV (16)
+
+typedef struct _tbm_shm_bufmgr tbm_shm_bufmgr;
+typedef struct _tbm_shm_bo tbm_shm_bo;
+
+/* tbm buffor object for shm */
+struct _tbm_shm_bo {
+ key_t key;
+ void * pBase;
+
+ unsigned int size;
+
+ unsigned int flags_tbm;
+ hal_tbm_fd fd;
+
+ pthread_mutex_t mutex;
+ int device;
+ int opt;
+
+ tbm_shm_bufmgr *bufmgr_data;
+};
+
+/* tbm bufmgr private for shm */
+struct _tbm_shm_bufmgr {
+ int isLocal;
+ void* hashBos;
+};
+
+static char *STR_DEVICE[] = {
+ "DEF",
+ "CPU",
+ "2D",
+ "3D",
+ "MM"
+};
+
+static char *STR_OPT[] = {
+ "NONE",
+ "RD",
+ "WR",
+ "RDWR"
+};
+
+uint32_t tbm_shm_color_format_list[TBM_COLOR_FORMAT_COUNT] = {
+ HAL_TBM_FORMAT_ARGB8888,
+ HAL_TBM_FORMAT_XRGB8888,
+ HAL_TBM_FORMAT_NV12,
+ HAL_TBM_FORMAT_YUV420
+};
+
+char*
+target_name()
+{
+ FILE *f;
+ char *slash;
+ static int initialized = 0;
+ static char app_name[128];
+
+ if (initialized)
+ return app_name;
+
+ /* get the application name */
+ f = fopen("/proc/self/cmdline", "r");
+
+ if (!f)
+ return 0;
+
+ memset(app_name, 0x00, sizeof(app_name));
+
+ if (fgets(app_name, 100, f) == NULL) {
+ fclose(f);
+ return 0;
+ }
+
+ fclose(f);
+
+ if ((slash = strrchr(app_name, '/')) != NULL)
+ memmove(app_name, slash + 1, strlen(slash));
+
+ initialized = 1;
+
+ return app_name;
+}
+
+static hal_tbm_bo_handle
+_shm_bo_handle(tbm_shm_bo *bo_data, int device)
+{
+ hal_tbm_bo_handle bo_handle;
+ memset(&bo_handle, 0x0, sizeof(uint64_t));
+
+ switch (device) {
+ case HAL_TBM_DEVICE_DEFAULT:
+ case HAL_TBM_DEVICE_2D:
+ bo_handle.u32 = (uint32_t) bo_data->fd;
+ break;
+ case HAL_TBM_DEVICE_CPU:
+ bo_handle.ptr = (void *) bo_data->pBase;
+ break;
+ case HAL_TBM_DEVICE_3D:
+ case HAL_TBM_DEVICE_MM:
+ default:
+ TBM_BACKEND_DBG("Not supported device:%d\n", device);
+ bo_handle.ptr = (void *) bo_data->pBase;
+ break;
+ }
+
+ return bo_handle;
+}
+
+static int
+_shm_os_fd_set_cloexec(int fd)
+{
+ long flags;
+
+ if (fd == -1)
+ return -1;
+
+ flags = fcntl(fd, F_GETFD);
+ if (flags == -1)
+ return -1;
+
+ if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
+ return -1;
+
+ return 0;
+}
+
+static int
+_shm_set_cloexec_or_close(int fd)
+{
+ if (_shm_os_fd_set_cloexec(fd) != 0) {
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+static int
+_shm_create_tmpfile_cloexec(char *tmpname)
+{
+ int fd;
+
+#ifdef HAVE_MKOSTEMP
+ fd = mkostemp(tmpname, O_CLOEXEC);
+ if (fd >= 0)
+ unlink(tmpname);
+#else
+ fd = mkstemp(tmpname);
+ if (fd >= 0) {
+ fd = _shm_set_cloexec_or_close(fd);
+ unlink(tmpname);
+ }
+#endif
+
+ return fd;
+}
+
+static hal_tbm_fd
+_shm_create_anonymous_file(off_t size)
+{
+ static const char template[] = "/tbm-shared-XXXXXX";
+ const char *path;
+ char *name;
+ int fd;
+ int ret;
+
+ path = getenv("XDG_RUNTIME_DIR");
+ if (!path) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ name = malloc(strlen(path) + sizeof(template));
+ if (!name)
+ return -1;
+
+ snprintf(name, strlen(path) + sizeof(template), "%s%s", path, template);
+
+ fd = _shm_create_tmpfile_cloexec(name);
+
+ free(name);
+
+ if (fd < 0)
+ return -1;
+
+#ifdef HAVE_POSIX_FALLOCATE
+ do {
+ ret = posix_fallocate(fd, 0, size);
+ } while (ret == EINTR);
+ if (ret != 0) {
+ close(fd);
+ errno = ret;
+ return -1;
+ }
+#else
+ do {
+ ret = ftruncate(fd, size);
+ } while (ret < 0 && errno == EINTR);
+ if (ret < 0) {
+ close(fd);
+ return -1;
+ }
+#endif
+
+ return (hal_tbm_fd)fd;
+}
+
+static hal_tbm_bufmgr_capability
+tbm_shm_bufmgr_get_capabilities(hal_tbm_bufmgr *bufmgr, hal_tbm_error *error)
+{
+ hal_tbm_bufmgr_capability capabilities = HAL_TBM_BUFMGR_CAPABILITY_NONE;
+
+ capabilities = HAL_TBM_BUFMGR_CAPABILITY_SHARE_FD;
+
+ if (error)
+ *error = HAL_TBM_ERROR_NONE;
+
+ return capabilities;
+}
+
+static hal_tbm_error
+tbm_shm_bufmgr_get_supported_formats(hal_tbm_bufmgr *bufmgr,
+ uint32_t **formats, uint32_t *num)
+{
+ tbm_shm_bufmgr *bufmgr_data = (tbm_shm_bufmgr *)bufmgr;
+ uint32_t *color_formats;
+
+ TBM_BACKEND_RETURN_VAL_IF_FAIL(bufmgr_data != NULL, HAL_TBM_ERROR_INVALID_PARAMETER);
+
+ color_formats = (uint32_t *)calloc(1, sizeof(uint32_t) * TBM_COLOR_FORMAT_COUNT);
+ if (color_formats == NULL)
+ return HAL_TBM_ERROR_OUT_OF_MEMORY;
+
+ memcpy(color_formats, tbm_shm_color_format_list, sizeof(uint32_t) * TBM_COLOR_FORMAT_COUNT);
+
+ *formats = color_formats;
+ *num = TBM_COLOR_FORMAT_COUNT;
+
+ TBM_BACKEND_DBG("supported format count = %d\n", *num);
+
+ return HAL_TBM_ERROR_NONE;
+}
+
+static hal_tbm_error
+tbm_shm_bufmgr_get_plane_data(hal_tbm_bufmgr *bufmgr,
+ hal_tbm_format format, int plane_idx, int width, int height,
+ uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
+{
+ int ret = HAL_TBM_ERROR_NONE;
+ int bpp;
+ int _offset = 0;
+ int _pitch = 0;
+ int _size = 0;
+ int _bo_idx = 0;
+
+ switch (format) {
+ /* 16 bpp RGB */
+ case HAL_TBM_FORMAT_XRGB4444:
+ case HAL_TBM_FORMAT_XBGR4444:
+ case HAL_TBM_FORMAT_RGBX4444:
+ case HAL_TBM_FORMAT_BGRX4444:
+ case HAL_TBM_FORMAT_ARGB4444:
+ case HAL_TBM_FORMAT_ABGR4444:
+ case HAL_TBM_FORMAT_RGBA4444:
+ case HAL_TBM_FORMAT_BGRA4444:
+ case HAL_TBM_FORMAT_XRGB1555:
+ case HAL_TBM_FORMAT_XBGR1555:
+ case HAL_TBM_FORMAT_RGBX5551:
+ case HAL_TBM_FORMAT_BGRX5551:
+ case HAL_TBM_FORMAT_ARGB1555:
+ case HAL_TBM_FORMAT_ABGR1555:
+ case HAL_TBM_FORMAT_RGBA5551:
+ case HAL_TBM_FORMAT_BGRA5551:
+ case HAL_TBM_FORMAT_RGB565:
+ bpp = 16;
+ _offset = 0;
+ _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
+ _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ break;
+ /* 24 bpp RGB */
+ case HAL_TBM_FORMAT_RGB888:
+ case HAL_TBM_FORMAT_BGR888:
+ bpp = 24;
+ _offset = 0;
+ _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
+ _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ break;
+ /* 32 bpp RGB */
+ case HAL_TBM_FORMAT_XRGB8888:
+ case HAL_TBM_FORMAT_XBGR8888:
+ case HAL_TBM_FORMAT_RGBX8888:
+ case HAL_TBM_FORMAT_BGRX8888:
+ case HAL_TBM_FORMAT_ARGB8888:
+ case HAL_TBM_FORMAT_ABGR8888:
+ case HAL_TBM_FORMAT_RGBA8888:
+ case HAL_TBM_FORMAT_BGRA8888:
+ bpp = 32;
+ _offset = 0;
+ _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_RGB);
+ _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ break;
+
+ /* packed YCbCr */
+ case HAL_TBM_FORMAT_YUYV:
+ case HAL_TBM_FORMAT_YVYU:
+ case HAL_TBM_FORMAT_UYVY:
+ case HAL_TBM_FORMAT_VYUY:
+ case HAL_TBM_FORMAT_AYUV:
+ bpp = 32;
+ _offset = 0;
+ _pitch = SIZE_ALIGN((width * bpp) >> 3, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
+ _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ break;
+
+ /*
+ * 2 plane YCbCr
+ * index 0 = Y plane, [7:0] Y
+ * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
+ * or
+ * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
+ */
+ case HAL_TBM_FORMAT_NV12:
+ case HAL_TBM_FORMAT_NV21:
+ bpp = 12;
+ //if (plane_idx == 0)
+ {
+ _offset = 0;
+ _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
+ _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ if (plane_idx == 0)
+ break;
+ }
+ //else if (plane_idx == 1)
+ {
+ _offset += _size;
+ _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
+ _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ }
+ break;
+ case HAL_TBM_FORMAT_NV16:
+ case HAL_TBM_FORMAT_NV61:
+ bpp = 16;
+ //if(plane_idx == 0)
+ {
+ _offset = 0;
+ _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
+ _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ if (plane_idx == 0)
+ break;
+ }
+ //else if( plane_idx ==1 )
+ {
+ _offset += _size;
+ _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
+ _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ }
+ break;
+
+ /*
+ * 3 plane YCbCr
+ * index 0: Y plane, [7:0] Y
+ * index 1: Cb plane, [7:0] Cb
+ * index 2: Cr plane, [7:0] Cr
+ * or
+ * index 1: Cr plane, [7:0] Cr
+ * index 2: Cb plane, [7:0] Cb
+ */
+ /*
+ NATIVE_BUFFER_FORMAT_YV12
+ NATIVE_BUFFER_FORMAT_I420
+ */
+ case HAL_TBM_FORMAT_YUV410:
+ case HAL_TBM_FORMAT_YVU410:
+ bpp = 9;
+ _bo_idx = 0;
+ break;
+ case HAL_TBM_FORMAT_YUV411:
+ case HAL_TBM_FORMAT_YVU411:
+ case HAL_TBM_FORMAT_YUV420:
+ case HAL_TBM_FORMAT_YVU420:
+ bpp = 12;
+ //if(plane_idx == 0)
+ {
+ _offset = 0;
+ _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
+ _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ if (plane_idx == 0)
+ break;
+ }
+ //else if( plane_idx == 1 )
+ {
+ _offset += _size;
+ _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
+ _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ if (plane_idx == 1)
+ break;
+ }
+ //else if (plane_idx == 2 )
+ {
+ _offset += _size;
+ _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
+ _size = SIZE_ALIGN(_pitch * (height / 2), TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ }
+ break;
+ case HAL_TBM_FORMAT_YUV422:
+ case HAL_TBM_FORMAT_YVU422:
+ bpp = 16;
+ //if(plane_idx == 0)
+ {
+ _offset = 0;
+ _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
+ _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ if (plane_idx == 0)
+ break;
+ }
+ //else if( plane_idx == 1 )
+ {
+ _offset += _size;
+ _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
+ _size = SIZE_ALIGN(_pitch * (height), TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ if (plane_idx == 1)
+ break;
+ }
+ //else if (plane_idx == 2 )
+ {
+ _offset += _size;
+ _pitch = SIZE_ALIGN(width / 2, TBM_SURFACE_ALIGNMENT_PITCH_YUV/2);
+ _size = SIZE_ALIGN(_pitch * (height), TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ }
+ break;
+ case HAL_TBM_FORMAT_YUV444:
+ case HAL_TBM_FORMAT_YVU444:
+ bpp = 24;
+ //if(plane_idx == 0)
+ {
+ _offset = 0;
+ _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
+ _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ if (plane_idx == 0)
+ break;
+ }
+ //else if( plane_idx == 1 )
+ {
+ _offset += _size;
+ _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
+ _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ if (plane_idx == 1)
+ break;
+ }
+ //else if (plane_idx == 2 )
+ {
+ _offset += _size;
+ _pitch = SIZE_ALIGN(width, TBM_SURFACE_ALIGNMENT_PITCH_YUV);
+ _size = SIZE_ALIGN(_pitch * height, TBM_SURFACE_ALIGNMENT_PLANE);
+ _bo_idx = 0;
+ }
+ break;
+ default:
+ bpp = 0;
+ break;
+ }
+
+ *size = _size;
+ *offset = _offset;
+ *pitch = _pitch;
+ *bo_idx = _bo_idx;
+
+ return ret;
+}
+
+static hal_tbm_bo *
+tbm_shm_bufmgr_alloc_bo(hal_tbm_bufmgr *bufmgr, unsigned int size,
+ hal_tbm_bo_memory_type flags, hal_tbm_error *error)
+
+{
+ tbm_shm_bufmgr *bufmgr_data = (tbm_shm_bufmgr *)bufmgr;
+ tbm_shm_bo *bo_data;
+ hal_tbm_fd fd = -1;
+
+ if (bufmgr_data == NULL) {
+ TBM_BACKEND_ERR("bufmgr_data is null\n");
+ if (error) *error = HAL_TBM_ERROR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+ if (flags & HAL_TBM_BO_SCANOUT)
+ TBM_BACKEND_DBG("[libtbm-shm:%d] warning %s:%d HAL_TBM_BO_SCANOUT ins't supported\n", getpid(), __FUNCTION__, __LINE__);
+
+ bo_data = calloc(1, sizeof(struct _tbm_shm_bo));
+ if (!bo_data) {
+ TBM_BACKEND_DBG("[libtbm-shm:%d] error %s:%d Fail to allocate the bo private\n", getpid(), __FUNCTION__, __LINE__);
+ if (error) *error = HAL_TBM_ERROR_INVALID_OPERATION;
+ return 0;
+ }
+
+ bo_data->fd = -1;
+ fd = _shm_create_anonymous_file((off_t)size);
+ if (fd < 0) {
+ TBM_BACKEND_DBG("[libtbm-shm:%d] error %s:%d Fail to create a buffer file(size: %d) %m\n", getpid(),
+ __FUNCTION__, __LINE__, size);
+ free(bo_data);
+ if (error) *error = HAL_TBM_ERROR_INVALID_OPERATION;
+ return 0;
+ }
+
+ bo_data->fd = fd;
+ bo_data->pBase = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (bo_data->pBase == MAP_FAILED) {
+ TBM_BACKEND_DBG("[libtbm-shm:%d] error %s:%d Fail to mmap: %m\n", getpid(),
+ __FUNCTION__, __LINE__);
+ close(fd);
+ free(bo_data);
+ if (error) *error = HAL_TBM_ERROR_INVALID_OPERATION;
+ return 0;
+ }
+
+ bo_data->size = size;
+ bo_data->flags_tbm = HAL_TBM_BO_DEFAULT | HAL_TBM_BO_NONCACHABLE;
+
+ TBM_BACKEND_DBG(" [%s] bo:%p, fd:%d, flags:%d, size:%d\n", target_name(), bo_data, bo_data->fd, bo_data->flags_tbm, bo_data->size);
+ if (error) *error = HAL_TBM_ERROR_NONE;
+
+ return (hal_tbm_bo *) bo_data;
+}
+
+static hal_tbm_bo *
+tbm_shm_bufmgr_import_fd(hal_tbm_bufmgr *bufmgr, hal_tbm_fd key, hal_tbm_error *error)
+{
+ tbm_shm_bo *bo_data;
+ int real_size;
+ char buf[STRERR_BUFSIZE];
+ hal_tbm_fd fd;
+
+ if (key < 0) {
+ TBM_BACKEND_ERR("Invalid fd(%d)\n", key);
+ if (error)
+ *error = HAL_TBM_ERROR_INVALID_PARAMETER;
+ return 0;
+ }
+
+ bo_data = calloc(1, sizeof(struct _tbm_shm_bo));
+ if (!bo_data) {
+ TBM_BACKEND_ERR("Fail to allocate the bo private\n");
+ if (error)
+ *error = HAL_TBM_ERROR_INVALID_OPERATION;
+ return 0;
+ }
+
+ real_size = lseek(key, 0, SEEK_END);
+ if (real_size < 0) {
+ TBM_BACKEND_ERR("Fail to lseek(err:%s)\n",
+ strerror_r(errno, buf, STRERR_BUFSIZE));
+ free(bo_data);
+ if (error)
+ *error = HAL_TBM_ERROR_INVALID_OPERATION;
+ return 0;
+ }
+
+ bo_data->pBase = mmap(NULL, real_size,
+ PROT_READ | PROT_WRITE, MAP_SHARED, key, 0);
+ if (bo_data->pBase == MAP_FAILED) {
+ TBM_BACKEND_ERR("Fail to mmap (size:%d, err:%s)\n",
+ real_size, strerror_r(errno, buf, STRERR_BUFSIZE));
+ free(bo_data);
+ if (error)
+ *error = HAL_TBM_ERROR_INVALID_OPERATION;
+ return 0;
+ }
+
+ fd = dup(key);
+ if (fd < 0) {
+ TBM_BACKEND_ERR("dup failed: %m");
+ free(bo_data);
+ if (error)
+ *error = HAL_TBM_ERROR_INVALID_PARAMETER;
+ return 0;
+ }
+
+ bo_data->size = real_size;
+ bo_data->fd = fd;
+ bo_data->flags_tbm = HAL_TBM_BO_DEFAULT | HAL_TBM_BO_NONCACHABLE;
+
+ TBM_BACKEND_DBG(" [%s] bo:%p, shm:%d, flags:%d, size:%d imported_fd:%d\n", target_name(), bo_data, bo_data->fd,
+ bo_data->flags_tbm, bo_data->size, key);
+
+ if (error)
+ *error = HAL_TBM_ERROR_NONE;
+
+ return (hal_tbm_bo *)bo_data;
+}
+
+static void
+tbm_shm_bo_free(hal_tbm_bo *bo)
+{
+ tbm_shm_bo *bo_data = (tbm_shm_bo *)bo;
+ char buf[STRERR_BUFSIZE];
+
+ TBM_BACKEND_RETURN_IF_FAIL(bo_data != NULL);
+
+ TBM_BACKEND_DBG(" [%s] bo:%p, shm:%d, size:%d\n", target_name(), bo_data, bo_data->fd, bo_data->size);
+
+ if (bo_data->pBase) {
+ if (munmap(bo_data->pBase, bo_data->size) == -1) {
+ TBM_BACKEND_ERR("bo_data:%p fail to munmap(%s)\n",
+ bo_data, strerror_r(errno, buf, STRERR_BUFSIZE));
+ }
+ }
+
+ /* Free shm object*/
+ close(bo_data->fd);
+ free(bo_data);
+}
+
+static int
+tbm_shm_bo_get_size(hal_tbm_bo *bo, hal_tbm_error *error)
+{
+ tbm_shm_bo *bo_data = (tbm_shm_bo *)bo;
+
+ if (!bo_data) {
+ if (error)
+ *error = HAL_TBM_ERROR_INVALID_PARAMETER;
+ return 0;
+ }
+
+ if (error)
+ *error = HAL_TBM_ERROR_NONE;
+
+ return bo_data->size;
+}
+
+
+static hal_tbm_bo_memory_type
+tbm_shm_bo_get_memory_type(hal_tbm_bo *bo, hal_tbm_error *error)
+{
+ tbm_shm_bo *bo_data = (tbm_shm_bo *)bo;
+
+ if (!bo_data) {
+ if (error)
+ *error = HAL_TBM_ERROR_INVALID_PARAMETER;
+ return HAL_TBM_BO_DEFAULT;
+ }
+
+ if (error)
+ *error = HAL_TBM_ERROR_NONE;
+
+ return bo_data->flags_tbm;
+}
+
+static hal_tbm_bo_handle
+tbm_shm_bo_get_handle(hal_tbm_bo *bo, hal_tbm_bo_device_type device, hal_tbm_error *error)
+{
+ hal_tbm_bo_handle bo_handle;
+ tbm_shm_bo *bo_data = (tbm_shm_bo *)bo;;
+
+ if (!bo_data) {
+ if (error)
+ *error = HAL_TBM_ERROR_INVALID_PARAMETER;
+ return (hal_tbm_bo_handle) NULL;
+ }
+
+ TBM_BACKEND_DBG("[%s] bo:%p, shm:%d, flags:%d, size:%d, %s\n", target_name(), bo_data, bo_data->fd,
+ bo_data->flags_tbm, bo_data->size, STR_DEVICE[device]);
+
+ /*Get mapped bo_handle*/
+ bo_handle = _shm_bo_handle(bo_data, device);
+ if (bo_handle.ptr == NULL) {
+ TBM_BACKEND_DBG("error Cannot get handle: shm:%d, device:%d\n", bo_data->fd, device);
+
+ if (error)
+ *error = HAL_TBM_ERROR_INVALID_OPERATION;
+ return (hal_tbm_bo_handle) NULL;
+ }
+
+ if (error)
+ *error = HAL_TBM_ERROR_NONE;
+
+ return bo_handle;
+}
+
+
+static hal_tbm_bo_handle
+tbm_shm_bo_map(hal_tbm_bo *bo, hal_tbm_bo_device_type device,
+ hal_tbm_bo_access_option opt, hal_tbm_error *error)
+{
+ hal_tbm_bo_handle bo_handle;
+ tbm_shm_bo *bo_data = (tbm_shm_bo *)bo;;
+
+ if (!bo_data) {
+ if (error)
+ *error = HAL_TBM_ERROR_INVALID_PARAMETER;
+ return (hal_tbm_bo_handle) NULL;
+ }
+
+ TBM_BACKEND_DBG(" [%s] bo:%p, shm:%d, %s, %s\n", target_name(), bo_data, bo_data->fd, STR_DEVICE[device],
+ STR_OPT[opt]);
+
+ /*Get mapped bo_handle*/
+ bo_handle = _shm_bo_handle(bo_data, device);
+ if (bo_handle.ptr == NULL) {
+ TBM_BACKEND_DBG("error Cannot get handle: shm:%d, device:%d, opt:%d\n", bo_data->fd, device, opt);
+ if (error)
+ *error = HAL_TBM_ERROR_INVALID_OPERATION;
+ return (hal_tbm_bo_handle) NULL;
+ }
+
+ if (error)
+ *error = HAL_TBM_ERROR_NONE;
+
+ return bo_handle;
+}
+
+static hal_tbm_error
+tbm_shm_bo_unmap(hal_tbm_bo *bo)
+
+{
+ tbm_shm_bo *bo_data = (tbm_shm_bo *)bo;;
+ if (!bo_data)
+ return HAL_TBM_ERROR_INVALID_PARAMETER;
+
+ TBM_BACKEND_DBG(" [%s] bo:%p, shm:%d\n", target_name(), bo_data, bo_data->fd);
+
+ return HAL_TBM_ERROR_NONE;
+}
+
+static hal_tbm_fd
+tbm_shm_bo_export_fd(hal_tbm_bo *bo, hal_tbm_error *error)
+{
+ tbm_shm_bo *bo_data = (tbm_shm_bo *)bo;
+ hal_tbm_fd fd;
+
+ if (!bo_data) {
+ if (error)
+ *error = HAL_TBM_ERROR_INVALID_PARAMETER;
+ return -1;
+ }
+
+ fd = dup(bo_data->fd);
+ if (fd < 0) {
+ TBM_BACKEND_ERR("dup failed: %m");
+ if (error)
+ *error = HAL_TBM_ERROR_INVALID_PARAMETER;
+ return -1;
+ }
+
+ TBM_BACKEND_DBG(" [%s] bo:%p, shm:%d, flags:%d, size:%d, exported_fd:%d\n", target_name(), bo_data, bo_data->fd,
+ bo_data->flags_tbm, bo_data->size, fd);
+
+ if (error)
+ *error = HAL_TBM_ERROR_NONE;
+
+ return fd;
+}
+
+static int
+hal_backend_tbm_shm_exit(void *data)
+{
+ hal_tbm_backend_data *backend_data = (hal_tbm_backend_data *)data;
+ tbm_shm_bufmgr *bufmgr_data;
+
+ TBM_BACKEND_RETURN_VAL_IF_FAIL(backend_data != NULL, -1);
+
+ bufmgr_data = (tbm_shm_bufmgr *)backend_data->bufmgr;
+ TBM_BACKEND_RETURN_VAL_IF_FAIL(bufmgr_data != NULL, -1);
+
+ if (backend_data->bufmgr_funcs)
+ free(backend_data->bufmgr_funcs);
+ if (backend_data->bo_funcs)
+ free(backend_data->bo_funcs);
+
+ free(backend_data->bufmgr);
+ free(backend_data);
+
+ return HAL_TBM_ERROR_NONE;
+}
+
+static int
+hal_backend_tbm_shm_init(void **data)
+{
+ hal_tbm_backend_data *backend_data = NULL;
+ hal_tbm_bufmgr_funcs *bufmgr_funcs = NULL;
+ hal_tbm_bo_funcs *bo_funcs = NULL;
+ tbm_shm_bufmgr *bufmgr_data = NULL;
+
+ /* allocate a hal_tbm_backend_data */
+ backend_data = calloc(1, sizeof(struct _hal_tbm_backend_data));
+ if (!backend_data) {
+ TBM_BACKEND_ERR("fail to alloc backend_data!\n");
+ *data = NULL;
+ return -1;
+ }
+ *data = backend_data;
+
+ /* allocate a hal_tbm_bufmgr */
+ bufmgr_data = calloc(1, sizeof(struct _tbm_shm_bufmgr));
+ if (!bufmgr_data) {
+ TBM_BACKEND_ERR("fail to alloc bufmgr_data!\n");
+ goto fail_alloc_bufmgr_data;
+ }
+ backend_data->bufmgr = (hal_tbm_bufmgr *)bufmgr_data;
+
+ /* alloc and register bufmgr_funcs */
+ bufmgr_funcs = calloc(1, sizeof(struct _hal_tbm_bufmgr_funcs));
+ if (!bufmgr_funcs) {
+ TBM_BACKEND_ERR("fail to alloc bufmgr_funcs!\n");
+ goto fail_alloc_bufmgr_funcs;
+ }
+ backend_data->bufmgr_funcs = bufmgr_funcs;
+
+ bufmgr_funcs->bufmgr_get_capabilities = tbm_shm_bufmgr_get_capabilities;
+ bufmgr_funcs->bufmgr_get_supported_formats = tbm_shm_bufmgr_get_supported_formats;
+ bufmgr_funcs->bufmgr_get_plane_data = tbm_shm_bufmgr_get_plane_data;
+ bufmgr_funcs->bufmgr_alloc_bo = tbm_shm_bufmgr_alloc_bo;
+ bufmgr_funcs->bufmgr_alloc_bo_with_format = NULL;
+ bufmgr_funcs->bufmgr_import_fd = tbm_shm_bufmgr_import_fd;
+ bufmgr_funcs->bufmgr_import_key = NULL;
+
+ /* alloc and register bo_funcs */
+ bo_funcs = calloc(1, sizeof(struct _hal_tbm_bo_funcs));
+ if (!bo_funcs) {
+ TBM_BACKEND_ERR("fail to alloc bo_funcs!\n");
+ goto fail_alloc_bo_funcs;
+ }
+ backend_data->bo_funcs = bo_funcs;
+
+ bo_funcs->bo_free = tbm_shm_bo_free;
+ bo_funcs->bo_get_size = tbm_shm_bo_get_size;
+ bo_funcs->bo_get_memory_types = tbm_shm_bo_get_memory_type;
+ bo_funcs->bo_get_handle = tbm_shm_bo_get_handle;
+ bo_funcs->bo_map = tbm_shm_bo_map;
+ bo_funcs->bo_unmap = tbm_shm_bo_unmap;
+ bo_funcs->bo_lock = NULL;
+ bo_funcs->bo_unlock = NULL;
+ bo_funcs->bo_export_fd = tbm_shm_bo_export_fd;
+ bo_funcs->bo_export_key = NULL;
+
+ TBM_BACKEND_DBG("tbm_shm_init: done\n");
+ TBM_BACKEND_DBG("no drm_fd\n");
+
+ return HAL_TBM_ERROR_NONE;
+
+fail_alloc_bo_funcs:
+ free(bufmgr_funcs);
+fail_alloc_bufmgr_funcs:
+ free(bufmgr_data);
+fail_alloc_bufmgr_data:
+ free(backend_data);
+
+ *data = NULL;
+
+ return -1;
+}
+
+hal_backend hal_backend_tbm_data = {
+ "shm",
+ "Samsung",
+ HAL_ABI_VERSION_TIZEN_6_5,
+ hal_backend_tbm_shm_init,
+ hal_backend_tbm_shm_exit
+};
+