summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-11-13 07:04:27 -0800
committerAnas Nashif <anas.nashif@intel.com>2013-02-11 08:02:22 -0800
commit39108458cb8912b6122b9e0ff77053c6f7f2a79b (patch)
tree08e8dc77405aeb0621cdf3b54939fab7e47f27cd
parentaef270ee6488bea9666e124c1be014dcd4ff539a (diff)
downloadlibdrm-39108458cb8912b6122b9e0ff77053c6f7f2a79b.tar.gz
libdrm-39108458cb8912b6122b9e0ff77053c6f7f2a79b.tar.bz2
libdrm-39108458cb8912b6122b9e0ff77053c6f7f2a79b.zip
Support SLP
-rw-r--r--Makefile.am6
-rw-r--r--configure.ac20
-rw-r--r--configure.ac.orig349
-rw-r--r--configure.ac.rej11
-rw-r--r--libkms/Makefile.am5
-rw-r--r--libkms/slp.c222
-rw-r--r--slp/Makefile.am22
-rw-r--r--slp/drm_slp_bufmgr.c847
-rw-r--r--slp/drm_slp_bufmgr.h201
-rw-r--r--slp/libdrm_slp.pc.in11
-rw-r--r--slp/list.h131
11 files changed, 1824 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 94572d01..0338595c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -43,11 +43,15 @@ if HAVE_OMAP
OMAP_SUBDIR = omap
endif
+if HAVE_SLP
+SLP_SUBDIR = slp
+endif
+
if HAVE_EXYNOS
EXYNOS_SUBDIR = exynos
endif
-SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) tests include man
+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 e2e34667..e1846ec6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -93,6 +93,20 @@ 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], [
@@ -318,6 +332,9 @@ if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno" -o "x$
fi
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])
@@ -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"])
@@ -349,6 +367,8 @@ AC_CONFIG_FILES([
libkms/Makefile
libkms/libkms.pc
intel/Makefile
+ slp/Makefile
+ slp/libdrm_slp.pc
intel/libdrm_intel.pc
radeon/Makefile
radeon/libdrm_radeon.pc
diff --git a/configure.ac.orig b/configure.ac.orig
new file mode 100644
index 00000000..95068272
--- /dev/null
+++ b/configure.ac.orig
@@ -0,0 +1,349 @@
+# Copyright 2005 Adam Jackson.
+#
+# 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
+# on 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
+# ADAM JACKSON 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.
+
+AC_PREREQ([2.63])
+AC_INIT([libdrm],
+ [2.4.39],
+ [https://bugs.freedesktop.org/enter_bug.cgi?product=DRI],
+ [libdrm])
+
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_SRCDIR([Makefile.am])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_AUX_DIR([build-aux])
+
+AM_INIT_AUTOMAKE([1.10 foreign dist-bzip2])
+AM_MAINTAINER_MODE([enable])
+
+# Enable quiet compiles on automake 1.11.
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+# Check for programs
+AC_PROG_CC
+
+AC_USE_SYSTEM_EXTENSIONS
+AC_SYS_LARGEFILE
+AC_FUNC_ALLOCA
+
+# Initialize libtool
+LT_PREREQ([2.2])
+LT_INIT([disable-static])
+
+
+PKG_CHECK_MODULES(PTHREADSTUBS, pthread-stubs)
+AC_SUBST(PTHREADSTUBS_CFLAGS)
+AC_SUBST(PTHREADSTUBS_LIBS)
+
+pkgconfigdir=${libdir}/pkgconfig
+AC_SUBST(pkgconfigdir)
+AC_ARG_ENABLE([udev],
+ [AS_HELP_STRING([--enable-udev],
+ [Enable support for using udev instead of mknod (default: disabled)])],
+ [UDEV=$enableval], [UDEV=no])
+
+AC_ARG_ENABLE(libkms,
+ AS_HELP_STRING([--disable-libkms],
+ [Disable KMS mm abstraction library (default: auto)]),
+ [LIBKMS=$enableval], [LIBKMS=auto])
+
+AC_ARG_ENABLE(intel,
+ AS_HELP_STRING([--disable-intel],
+ [Enable support for intel's KMS API (default: auto)]),
+ [INTEL=$enableval], [INTEL=auto])
+
+AC_ARG_ENABLE(radeon,
+ AS_HELP_STRING([--disable-radeon],
+ [Enable support for radeon's KMS API (default: auto)]),
+ [RADEON=$enableval], [RADEON=auto])
+
+AC_ARG_ENABLE(nouveau,
+ AS_HELP_STRING([--disable-nouveau],
+ [Enable support for nouveau's KMS API (default: auto)]),
+ [NOUVEAU=$enableval], [NOUVEAU=auto])
+
+AC_ARG_ENABLE(vmwgfx-experimental-api,
+ AS_HELP_STRING([--enable-vmwgfx-experimental-api],
+ [Install vmwgfx's experimental kernel API header (default: disabled)]),
+ [VMWGFX=$enableval], [VMWGFX=no])
+
+AC_ARG_ENABLE(omap-experimental-api,
+ AS_HELP_STRING([--enable-omap-experimental-api],
+ [Enable support for OMAP's experimental API (default: disabled)]),
+ [OMAP=$enableval], [OMAP=no])
+
+AC_ARG_ENABLE(exynos-experimental-api,
+ AS_HELP_STRING([--enable-exynos-experimental-api],
+ [Enable support for EXYNOS's experimental API (default: disabled)]),
+ [EXYNOS=$enableval], [EXYNOS=no])
+
+dnl ===========================================================================
+dnl check compiler flags
+AC_DEFUN([LIBDRM_CC_TRY_FLAG], [
+ AC_MSG_CHECKING([whether $CC supports $1])
+
+ libdrm_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $1"
+
+ AC_COMPILE_IFELSE([ ], [libdrm_cc_flag=yes], [libdrm_cc_flag=no])
+ CFLAGS="$libdrm_save_CFLAGS"
+
+ if test "x$libdrm_cc_flag" = "xyes"; then
+ ifelse([$2], , :, [$2])
+ else
+ ifelse([$3], , :, [$3])
+ fi
+ AC_MSG_RESULT([$libdrm_cc_flag])
+])
+
+dnl We use clock_gettime to check for timeouts in drmWaitVBlank
+
+AC_CHECK_FUNCS([clock_gettime], [CLOCK_LIB=],
+ [AC_CHECK_LIB([rt], [clock_gettime], [CLOCK_LIB=-lrt],
+ [AC_MSG_ERROR([Couldn't find clock_gettime])])])
+AC_SUBST([CLOCK_LIB])
+
+AC_CHECK_FUNCS([open_memstream], [HAVE_OPEN_MEMSTREAM=yes])
+
+dnl Use lots of warning flags with with gcc and compatible compilers
+
+dnl Note: if you change the following variable, the cache is automatically
+dnl skipped and all flags rechecked. So there's no need to do anything
+dnl else. If for any reason you need to force a recheck, just change
+dnl MAYBE_WARN in an ignorable way (like adding whitespace)
+
+MAYBE_WARN="-Wall -Wextra \
+-Wsign-compare -Werror-implicit-function-declaration \
+-Wpointer-arith -Wwrite-strings -Wstrict-prototypes \
+-Wmissing-prototypes -Wmissing-declarations -Wnested-externs \
+-Wpacked -Wswitch-enum -Wmissing-format-attribute \
+-Wstrict-aliasing=2 -Winit-self \
+-Wdeclaration-after-statement -Wold-style-definition \
+-Wno-missing-field-initializers -Wno-unused-parameter \
+-Wno-attributes -Wno-long-long -Winline"
+
+# invalidate cached value if MAYBE_WARN has changed
+if test "x$libdrm_cv_warn_maybe" != "x$MAYBE_WARN"; then
+ unset libdrm_cv_warn_cflags
+fi
+AC_CACHE_CHECK([for supported warning flags], libdrm_cv_warn_cflags, [
+ echo
+ WARN_CFLAGS=""
+
+ # Some warning options are not supported by all versions of
+ # gcc, so test all desired options against the current
+ # compiler.
+ #
+ # Note that there are some order dependencies
+ # here. Specifically, an option that disables a warning will
+ # have no net effect if a later option then enables that
+ # warnings, (perhaps implicitly). So we put some grouped
+ # options (-Wall and -Wextra) up front and the -Wno options
+ # last.
+
+ for W in $MAYBE_WARN; do
+ LIBDRM_CC_TRY_FLAG([$W], [WARN_CFLAGS="$WARN_CFLAGS $W"])
+ done
+
+ libdrm_cv_warn_cflags=$WARN_CFLAGS
+ libdrm_cv_warn_maybe=$MAYBE_WARN
+
+ AC_MSG_CHECKING([which warning flags were supported])])
+WARN_CFLAGS="$libdrm_cv_warn_cflags"
+
+if test "x$UDEV" = xyes; then
+ AC_DEFINE(UDEV, 1, [Have UDEV support])
+fi
+
+AC_CANONICAL_HOST
+if test "x$LIBKMS" = xauto ; then
+ case $host_os in
+ linux*) LIBKMS="yes" ;;
+ *) LIBKMS="no" ;;
+ esac
+fi
+
+AM_CONDITIONAL(HAVE_LIBKMS, [test "x$LIBKMS" = xyes])
+
+AM_CONDITIONAL(HAVE_VMWGFX, [test "x$VMWGFX" = xyes])
+if test "x$VMWGFX" = xyes; then
+ AC_DEFINE(HAVE_VMWGFX, 1, [Have vmwgfx kernel headers])
+fi
+
+AM_CONDITIONAL(HAVE_NOUVEAU, [test "x$NOUVEAU" = xyes])
+if test "x$NOUVEAU" = xyes; then
+ AC_DEFINE(HAVE_NOUVEAU, 1, [Have nouveau (nvidia) support])
+fi
+
+AM_CONDITIONAL(HAVE_OMAP, [test "x$OMAP" = xyes])
+if test "x$OMAP" = xyes; then
+ AC_DEFINE(HAVE_OMAP, 1, [Have OMAP support])
+fi
+
+AM_CONDITIONAL(HAVE_EXYNOS, [test "x$EXYNOS" = xyes])
+if test "x$EXYNOS" = xyes; then
+ AC_DEFINE(HAVE_EXYNOS, 1, [Have EXYNOS support])
+fi
+
+PKG_CHECK_MODULES(CAIRO, cairo, [HAVE_CAIRO=yes], [HAVE_CAIRO=no])
+if test "x$HAVE_CAIRO" = xyes; then
+ AC_DEFINE(HAVE_CAIRO, 1, [Have cairo support])
+fi
+AM_CONDITIONAL(HAVE_CAIRO, [test "x$HAVE_CAIRO" = xyes])
+
+# For enumerating devices in test case
+PKG_CHECK_MODULES(LIBUDEV, libudev, [HAVE_LIBUDEV=yes], [HAVE_LIBUDEV=no])
+if test "x$HAVE_LIBUDEV" = xyes; then
+ AC_DEFINE(HAVE_LIBUDEV, 1, [Have libudev support])
+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
+ # Check for atomic intrinsics
+ AC_CACHE_CHECK([for native atomic primitives], drm_cv_atomic_primitives,
+ [
+ drm_cv_atomic_primitives="none"
+
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+ int atomic_add(int i) { return __sync_fetch_and_add (&i, 1); }
+ int atomic_cmpxchg(int i, int j, int k) { return __sync_val_compare_and_swap (&i, j, k); }
+ ]],[[]])],
+ [drm_cv_atomic_primitives="Intel"],[])
+
+ if test "x$drm_cv_atomic_primitives" = "xnone"; then
+ AC_CHECK_HEADER([atomic_ops.h], drm_cv_atomic_primitives="libatomic-ops")
+ fi
+
+ # atomic functions defined in <atomic.h> & libc on Solaris
+ if test "x$drm_cv_atomic_primitives" = "xnone"; then
+ AC_CHECK_FUNC([atomic_cas_uint],
+ drm_cv_atomic_primitives="Solaris")
+ fi
+
+ ])
+ if test "x$drm_cv_atomic_primitives" = xIntel; then
+ AC_DEFINE(HAVE_LIBDRM_ATOMIC_PRIMITIVES, 1,
+ [Enable if your compiler supports the Intel __sync_* atomic primitives])
+ fi
+ if test "x$drm_cv_atomic_primitives" = "xlibatomic-ops"; then
+ AC_DEFINE(HAVE_LIB_ATOMIC_OPS, 1, [Enable if you have libatomic-ops-dev installed])
+ fi
+
+ if test "x$drm_cv_atomic_primitives" = "xnone"; then
+ if test "x$INTEL" != "xauto"; then
+ if test "x$INTEL" != "xno"; then
+ AC_MSG_ERROR([libdrm_intel depends upon atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package, or, failing both of those, disable support for Intel GPUs by passing --disable-intel to ./configure])
+ fi
+ else
+ AC_MSG_WARN([Disabling libdrm_intel. It depends on atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package.])
+ INTEL=no
+ fi
+ if test "x$RADEON" != "xauto"; then
+ if test "x$RADEON" != "xno"; then
+ AC_MSG_ERROR([libdrm_radeon depends upon atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package, or, failing both of those, disable support for Radeon support by passing --disable-radeon to ./configure])
+ fi
+ else
+ AC_MSG_WARN([Disabling libdrm_radeon. It depends on atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package.])
+ RADEON=no
+ fi
+ if test "x$NOUVEAU" != "xauto"; then
+ if test "x$NOUVEAU" != "xno"; then
+ AC_MSG_ERROR([libdrm_nouveau depends upon atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package, or, failing both of those, disable support for NVIDIA GPUs by passing --disable-nouveau to ./configure])
+ fi
+ else
+ AC_MSG_WARN([Disabling libdrm_nouveau. It depends on atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package.])
+ NOUVEAU=no
+ fi
+ else
+ if test "x$INTEL" != "xno"; then
+ case $host_cpu in
+ i?86|x86_64) INTEL=yes ;;
+ *) INTEL=no ;;
+ esac
+ fi
+ if test "x$RADEON" != "xno"; then
+ RADEON=yes
+ fi
+ if test "x$NOUVEAU" != "xno"; then
+ NOUVEAU=yes
+ fi
+ fi
+fi
+
+if test "x$INTEL" != "xno"; then
+ PKG_CHECK_MODULES(PCIACCESS, [pciaccess >= 0.10])
+fi
+AC_SUBST(PCIACCESS_CFLAGS)
+AC_SUBST(PCIACCESS_LIBS)
+
+PKG_CHECK_MODULES(VALGRIND, [valgrind], [have_valgrind=yes], [have_valgrind=no])
+if test "x$have_valgrind" = "xyes"; then
+ AC_DEFINE([HAVE_VALGRIND], 1, [Use valgrind intrinsics to suppress false warnings])
+fi
+
+AM_CONDITIONAL(HAVE_INTEL, [test "x$INTEL" != "xno"])
+AM_CONDITIONAL(HAVE_RADEON, [test "x$RADEON" != "xno"])
+AM_CONDITIONAL(HAVE_NOUVEAU, [test "x$NOUVEAU" != "xno"])
+if test "x$RADEON" = xyes; then
+ AC_DEFINE(HAVE_RADEON, 1, [Have radeon support])
+fi
+
+AC_ARG_WITH([kernel-source],
+ [AS_HELP_STRING([--with-kernel-source],
+ [specify path to linux kernel source])],
+ [kernel_source="$with_kernel_source"])
+AC_SUBST(kernel_source)
+
+AC_SUBST(WARN_CFLAGS)
+AC_CONFIG_FILES([
+ Makefile
+ libkms/Makefile
+ libkms/libkms.pc
+ intel/Makefile
+ intel/libdrm_intel.pc
+ radeon/Makefile
+ radeon/libdrm_radeon.pc
+ nouveau/Makefile
+ nouveau/libdrm_nouveau.pc
+ omap/Makefile
+ omap/libdrm_omap.pc
+ exynos/Makefile
+ exynos/libdrm_exynos.pc
+ tests/Makefile
+ tests/modeprint/Makefile
+ tests/modetest/Makefile
+ tests/kmstest/Makefile
+ tests/radeon/Makefile
+ tests/vbltest/Makefile
+ include/Makefile
+ include/drm/Makefile
+ libdrm.pc])
+AC_OUTPUT
+
+echo ""
+echo "$PACKAGE_STRING will be compiled with:"
+echo ""
+echo " libkms $LIBKMS"
+echo " Intel API $INTEL"
+echo " vmwgfx API $VMWGFX"
+echo " Radeon API $RADEON"
+echo " Nouveau API $NOUVEAU"
+echo " OMAP API $OMAP"
+echo " EXYNOS API $EXYNOS"
+echo ""
diff --git a/configure.ac.rej b/configure.ac.rej
new file mode 100644
index 00000000..c0d07388
--- /dev/null
+++ b/configure.ac.rej
@@ -0,0 +1,11 @@
+--- configure.ac
++++ configure.ac
+@@ -228,7 +242,7 @@
+ fi
+ AM_CONDITIONAL(HAVE_LIBUDEV, [test "x$HAVE_LIBUDEV" = xyes])
+
+-if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno"; then
++if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno" -o "x$SLP" != "xno"; then
+ # Check for atomic intrinsics
+ AC_CACHE_CHECK([for native atomic primitives], drm_cv_atomic_primitives,
+ [
diff --git a/libkms/Makefile.am b/libkms/Makefile.am
index 215450ac..360e4940 100644
--- a/libkms/Makefile.am
+++ b/libkms/Makefile.am
@@ -19,6 +19,11 @@ libkms_la_SOURCES = \
dumb.c \
api.c
+if HAVE_SLP
+libkms_la_SOURCES += slp.c
+AM_CFLAGS += -I$(top_srcdir)/exynos
+endif
+
if HAVE_VMWGFX
libkms_la_SOURCES += vmwgfx.c
endif
diff --git a/libkms/slp.c b/libkms/slp.c
new file mode 100644
index 00000000..263f2ab9
--- /dev/null
+++ b/libkms/slp.c
@@ -0,0 +1,222 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., 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 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
+ * 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.
+ *
+ **************************************************************************/
+
+
+#define HAVE_STDINT_H
+#define _FILE_OFFSET_BITS 64
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "internal.h"
+
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include "xf86drm.h"
+
+#include "exynos_drm.h"
+
+struct slp_bo
+{
+ struct kms_bo base;
+ unsigned map_count;
+};
+
+static int
+slp_get_prop(struct kms_driver *kms, unsigned key, unsigned *out)
+{
+ switch (key) {
+ case KMS_BO_TYPE:
+ *out = KMS_BO_TYPE_SCANOUT_X8R8G8B8 | KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int
+slp_destroy(struct kms_driver *kms)
+{
+ free(kms);
+ return 0;
+}
+
+static int
+slp_bo_create(struct kms_driver *kms,
+ const unsigned width, const unsigned height,
+ const enum kms_bo_type type, const unsigned *attr,
+ struct kms_bo **out)
+{
+ struct drm_exynos_gem_create arg;
+ unsigned size, pitch;
+ struct slp_bo *bo;
+ int i, ret;
+
+ for (i = 0; attr[i]; i += 2) {
+ switch (attr[i]) {
+ case KMS_WIDTH:
+ case KMS_HEIGHT:
+ case KMS_BO_TYPE:
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ bo = calloc(1, sizeof(*bo));
+ if (!bo)
+ return -ENOMEM;
+
+ if (type == KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8) {
+ pitch = 64 * 4;
+ size = 64 * 64 * 4;
+ } else if (type == KMS_BO_TYPE_SCANOUT_X8R8G8B8) {
+ pitch = width * 4;
+ pitch = (pitch + 512 - 1) & ~(512 - 1);
+ size = pitch * ((height + 4 - 1) & ~(4 - 1));
+ } else {
+ return -EINVAL;
+ }
+
+ memset(&arg, 0, sizeof(arg));
+ arg.size = size;
+
+ ret = drmCommandWriteRead(kms->fd, DRM_EXYNOS_GEM_CREATE, &arg, sizeof(arg));
+ if (ret)
+ goto err_free;
+
+ bo->base.kms = kms;
+ bo->base.handle = arg.handle;
+ bo->base.size = size;
+ bo->base.pitch = pitch;
+
+ *out = &bo->base;
+
+ return 0;
+
+err_free:
+ free(bo);
+ return ret;
+}
+
+static int
+slp_bo_get_prop(struct kms_bo *bo, unsigned key, unsigned *out)
+{
+ switch (key) {
+ default:
+ return -EINVAL;
+ }
+}
+
+static int
+slp_bo_map(struct kms_bo *_bo, void **out)
+{
+ struct slp_bo *bo = (struct slp_bo *)_bo;
+ struct drm_exynos_gem_map_off arg;
+ void *map = NULL;
+ int ret;
+
+ if (bo->base.ptr) {
+ bo->map_count++;
+ *out = bo->base.ptr;
+ return 0;
+ }
+
+ memset(&arg, 0, sizeof(arg));
+ arg.handle = bo->base.handle;
+
+ ret = drmCommandWriteRead(bo->base.kms->fd, DRM_EXYNOS_GEM_MAP_OFFSET, &arg, sizeof(arg));
+ if (ret)
+ return ret;
+
+ map = mmap(0, bo->base.size, PROT_READ | PROT_WRITE, MAP_SHARED, bo->base.kms->fd, arg.offset);
+ if (map == MAP_FAILED)
+ return -errno;
+
+ bo->base.ptr = map;
+ bo->map_count++;
+ *out = bo->base.ptr;
+
+ return 0;
+}
+
+static int
+slp_bo_unmap(struct kms_bo *_bo)
+{
+ struct slp_bo *bo = (struct slp_bo *)_bo;
+ bo->map_count--;
+ return 0;
+}
+
+static int
+slp_bo_destroy(struct kms_bo *_bo)
+{
+ struct slp_bo *bo = (struct slp_bo *)_bo;
+ struct drm_gem_close arg;
+ int ret;
+
+ if (bo->base.ptr) {
+ /* XXX Sanity check map_count */
+ munmap(bo->base.ptr, bo->base.size);
+ bo->base.ptr = NULL;
+ }
+
+ memset(&arg, 0, sizeof(arg));
+ arg.handle = bo->base.handle;
+
+ ret = drmIoctl(bo->base.kms->fd, DRM_IOCTL_GEM_CLOSE, &arg);
+ if (ret)
+ return -errno;
+
+ free(bo);
+ return 0;
+}
+
+int
+slp_create(int fd, struct kms_driver **out)
+{
+ struct kms_driver *kms;
+
+ kms = calloc(1, sizeof(*kms));
+ if (!kms)
+ return -ENOMEM;
+
+ kms->fd = fd;
+
+ kms->bo_create = slp_bo_create;
+ kms->bo_map = slp_bo_map;
+ kms->bo_unmap = slp_bo_unmap;
+ kms->bo_get_prop = slp_bo_get_prop;
+ kms->bo_destroy = slp_bo_destroy;
+ kms->get_prop = slp_get_prop;
+ kms->destroy = slp_destroy;
+ *out = kms;
+
+ return 0;
+}
diff --git a/slp/Makefile.am b/slp/Makefile.am
new file mode 100644
index 00000000..132662b6
--- /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 00000000..f723ded8
--- /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 <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
index 00000000..a4adef57
--- /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 <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
index 00000000..220d38be
--- /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 00000000..e967b93c
--- /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 <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_*/