Adding slp buffer support 57/2357/1
authorRusty Lynch <rusty.lynch@intel.com>
Tue, 2 Oct 2012 00:36:32 +0000 (17:36 -0700)
committerRusty Lynch <rusty.lynch@intel.com>
Tue, 13 Nov 2012 22:11:08 +0000 (14:11 -0800)
Makefile.am
configure.ac
slp/Makefile.am [new file with mode: 0644]
slp/drm_slp_bufmgr.c [new file with mode: 0644]
slp/drm_slp_bufmgr.h [new file with mode: 0644]
slp/libdrm_slp.pc.in [new file with mode: 0644]
slp/list.h [new file with mode: 0644]

index 8ecd9d9..bb7b769 100644 (file)
@@ -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)
index 0c19929..1a682a0 100644 (file)
@@ -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 (file)
index 0000000..132662b
--- /dev/null
@@ -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 (file)
index 0000000..f723ded
--- /dev/null
@@ -0,0 +1,847 @@
+/**************************************************************************
+
+xserver-xorg-video-sec
+
+Copyright 2011 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.
+
+**************************************************************************/
+
+#include "config.h"
+
+#include <unistd.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <dirent.h>
+#include <string.h>
+#include <errno.h>
+
+#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 (file)
index 0000000..a4adef5
--- /dev/null
@@ -0,0 +1,201 @@
+/**************************************************************************
+
+xserver-xorg-video-sec
+
+Copyright 2011 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.
+
+**************************************************************************/
+
+#ifndef _DRM_SLP_BUFMGR_H_
+#define _DRM_SLP_BUFMGR_H_
+
+#include <semaphore.h>
+#include <pthread.h>
+#include <xf86drm.h>
+
+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 (file)
index 0000000..220d38b
--- /dev/null
@@ -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 (file)
index 0000000..e967b93
--- /dev/null
@@ -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 <stddef.h>
+
+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_*/