diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-11-13 07:04:27 -0800 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2013-02-11 08:02:22 -0800 |
commit | 39108458cb8912b6122b9e0ff77053c6f7f2a79b (patch) | |
tree | 08e8dc77405aeb0621cdf3b54939fab7e47f27cd | |
parent | aef270ee6488bea9666e124c1be014dcd4ff539a (diff) | |
download | libdrm-39108458cb8912b6122b9e0ff77053c6f7f2a79b.tar.gz libdrm-39108458cb8912b6122b9e0ff77053c6f7f2a79b.tar.bz2 libdrm-39108458cb8912b6122b9e0ff77053c6f7f2a79b.zip |
Support SLP
-rw-r--r-- | Makefile.am | 6 | ||||
-rw-r--r-- | configure.ac | 20 | ||||
-rw-r--r-- | configure.ac.orig | 349 | ||||
-rw-r--r-- | configure.ac.rej | 11 | ||||
-rw-r--r-- | libkms/Makefile.am | 5 | ||||
-rw-r--r-- | libkms/slp.c | 222 | ||||
-rw-r--r-- | slp/Makefile.am | 22 | ||||
-rw-r--r-- | slp/drm_slp_bufmgr.c | 847 | ||||
-rw-r--r-- | slp/drm_slp_bufmgr.h | 201 | ||||
-rw-r--r-- | slp/libdrm_slp.pc.in | 11 | ||||
-rw-r--r-- | slp/list.h | 131 |
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_*/ |