From: Rusty Lynch Date: Tue, 2 Oct 2012 00:36:32 +0000 (-0700) Subject: Adding slp buffer support X-Git-Tag: accepted/2.0alpha-wayland/20121114.232726~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c292eaac9dd608ab8a5f63a07ed72260c2824eba;p=profile%2Fivi%2Flibdrm.git Adding slp buffer support --- diff --git a/Makefile.am b/Makefile.am index 8ecd9d9..bb7b769 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,7 +49,11 @@ if HAVE_EXYNOS EXYNOS_SUBDIR = exynos endif -SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) tests include man +if HAVE_SLP +SLP_SUBDIR = slp +endif + +SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) $(SLP_SUBDIR) tests include man libdrm_la_LTLIBRARIES = libdrm.la libdrm_ladir = $(libdir) diff --git a/configure.ac b/configure.ac index 0c19929..1a682a0 100644 --- a/configure.ac +++ b/configure.ac @@ -114,6 +114,19 @@ AC_ARG_ENABLE(exynos-experimental-api, [Enable support for EXYNOS's experimental API (default: disabled)]), [EXYNOS=$enableval], [EXYNOS=no]) +AC_ARG_ENABLE(slp, + AS_HELP_STRING([--disable-slp], + [Enable support for slp's API (default: auto)]), + [SLP=$enableval], [SLP=auto]) + +AC_ARG_VAR([bufmgr_dir], [Directory of slp-bufmgr]) + +if test "x$bufmgr_dir" = xyes; then + AC_DEFINE_UNQUOTED(BUFMGR_DIR, "$bufmgr_dir", [Directory for the modules of slp_bufmgr]) +else + AC_DEFINE(BUFMGR_DIR, "/usr/lib/bufmgr", [Directory for the modules of slp_bufmgr]) +fi + dnl =========================================================================== dnl check compiler flags AC_DEFUN([LIBDRM_CC_TRY_FLAG], [ @@ -247,7 +260,7 @@ if test "x$HAVE_LIBUDEV" = xyes; then fi AM_CONDITIONAL(HAVE_LIBUDEV, [test "x$HAVE_LIBUDEV" = xyes]) -if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno" -o "x$OMAP" != "xno"; then +if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno" -o "x$OMAP" != "xno" -o "x$SLP" != "xno"; then # Check for atomic intrinsics AC_CACHE_CHECK([for native atomic primitives], drm_cv_atomic_primitives, [ @@ -319,6 +332,10 @@ if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno" -o "x$ fi fi +if test "x$SLP" != "xno"; then + AC_DEFINE(HAVE_SLP, 1, [Have slp]) +fi + if test "x$INTEL" != "xno"; then PKG_CHECK_MODULES(PCIACCESS, [pciaccess >= 0.10]) fi @@ -330,6 +347,7 @@ if test "x$have_valgrind" = "xyes"; then AC_DEFINE([HAVE_VALGRIND], 1, [Use valgrind intrinsics to suppress false warnings]) fi +AM_CONDITIONAL(HAVE_SLP, [test "x$SLP" != "xno"]) AM_CONDITIONAL(HAVE_INTEL, [test "x$INTEL" != "xno"]) AM_CONDITIONAL(HAVE_RADEON, [test "x$RADEON" != "xno"]) AM_CONDITIONAL(HAVE_NOUVEAU, [test "x$NOUVEAU" != "xno"]) @@ -348,6 +366,8 @@ AC_CONFIG_FILES([ Makefile libkms/Makefile libkms/libkms.pc + slp/Makefile + slp/libdrm_slp.pc intel/Makefile intel/libdrm_intel.pc radeon/Makefile @@ -380,4 +400,6 @@ echo " Radeon API $RADEON" echo " Nouveau API $NOUVEAU" echo " OMAP API $OMAP" echo " EXYNOS API $EXYNOS" +echo " SLP API $SLP" +echo " SLP bufmgr_dir $bufmgr_dir" echo "" diff --git a/slp/Makefile.am b/slp/Makefile.am new file mode 100644 index 0000000..132662b --- /dev/null +++ b/slp/Makefile.am @@ -0,0 +1,22 @@ +SUBDIRS = . + +AM_CFLAGS = \ + $(WARN_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/slp \ + $(PTHREADSTUBS_CFLAGS) \ + -I$(top_srcdir)/include/drm + +libdrm_slp_la_LTLIBRARIES = libdrm_slp.la +libdrm_slp_ladir = $(libdir) +libdrm_slp_la_LDFLAGS = -version-number 1:0:0 -no-undefined +libdrm_slp_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@ @CLOCK_LIB@ -ldl + +libdrm_slp_la_SOURCES = \ + drm_slp_bufmgr.c \ + drm_slp_bufmgr.h + +libdrm_slpincludedir = ${includedir}/libdrm +libdrm_slpinclude_HEADERS = drm_slp_bufmgr.h + +pkgconfig_DATA = libdrm_slp.pc diff --git a/slp/drm_slp_bufmgr.c b/slp/drm_slp_bufmgr.c new file mode 100644 index 0000000..f723ded --- /dev/null +++ b/slp/drm_slp_bufmgr.c @@ -0,0 +1,847 @@ +/************************************************************************** + +xserver-xorg-video-sec + +Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim , Sangjin Lee + +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. + +**************************************************************************/ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "drm_slp_bufmgr.h" +#include "list.h" + +#define PREFIX_LIB "libdrm_slp_" +#define SUFFIX_LIB ".so" +#define DEFAULT_LIB PREFIX_LIB"default"SUFFIX_LIB + +#define NUM_TRY_LOCK 10 +#define SEM_NAME "pixmap_1" +#define SEM_DEBUG 0 + +#define DRM_RETURN_IF_FAIL(cond) {if (!(cond)) { fprintf (stderr, "[%s] : '%s' failed.\n", __FUNCTION__, #cond); return; }} +#define DRM_RETURN_VAL_IF_FAIL(cond, val) {if (!(cond)) { fprintf (stderr, "[%s] : '%s' failed.\n", __FUNCTION__, #cond); return val; }} + +#define MGR_IS_VALID(mgr) (mgr && \ + mgr->link.next && \ + mgr->link.next->prev == &mgr->link) +#define BO_IS_VALID(bo) (bo && \ + MGR_IS_VALID(bo->bufmgr) && \ + bo->list.next && \ + bo->list.next->prev == &bo->list) + +typedef struct{ + void* data; + + int is_valid; + drm_data_free free_func ; +}drm_slp_user_data; + +static struct list_head *gBufMgrs = NULL; + +static int +_sem_wait_wrapper(sem_t* sem) +{ + int res = 0; + int num_try = NUM_TRY_LOCK; + + do + { + res = sem_wait(sem); + num_try--; + } while((res == -1) && (errno == EINTR) && (num_try >= 0)); + + if(res == -1) + { + fprintf(stderr, + "[libdrm] error %s:%d(sem:%p, num_try:%d) PID:%04d\n", + __FUNCTION__, + __LINE__, + sem, + num_try, + getpid()); + return 0; + } +#if SEM_DEBUG + else + { + fprintf(stderr, + "[libdrm] LOCK >> %s:%d(sem:%p, num_try:%d) PID:%04d\n", + __FUNCTION__, + __LINE__, + sem, + num_try, + getpid()); + } +#endif + + return 1; +} + +static int +_sem_post_wrapper(sem_t* sem) +{ + int res = 0; + int num_try = NUM_TRY_LOCK; + + do + { + res = sem_post(sem); + num_try--; + + } while((res == -1) && (errno == EINTR) && (num_try >= 0)); + + if(res == -1) + { + fprintf(stderr, + "[libdrm] error %s:%d(sem:%p, num_try:%d) PID:%04d\n", + __FUNCTION__, + __LINE__, + sem, + num_try, + getpid()); + return 0; + } +#if SEM_DEBUG + else + { + fprintf(stderr, + "[libdrm] UNLOCK << %s:%d(sem:%p, num_try:%d) PID:%04d\n", + __FUNCTION__, + __LINE__, + sem, + num_try, + getpid()); + } +#endif + + return 1; +} + +static int +_sem_open(drm_slp_bufmgr bufmgr) +{ + bufmgr->semObj.handle = sem_open(SEM_NAME, O_CREAT, 0777, 1); + if(bufmgr->semObj.handle == SEM_FAILED) + { + fprintf(stderr, + "[libdrm] error %s:%d(name:%s) PID:%04d\n", + __FUNCTION__, + __LINE__, + SEM_NAME, + getpid()); + bufmgr->semObj.handle = NULL; + return 0; + } +#if SEM_DEBUG + else + { + fprintf(stderr, + "[libdrm] OPEN %s:%d(sem:%p) PID:%04d\n", + __FUNCTION__, + __LINE__, + bufmgr->semObj.handle, + getpid()); + } +#endif + + bufmgr->semObj.status = STATUS_UNLOCK; + + return 1; +} + +static int +_sem_close(drm_slp_bufmgr bufmgr) +{ + _sem_wait_wrapper(bufmgr->semObj.handle); + sem_unlink(SEM_NAME); + return 1; +} + +static int +_sem_lock(drm_slp_bufmgr bufmgr) +{ + if(bufmgr->semObj.status != STATUS_UNLOCK) return 0; + + if(!_sem_wait_wrapper(bufmgr->semObj.handle)) return 0; + bufmgr->semObj.status = STATUS_LOCK; + return 1; +} + +static int +_sem_unlock(drm_slp_bufmgr bufmgr) +{ + if(bufmgr->semObj.status != STATUS_LOCK) return 0; + + _sem_post_wrapper(bufmgr->semObj.handle); + bufmgr->semObj.status = STATUS_UNLOCK; + return 1; +} + +static drm_slp_bufmgr +_load_bufmgr(int fd, const char *file, void *arg) +{ + char path[PATH_MAX] = {0,}; + drm_slp_bufmgr bufmgr = NULL; + int (*bufmgr_init)(drm_slp_bufmgr bufmgr, int fd, void *arg); + void *module; + + snprintf(path, sizeof(path), BUFMGR_DIR "/%s", file); + + module = dlopen(path, RTLD_LAZY); + if (!module) { + fprintf(stderr, + "[libdrm] failed to load module: %s(%s)\n", + dlerror(), file); + return NULL; + } + + bufmgr_init = dlsym(module, "init_slp_bufmgr"); + if (!bufmgr_init) { + fprintf(stderr, + "[libdrm] failed to lookup init function: %s(%s)\n", + dlerror(), file); + return NULL; + } + + bufmgr = calloc(sizeof(struct _drm_slp_bufmgr), 1); + if(!bufmgr) + { + return NULL; + } + + if(!bufmgr_init(bufmgr, fd, arg)) + { + fprintf(stderr,"[libdrm] Fail to init module(%s)\n", file); + free(bufmgr); + bufmgr = NULL; + return NULL; + } + + fprintf(stderr,"[libdrm] Success to load module(%s)\n", file); + + return bufmgr; +} + +drm_slp_bufmgr +drm_slp_bufmgr_init(int fd, void *arg) +{ + drm_slp_bufmgr bufmgr = NULL; + const char *p = NULL; + + if (fd < 0) + return NULL; + + if(gBufMgrs == NULL) + { + gBufMgrs = malloc(sizeof(struct list_head)); + LIST_INITHEAD(gBufMgrs); + } + else + { + LIST_FOR_EACH_ENTRY(bufmgr, gBufMgrs, link) + { + if(bufmgr->drm_fd == fd) + { + bufmgr->ref_count++; + fprintf(stderr, "[libdrm] bufmgr ref: fd=%d, ref_count:%d\n", fd, bufmgr->ref_count); + return bufmgr; + } + } + bufmgr = NULL; + } + fprintf(stderr, "[libdrm] bufmgr init: fd=%d\n", fd); + + p = getenv ("SLP_BUFMGR_MODULE"); + if (p) + { + char file[PATH_MAX] = {0,}; + snprintf(file, sizeof(file), PREFIX_LIB"%s"SUFFIX_LIB, p); + bufmgr = _load_bufmgr (fd, file, arg); + } + + if (!bufmgr) + bufmgr = _load_bufmgr (fd, DEFAULT_LIB, arg); + + if (!bufmgr) + { + struct dirent **namelist; + int found = 0; + int n; + + n = scandir(BUFMGR_DIR, &namelist, 0, alphasort); + if (n < 0) + fprintf(stderr,"[libdrm] no files : %s\n", BUFMGR_DIR); + else + { + while(n--) + { + if (!found && strstr (namelist[n]->d_name, PREFIX_LIB)) + { + char *p = strstr (namelist[n]->d_name, SUFFIX_LIB); + if (!strcmp (p, SUFFIX_LIB)) + { + bufmgr = _load_bufmgr (fd, namelist[n]->d_name, arg); + if (bufmgr) + found = 1; + } + } + free(namelist[n]); + } + free(namelist); + } + } + + if (!bufmgr) + { + fprintf(stderr,"[libdrm] backend is NULL.\n"); + return NULL; + } + + if (pthread_mutex_init(&bufmgr->lock, NULL) != 0) + { + bufmgr->bufmgr_destroy(bufmgr); + free(bufmgr); + return NULL; + } + + bufmgr->ref_count = 1; + bufmgr->drm_fd = fd; + + LIST_INITHEAD(&bufmgr->bos); + LIST_ADD(&bufmgr->link, gBufMgrs); + + return bufmgr; +} + +void +drm_slp_bufmgr_destroy(drm_slp_bufmgr bufmgr) +{ + DRM_RETURN_IF_FAIL(MGR_IS_VALID(bufmgr)); + + fprintf(stderr, "[DRM] bufmgr destroy: bufmgr:%p, drm_fd:%d\n", + bufmgr, bufmgr->drm_fd); + + /*Check and Free bos*/ + if(!LIST_IS_EMPTY(&bufmgr->bos)) + { + drm_slp_bo bo, tmp; + + LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bos, list) + { + fprintf(stderr, "[libdrm] Un-freed bo(%p, ref:%d) \n", bo, bo->ref_cnt); + bo->ref_cnt = 1; + drm_slp_bo_unref(bo); + } + } + + LIST_DEL(&bufmgr->link); + bufmgr->bufmgr_destroy(bufmgr); + + if(bufmgr->semObj.isOpened) + { + _sem_close(bufmgr); + } + + pthread_mutex_destroy(&bufmgr->lock); + free(bufmgr); +} + +int +drm_slp_bufmgr_lock(drm_slp_bufmgr bufmgr) +{ + DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr), 0); + + pthread_mutex_lock(&bufmgr->lock); + + if(bufmgr->bufmgr_lock) + { + int ret; + ret = bufmgr->bufmgr_lock(bufmgr); + pthread_mutex_unlock(&bufmgr->lock); + return ret; + } + + if(!bufmgr->semObj.isOpened) + { + if(_sem_open(bufmgr) != 1) + { + pthread_mutex_unlock(&bufmgr->lock); + return 0; + } + bufmgr->semObj.isOpened = 1; + } + + if(_sem_lock(bufmgr) != 1) + { + pthread_mutex_unlock(&bufmgr->lock); + return 0; + } + + pthread_mutex_unlock(&bufmgr->lock); + + return 1; +} + +int +drm_slp_bufmgr_unlock(drm_slp_bufmgr bufmgr) +{ + DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr), 0); + + pthread_mutex_lock(&bufmgr->lock); + + if(bufmgr->bufmgr_unlock) + { + int ret; + ret = bufmgr->bufmgr_unlock(bufmgr); + pthread_mutex_unlock(&bufmgr->lock); + return ret; + } + + if(_sem_unlock(bufmgr) != 1) + { + pthread_mutex_unlock(&bufmgr->lock); + return 0; + } + + pthread_mutex_unlock(&bufmgr->lock); + + return 1; +} + +int +drm_slp_bufmgr_cache_flush(drm_slp_bufmgr bufmgr, drm_slp_bo bo, int flags) +{ + int ret; + + DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr) || BO_IS_VALID(bo), 0); + + if (!bo) + flags |= DRM_SLP_CACHE_ALL; + + if (bo) + { + DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0); + + if(!bo->bufmgr) + return 0; + + pthread_mutex_lock(&bo->bufmgr->lock); + ret = bo->bufmgr->bufmgr_cache_flush(bufmgr, bo, flags); + pthread_mutex_unlock(&bo->bufmgr->lock); + } + else + { + pthread_mutex_lock(&bufmgr->lock); + ret = bufmgr->bufmgr_cache_flush(bufmgr, NULL, flags); + pthread_mutex_unlock(&bufmgr->lock); + } + + return ret; +} + +int +drm_slp_bo_size(drm_slp_bo bo) +{ + int size; + drm_slp_bufmgr bufmgr; + + DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0); + + bufmgr = bo->bufmgr; + + pthread_mutex_lock(&bufmgr->lock); + size = bo->bufmgr->bo_size(bo); + pthread_mutex_unlock(&bufmgr->lock); + + return size; +} + +drm_slp_bo +drm_slp_bo_ref(drm_slp_bo bo) +{ + drm_slp_bufmgr bufmgr; + + DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), NULL); + + bufmgr = bo->bufmgr; + + pthread_mutex_lock(&bufmgr->lock); + + bo->ref_cnt++; + + pthread_mutex_unlock(&bufmgr->lock); + + return bo; +} + +void +drm_slp_bo_unref(drm_slp_bo bo) +{ + drm_slp_bufmgr bufmgr; + + DRM_RETURN_IF_FAIL(BO_IS_VALID(bo)); + + bufmgr = bo->bufmgr; + + if(0 >= bo->ref_cnt) + return; + + pthread_mutex_lock(&bufmgr->lock); + + bo->ref_cnt--; + if(bo->ref_cnt == 0) + { + if(bo->user_data) + { + void* rd; + drm_slp_user_data* old_data; + unsigned long key; + + while(1==drmSLFirst(bo->user_data, &key, &rd)) + { + old_data = (drm_slp_user_data*)rd; + + if(old_data->is_valid && old_data->free_func) + { + if(old_data->data) + old_data->free_func(old_data->data); + old_data->data = NULL; + free(old_data); + } + drmSLDelete(bo->user_data, key); + } + + drmSLDestroy(bo->user_data); + bo->user_data = (void*)0; + } + + LIST_DEL(&bo->list); + bufmgr->bo_free(bo); + + free(bo); + } + + pthread_mutex_unlock(&bufmgr->lock); +} + +drm_slp_bo +drm_slp_bo_alloc(drm_slp_bufmgr bufmgr, const char * name, int size, int flags) +{ + drm_slp_bo bo=NULL; + + DRM_RETURN_VAL_IF_FAIL( MGR_IS_VALID(bufmgr) && (size > 0), NULL); + + bo = calloc(sizeof(struct _drm_slp_bo), 1); + if(!bo) + return NULL; + + bo->bufmgr = bufmgr; + + pthread_mutex_lock(&bufmgr->lock); + if(!bufmgr->bo_alloc(bo, name, size, flags)) + { + free(bo); + pthread_mutex_unlock(&bufmgr->lock); + return NULL; + } + bo->ref_cnt = 1; + LIST_ADD(&bo->list, &bufmgr->bos); + pthread_mutex_unlock(&bufmgr->lock); + + return bo; +} + +drm_slp_bo +drm_slp_bo_attach(drm_slp_bufmgr bufmgr, + const char* name, + int type, + int size, + unsigned int handle) +{ + drm_slp_bo bo; + + DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr), NULL); + + bo = calloc(sizeof(struct _drm_slp_bo), 1); + if(!bo) + return NULL; + + bo->bufmgr = bufmgr; + + pthread_mutex_lock(&bufmgr->lock); + if(!bufmgr->bo_attach(bo, name, type, size, handle)) + { + free(bo); + pthread_mutex_unlock(&bufmgr->lock); + return NULL; + } + bo->ref_cnt = 1; + LIST_ADD(&bo->list, &bufmgr->bos); + pthread_mutex_unlock(&bufmgr->lock); + + return bo; +} + +drm_slp_bo +drm_slp_bo_import(drm_slp_bufmgr bufmgr, unsigned int key) +{ + drm_slp_bo bo; + + DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr), NULL); + + bo = calloc(sizeof(struct _drm_slp_bo), 1); + if(!bo) + return NULL; + + bo->bufmgr = bufmgr; + + pthread_mutex_lock(&bufmgr->lock); + if(!bufmgr->bo_import(bo, key)) + { + free(bo); + pthread_mutex_unlock(&bufmgr->lock); + return NULL; + } + bo->ref_cnt = 1; + LIST_ADD(&bo->list, &bufmgr->bos); + pthread_mutex_unlock(&bufmgr->lock); + + return bo; +} + +unsigned int +drm_slp_bo_export(drm_slp_bo bo) +{ + int ret; + + DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0); + + pthread_mutex_lock(&bo->bufmgr->lock); + ret = bo->bufmgr->bo_export(bo); + pthread_mutex_unlock(&bo->bufmgr->lock); + + return ret; +} + +unsigned int +drm_slp_bo_get_handle(drm_slp_bo bo, int device) +{ + unsigned int ret; + + DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0); + + pthread_mutex_lock(&bo->bufmgr->lock); + ret = bo->bufmgr->bo_get_handle(bo, device); + pthread_mutex_unlock(&bo->bufmgr->lock); + + return ret; +} + +unsigned int +drm_slp_bo_map(drm_slp_bo bo, int device, int opt) +{ + unsigned int ret; + + DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0); + + pthread_mutex_lock(&bo->bufmgr->lock); + if(bo->bufmgr->bo_lock) + { + bo->bufmgr->bo_lock(bo, 0, (void*)0); + } + + ret = bo->bufmgr->bo_map(bo, device, opt); + pthread_mutex_unlock(&bo->bufmgr->lock); + + return ret; +} + +int +drm_slp_bo_unmap(drm_slp_bo bo, int device) +{ + int ret; + + DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0); + + pthread_mutex_lock(&bo->bufmgr->lock); + ret = bo->bufmgr->bo_unmap(bo, device); + + if(bo->bufmgr->bo_unlock) + { + bo->bufmgr->bo_unlock(bo); + } + pthread_mutex_unlock(&bo->bufmgr->lock); + + return 0; +} + +int +drm_slp_bo_swap(drm_slp_bo bo1, drm_slp_bo bo2) +{ + void* temp; + + DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo1), 0); + DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo2), 0); + + if(bo1->bufmgr->bo_size(bo1) != bo2->bufmgr->bo_size(bo2)) + return 0; + + pthread_mutex_lock(&bo1->bufmgr->lock); + temp = bo1->priv; + bo1->priv = bo2->priv; + bo2->priv = temp; + pthread_mutex_unlock(&bo1->bufmgr->lock); + + return 1; +} + +int +drm_slp_bo_add_user_data(drm_slp_bo bo, unsigned long key, drm_data_free data_free_func) +{ + int ret; + drm_slp_user_data* data; + + DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0); + + if(!bo->user_data) + bo->user_data = drmSLCreate(); + + data = calloc(1, sizeof(drm_slp_user_data)); + if(!data) + return 0; + + data->free_func = data_free_func; + data->data = (void*)0; + data->is_valid = 0; + + ret = drmSLInsert(bo->user_data, key, data); + if(ret == 1) /* Already in list */ + { + free(data); + return 0; + } + + return 1; +} + +int +drm_slp_bo_set_user_data(drm_slp_bo bo, unsigned long key, void* data) +{ + void *rd; + drm_slp_user_data* old_data; + + DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0); + + if(!bo->user_data) + return 0; + + if(drmSLLookup(bo->user_data, key, &rd)) + return 0; + + old_data = (drm_slp_user_data*)rd; + if (!old_data) + return 0; + + if(old_data->is_valid) + { + if(old_data->free_func) + { + if(old_data->data) + old_data->free_func(old_data->data); + old_data->data = NULL; + } + } + else + old_data->is_valid = 1; + + old_data->data = data; + + return 1; +} + +int +drm_slp_bo_get_user_data(drm_slp_bo bo, unsigned long key, void** data) +{ + void *rd; + drm_slp_user_data* old_data; + + DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo) && data && bo->user_data, 0); + + if(drmSLLookup(bo->user_data, key, &rd)) + { + *data = NULL; + return 0; + } + + old_data = (drm_slp_user_data*)rd; + if (!old_data) + { + *data = NULL; + return 0; + } + + *data = old_data->data; + + return 1; +} + +int +drm_slp_bo_delete_user_data(drm_slp_bo bo, unsigned long key) +{ + void *rd; + drm_slp_user_data* old_data=(void*)0; + + DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo) && bo->user_data, 0); + + if(drmSLLookup(bo->user_data, key, &rd)) + return 0; + + old_data = (drm_slp_user_data*)rd; + if (!old_data) + return 0; + + if(old_data->is_valid && old_data->free_func) + { + if(old_data->data) + old_data->free_func(old_data->data); + free(old_data); + } + drmSLDelete(bo->user_data, key); + + return 1; +} diff --git a/slp/drm_slp_bufmgr.h b/slp/drm_slp_bufmgr.h new file mode 100644 index 0000000..a4adef5 --- /dev/null +++ b/slp/drm_slp_bufmgr.h @@ -0,0 +1,201 @@ +/************************************************************************** + +xserver-xorg-video-sec + +Copyright 2011 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: SooChan Lim , Sangjin Lee + +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. + +**************************************************************************/ + +#ifndef _DRM_SLP_BUFMGR_H_ +#define _DRM_SLP_BUFMGR_H_ + +#include +#include +#include + +typedef struct _drm_slp_bo * drm_slp_bo; +typedef struct _drm_slp_bufmgr * drm_slp_bufmgr; + +struct list_head +{ + struct list_head *prev; + struct list_head *next; +}; + +struct _drm_slp_bo +{ + struct list_head list; + drm_slp_bufmgr bufmgr; + int ref_cnt; /*atomic count*/ + void *user_data; + + /* private data */ + void *priv; +}; + +typedef enum +{ + STATUS_UNLOCK, + STATUS_READY_TO_LOCK, + STATUS_LOCK, +} lock_status; + +struct _drm_slp_bufmgr +{ + struct list_head bos; /*list head of bo*/ + + pthread_mutex_t lock; + struct { + int isOpened; + lock_status status; + sem_t* handle; + } semObj; + + void (*bufmgr_destroy)(drm_slp_bufmgr bufmgr); + int (*bufmgr_cache_flush)(drm_slp_bufmgr bufmgr, drm_slp_bo bo, int flags); + + int (*bo_size)(drm_slp_bo bo); + + void (*bo_free)(drm_slp_bo bo); + int (*bo_alloc)(drm_slp_bo bo, + const char* name, + int size, + int flags); + int (*bo_attach)(drm_slp_bo bo, + const char* name, + int type, + int size, + unsigned int handle); + int (*bo_import)(drm_slp_bo bo, unsigned int key); + unsigned int (*bo_export)(drm_slp_bo bo); + + unsigned int (*bo_get_handle)(drm_slp_bo bo, int device); + unsigned int (*bo_map)(drm_slp_bo bo, int device, int opt); + int (*bo_unmap)(drm_slp_bo bo, int device); + + + /* Padding for future extension */ + int (*bufmgr_lock) (drm_slp_bufmgr bufmgr); + int (*bufmgr_unlock) (drm_slp_bufmgr bufmgr); + int (*bo_lock) (drm_slp_bo bo, unsigned int checkOnly, unsigned int* isLocked); + int (*bo_unlock) (drm_slp_bo bo); + void (*reserved5) (void); + void (*reserved6) (void); + + /* private data */ + void *priv; + + struct list_head link; /*link of bufmgr*/ + + int drm_fd; + int ref_count; +}; + +/* DRM_SLP_MEM_TYPE */ +#define DRM_SLP_MEM_GEM 0 +#define DRM_SLP_MEM_USERPTR 1 +#define DRM_SLP_MEM_DMABUF 2 +#define DRM_SLP_MEM_GPU 3 + +/* DRM_SLP_DEVICE_TYPE */ +#define DRM_SLP_DEVICE_DEFAULT 0 //Default handle +#define DRM_SLP_DEVICE_CPU 1 +#define DRM_SLP_DEVICE_2D 2 +#define DRM_SLP_DEVICE_3D 3 +#define DRM_SLP_DEVICE_MM 4 + +/* DRM_SLP_OPTION */ +#define DRM_SLP_OPTION_READ (1 << 0) +#define DRM_SLP_OPTION_WRITE (1 << 1) + +/* DRM_SLP_CACHE */ +#define DRM_SLP_CACHE_INV 0x01 +#define DRM_SLP_CACHE_CLN 0x02 +#define DRM_SLP_CACHE_ALL 0x10 +#define DRM_SLP_CACHE_FLUSH (DRM_SLP_CACHE_INV|DRM_SLP_CACHE_CLN) +#define DRM_SLP_CACHE_FLUSH_ALL (DRM_SLP_CACHE_FLUSH|DRM_SLP_CACHE_ALL) + +enum DRM_SLP_BO_FLAGS{ + DRM_SLP_BO_DEFAULT = 0, + DRM_SLP_BO_SCANOUT = (1<<0), + DRM_SLP_BO_NONCACHABLE = (1<<1), + DRM_SLP_BO_WC = (1<<2), +}; + +/* Functions for buffer mnager */ +drm_slp_bufmgr +drm_slp_bufmgr_init(int fd, void * arg); +void +drm_slp_bufmgr_destroy(drm_slp_bufmgr bufmgr); +int +drm_slp_bufmgr_lock(drm_slp_bufmgr bufmgr); +int +drm_slp_bufmgr_unlock(drm_slp_bufmgr bufmgr); +int +drm_slp_bufmgr_cache_flush(drm_slp_bufmgr bufmgr, drm_slp_bo bo, int flags); + + +/*Functions for bo*/ +int +drm_slp_bo_size (drm_slp_bo bo); +drm_slp_bo +drm_slp_bo_ref(drm_slp_bo bo); +void +drm_slp_bo_unref(drm_slp_bo bo); +drm_slp_bo +drm_slp_bo_alloc(drm_slp_bufmgr bufmgr, + const char* name, + int size, + int flags); +drm_slp_bo +drm_slp_bo_attach(drm_slp_bufmgr bufmgr, + const char* name, + int type, + int size, + unsigned int handle); +drm_slp_bo +drm_slp_bo_import(drm_slp_bufmgr bufmgr, unsigned int key); +unsigned int +drm_slp_bo_export(drm_slp_bo bo); +unsigned int +drm_slp_bo_get_handle(drm_slp_bo, int device); +unsigned int +drm_slp_bo_map(drm_slp_bo bo, int device, int opt); +int +drm_slp_bo_unmap(drm_slp_bo bo, int device); +int +drm_slp_bo_swap(drm_slp_bo bo1, drm_slp_bo bo2); + +/*Functions for userdata of bo*/ +typedef void (*drm_data_free)(void *); +int +drm_slp_bo_add_user_data(drm_slp_bo bo, unsigned long key, drm_data_free data_free_func); +int +drm_slp_bo_delete_user_data(drm_slp_bo bo, unsigned long key); +int +drm_slp_bo_set_user_data(drm_slp_bo bo, unsigned long key, void* data); +int +drm_slp_bo_get_user_data(drm_slp_bo bo, unsigned long key, void** data); +#endif /* _DRM_SLP_BUFMGR_H_ */ diff --git a/slp/libdrm_slp.pc.in b/slp/libdrm_slp.pc.in new file mode 100644 index 0000000..220d38b --- /dev/null +++ b/slp/libdrm_slp.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libdrm +Description: Userspace interface to kernel DRM services +Version: @PACKAGE_VERSION@ +Requires: libdrm +Libs: -L${libdir} -ldrm_slp +Cflags: -I${includedir} -I${includedir}/libdrm diff --git a/slp/list.h b/slp/list.h new file mode 100644 index 0000000..e967b93 --- /dev/null +++ b/slp/list.h @@ -0,0 +1,131 @@ +/* + * + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA. + * All Rights Reserved. + * + * 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 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 + * THE COPYRIGHT HOLDERS, AUTHORS 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. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + */ + +/** + * \file + * List macros heavily inspired by the Linux kernel + * list handling. No list looping yet. + * + * Is not threadsafe, so common operations need to + * be protected using an external mutex. + */ +#ifndef _U_DOUBLE_LIST_H_ +#define _U_DOUBLE_LIST_H_ + +#include + +static void list_inithead(struct list_head *item) +{ + item->prev = item; + item->next = item; +} + +static inline void list_add(struct list_head *item, struct list_head *list) +{ + item->prev = list; + item->next = list->next; + list->next->prev = item; + list->next = item; +} + +static inline void list_addtail(struct list_head *item, struct list_head *list) +{ + item->next = list; + item->prev = list->prev; + list->prev->next = item; + list->prev = item; +} + +static inline void list_replace(struct list_head *from, struct list_head *to) +{ + to->prev = from->prev; + to->next = from->next; + from->next->prev = to; + from->prev->next = to; +} + +static inline void list_del(struct list_head *item) +{ + item->prev->next = item->next; + item->next->prev = item->prev; +} + +static inline void list_delinit(struct list_head *item) +{ + item->prev->next = item->next; + item->next->prev = item->prev; + item->next = item; + item->prev = item; +} + +#define LIST_INITHEAD(__item) list_inithead(__item) +#define LIST_ADD(__item, __list) list_add(__item, __list) +#define LIST_ADDTAIL(__item, __list) list_addtail(__item, __list) +#define LIST_REPLACE(__from, __to) list_replace(__from, __to) +#define LIST_DEL(__item) list_del(__item) +#define LIST_DELINIT(__item) list_delinit(__item) + +#define LIST_ENTRY(__type, __item, __field) \ + ((__type *)(((char *)(__item)) - offsetof(__type, __field))) + +#define LIST_IS_EMPTY(__list) \ + ((__list)->next == (__list)) + +#ifndef container_of +#define container_of(ptr, sample, member) \ + (void *)((char *)(ptr) \ + - ((char *)&(sample)->member - (char *)(sample))) +#endif + +#define LIST_FOR_EACH_ENTRY(pos, head, member) \ + for (pos = container_of((head)->next, pos, member); \ + &pos->member != (head); \ + pos = container_of(pos->member.next, pos, member)) + +#define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member) \ + for (pos = container_of((head)->next, pos, member), \ + storage = container_of(pos->member.next, pos, member); \ + &pos->member != (head); \ + pos = storage, storage = container_of(storage->member.next, storage, member)) + +#define LIST_FOR_EACH_ENTRY_SAFE_REV(pos, storage, head, member) \ + for (pos = container_of((head)->prev, pos, member), \ + storage = container_of(pos->member.prev, pos, member); \ + &pos->member != (head); \ + pos = storage, storage = container_of(storage->member.prev, storage, member)) + +#define LIST_FOR_EACH_ENTRY_FROM(pos, start, head, member) \ + for (pos = container_of((start), pos, member); \ + &pos->member != (head); \ + pos = container_of(pos->member.next, pos, member)) + +#define LIST_FOR_EACH_ENTRY_FROM_REV(pos, start, head, member) \ + for (pos = container_of((start), pos, member); \ + &pos->member != (head); \ + pos = container_of(pos->member.prev, pos, member)) + +#endif /*_U_DOUBLE_LIST_H_*/